1 | --- |
2 | type: none |
3 | identifier: recover-linux-shell |
4 | title: Recovering a Linux desktop with a misconfigured shell |
5 | description: How to fix a custom shell when your terminal can't open. |
6 | datestring: 2022-11-10 |
7 | banner_image: /static/images/esp32.jpg |
8 | links: |
9 | chsh: https://man7.org/linux/man-pages/man1/chsh.1.html |
10 | xonsh: https://xon.sh/ |
11 | Virtual consoles: https://www.wikiwand.com/en/Virtual_console |
12 | /etc/passwd: https://man7.org/linux/man-pages/man5/passwd.5.html |
13 | --- |
14 |
|
15 | Suppose you’ve used the `chsh` command to change your login shell in the past |
16 | and something has gone wrong to the point that your custom shell executable is |
17 | nonexistent or no longer functions properly. Opening a new terminal results in |
18 | the window closing immediately following a fatal error, or you can’t log in to |
19 | your desktop entirely. For me, this happened with `xonsh` (a great amalgam of |
20 | Python and Bash) when upgrading between Ubuntu versions, as the installed |
21 | Python library fell out of the system path. There are a few methods, however, |
22 | to regain access to a functioning shell. |
23 |
|
24 | # Gaining access to a functioning shell |
25 |
|
26 | ## Method 1(a): Application launching |
27 |
|
28 | This method assumes the following: |
29 |
|
30 | - You are still signed in to your semi-functioning desktop environment (DE) |
31 | - You have a functioning terminal emulator and shell installed on your system |
32 | - Your DE offers application launching |
33 |
|
34 | This one is pretty self-explanatory. Terminal emulators can be fed command-line |
35 | arguments to skip shell loading entirely and perform direct file execution. You |
36 | can use this option to load a shell other than your user’s default shell, as |
37 | shells are just executable files. Here are some example commands to load Bash |
38 | with different terminals, bypassing your login shell: |
39 |
|
40 | ```bash |
41 | xterm -e /usr/bin/env bash |
42 | xfce4-terminal -e /usr/bin/env bash |
43 | gnome-terminal -- /usr/bin/env bash |
44 | ``` |
45 |
|
46 | If your DE offers application launching, you can execute the appropriate |
47 | command for your terminal emulator and (functional) shell of choice. The |
48 | shortcut for application launching on Gnome and XFCE is `<Alt><F2>`. On KDE, |
49 | it’s `<Alt><F1>`, and on i3, which uses dmenu, it’s `<Ctrl>D`. For other |
50 | desktop environments with application launchers, check which you should use in |
51 | the related documentation. |
52 |
|
53 | ## Method 1(b): GUI-based file execution |
54 |
|
55 | This is an alternative method to 1(a), assuming: |
56 |
|
57 | - You are still signed in to your semi-functioning desktop environment (DE) |
58 | - Your DE *does not* have application launching, or it doesn’t work for some |
59 | reason |
60 | - You have a functioning terminal emulator and shell installed on your system |
61 | - Your GUI file browser offers direct file execution without terminal |
62 |
|
63 | Essentially, you create a file like the following, using the appropriate |
64 | terminal emulator and shell: |
65 |
|
66 | ```bash |
67 | #!/usr/bin/env bash |
68 | gnome-terminal -- /bin/bash |
69 | ``` |
70 |
|
71 | Using your file browser, give this file permission for user execution and run |
72 | it. |
73 |
|
74 | ## Method 2: Use another user with a functioning login shell |
75 |
|
76 | This method assumes: |
77 |
|
78 | - There is a separate user on your system that can be logged into via password |
79 | that uses a functioning login shell |
80 | - The user is a member of the sudo group |
81 |
|
82 | Open a virtual console (usually with `<CTRL><ALT><F1..F9>`) and log in as the |
83 | separate user. Then, you can take the necessary actions to fix your broken |
84 | login shell or other configuration. (On my systems I create a sudoer named |
85 | `bash-user` whose sole purpose is to be password-login-able with Bash as its |
86 | login shell.) |
87 |
|
88 | If you don’t have this option, then… |
89 |
|
90 | ## Method 3: Externally mount the filesystem and forcibly change the default login shell |
91 |
|
92 | This is the most involved and complicated method, meant to be used as a last |
93 | resort if you don’t feel like reimaging your system (or living without a |
94 | terminal). You will need to find a way to externally mount the filesystem from |
95 | another functioning operating system and change the `/etc/passwd` file |
96 | directly. |
97 |
|
98 | For desktops without any other operating systems installed, my go-to method |
99 | looks roughly like this: |
100 |
|
101 | 1. Create a live USB bootable Linux distribution on a flash drive |
102 | (Linux-on-a-stick) |
103 | 2. UEFI boot into this Linux-on-a-stick |
104 | 3. Force mount the hard drive your Linux system is on, with sufficient |
105 | read-write permissions *(Look for external help on this, so as to not break |
106 | your filesystem or mess up permissions)* |
107 |
|
108 | The full details of this method are a bit out of the scope of this article, so |
109 | I’ll let you figure them out with the help of Google and StackOverflow. Having |
110 | a bootable Linux-on-a-stick is also useful for other reasons, so if you don’t |
111 | have one, I do recommend setting one up and using the steps outlined above. |
112 |
|
113 | Once your filesystem is mounted and you have sufficient read/write permissions, |
114 | you can do one of the following: |
115 |
|
116 | - Directly change `/etc/passwd` to reflect a working login shell for your user |
117 | - Through the external operating system, take the necessary actions to fix your |
118 | broken login shell (not recommended) |
119 |
|
120 | After completing this, you should be able to log into your system as normal. |
121 |
|
122 | # Fixing your custom shell |
123 |
|
124 | This will vary widely depending on your setup and the shell you’re trying to |
125 | fix, so unfortunately I can’t cover that extensively here. In my case, for |
126 | fixing `xonsh`, I just had to reinstall it via Python’s package manager with |
127 | this command: |
128 |
|
129 | ```bash |
130 | $ sudo python3 -m pip install 'xonsh[full]' |
131 | ``` |
132 |
|
133 | Your process for fixing your broken shell will likely be a similar process of |
134 | reinstallation or reconfiguration via `chsh`. |
135 |
|