2

I am getting really worried -- as i really need to recover my Ubuntu --, and have wasted so much time on trying to fix this.

Basically, I was just following a lab for my security class and encountered this problem.

OK so I followed these commands:

cd /bin
rm sh
ln -s /bin/zsh /bin/sh

Then when i opened a new terminal then it gave some sort of error. So, i thought this would go away after restarting my system.

But, to my misfortune my system could never load again.

First it opens the grub2 boot manager then when i hit enter on Ubuntu it loads into a black screen with blinking cursor at the top-left.

I have a lot of my work and all my programming environment for work and school in this system.

Thomas Ward
  • 74,764
thesas
  • 23
  • 1
  • 3
  • 1
    You can always load a LiveUSB and mount your partition to recover data... that way you can recover the data. – Thomas Ward Oct 02 '14 at 22:22
  • Yes, Eliah you are right. I didn't had zsh installed. But, I was just curious if it was already there. Also, it didn't showed be any error while i tried that zsh linking command. So, i thought it was working. And that was the source of all evil. – thesas Oct 03 '14 at 02:00
  • Yeah, it is somewhat nonintuitive that creating a broken symlink succeeds silently. – Eliah Kagan Oct 03 '14 at 05:00

2 Answers2

2

I don't think that that would cause you to be unable to boot but you could revert to your old sh by doing this since /bin/sh is just a symbolic link to /bin/dash anyway...

Boot until you get the blinking cursor then press Ctrl+Alt+F2 to get a terminal then do

cd /bin
sudo rm sh           # if this fails then just go to next
sudo ln -s dash sh

Then you can reboot (sudo reboot)

Edit: For anyone in the future, if you can't access the shell prompt at boot by pressing Ctrl+Alt+F2, you can do one of the following:

Option 1: Boot a live cd and press try then open the terminal and do

sudo mount /dev/sda1 /mnt   #replace sda1 with whatever drive/partition your install is on
cd /mnt/bin
sudo rm sh           #if this fails then just go to next
sudo ln -s dash sh

Option 2: Boot a live cd and press try then open the terminal there and do

sudo mount /dev/sda1 /mnt   #replace sda1 with whatever drive/partition your install is on
sudo chroot /mnt
cd /bin
rm sh           # if this fails then just go to next
ln -s dash sh

Then you can reboot (sudo reboot)

That should revert to the default sh folder.

source: https://askubuntu.com/a/135219/333886

Termhn
  • 401
  • 2
  • 7
  • The terminal wouldn't open from that screen. I had to go inside a USB ubuntu and press CTR+ALT+F1. Then, used -sudo mount /dev/sda1 /mnt- and -sudo chroot /mnt- to go to the root user. After, that I exactly followed your instruction -- except that rm sh was giving me no sh found -- then rebooted my pc and it worked. You saved my life. Thank You so much. – thesas Oct 02 '14 at 23:04
  • Glad I could help. Seeing as it couldn't find sh I think your original symlink to /bin/zsh failed. – Termhn Oct 02 '14 at 23:12
  • Added to answer – Termhn Oct 02 '14 at 23:47
2

It's not surprising that making /bin/sh a symlink to /bin/zsh caused problems, since /bin/zsh often doesn't exist. I suspect zsh Install zsh wasn't installed and that's why things broke. This seems especially likely2 if the error you saw on the new terminal was:

bash: /usr/bin/lesspipe: /bin/sh: bad interpreter: No such file or directory

Making /bin/sh a link to dash again (as it is by default on Ubuntu) is usually the appropriate solution--and in your case, as your goal is to restore your system to the way it was before, it is definitely the correct way. It can be achieved by booting from live media, as presented in Termhn's excellent answer1, and in other ways.

But if for some bizarre reason you did want to use zsh instead of dash for /bin/sh in Ubuntu, this can be achieved--but not quite the way you attempted it.

Restoring shdash Without a Live Environment

I think using a live CD/DVD/USB is the overall best solution to this problem, because it's less technical than other ways and is very likely to succeed without problems.

But in case you want to fix this just by booting from the hard disk, you can.

This is somewhat less long and complicated than it might seem at first glance, as a good bit of length is due to (a) presenting two alternatives, and (b) the screenshots.

First, shut down or reboot cleanly (if you can).

This applies to all solutions, not just those that attempt to fix the problem while still booting from the internal hard drive. But it's probably not a big problem if you didn't do this.

Depending on how badly broken things are, Ctrl+Alt+Delete might not successfully shut down and reboot your Ubuntu system. (Ordinarily it does that, if pressed when in a text-based virtual console.)

If Ctrl+Alt+Delete doesn't work, use:

  • Alt+SysRq+REISUB to reBoot, or
  • Alt+SysRq+REISUO to power Off.

Since problems caused by a missing /bin/sh shouldn't cause failures deep in the kernel, I think these "magic SysRq" techniques will always work in this situation.

init=/bin/dash Should Work

  1. Hold down Shift while booting to get a GRUB menu.

    enter image description here
    It should very generally resemble this screenshot, but may be expected to look different depending on which Ubuntu flavor and release you're running.

  2. "Ubuntu" is selected by default. Keep that selection, but press e to edit it.
    (Don't worry, your edit is just for this boot, and will not be saved.)

  3. Move to the end of the line that beginning linux /boot/vmlinuz-.... (You can use the arrow keys, and End to get to the end of the line.)

    enter image description here

    Type a space, then init=/bin/dash. Then press F10 to boot this configuration.

    Source: How to set NOMODESET and other kernel boot options in grub2

  4. You should see:

    /bin/dash: 0: can't access tty: job control turned off
    #
    

    This is a root shell.

  5. Remount the root filesystem readwrite so you can make changes to files on disk:

    mount -o remount,rw /
    

    This command, and the ones that follow it, will (usually) not produce any output when they succeed. That's okay.

  6. Make /bin/sh a symlink to dash instead of zsh:

    cd /bin
    rm sh
    ln -s dash sh
    
  7. If you like, you can check that the sh symlink has been properly retargeted by running ls -l sh, which should show something like:

    lrwxrwxrwx 1 root root 4 Oct  2 23:13 sh -> dash
    

    (sh -> dash is the key part.)

  8. Restart with reboot -f. Your system should be fixed.

Alternative way: Recovery mode might work. Maybe.

It may be possible for recovery mode to function without sh. I haven't gotten this to work myself and don't actually know if it ever does--I got Ubuntu to boot normally (without a GUI) with sh as a broken symlink, but that stopped working for me before I tried recovery mode (which didn't work for me either).

For a more reliable way, go back up to init=/bin/dash Should Work. (Note that recovery mode is not at all unreliable in general, it just can't be expected to work without /bin/sh.)

If you want to attempt recovery mode:

  1. To enter recovery mode, hold down Shift during boot to get a GRUB menu.

  2. Select Advanced options for Ubuntu.

  3. In the menu of available kernels, press to move the selection to an entry ending in (recovery mode), and press Enter.

    enter image description here

  4. If it doesn't work, you can reboot with "magic SysRq" as detailed above. If it does work, you'll see the Recovery Menu.

  5. In the Recovery Menu, press repeatedly until

    root              Drop to root shell prompt
    

    is selected. Press Enter.

    enter image description here

  6. Perform steps 5 and 6 (and optional step 7, if you like) from the init=/bin/dash Should Work method above.

  7. Run reboot to restart.

    You could probably run exit, then select Resume. But I suggest rebooting instead, so the system can boot cleanly with an accessible and functioning sh from the very start. (If you managed to get into recovery mode with sh as a broken symlink, that still doesn't mean everything worked just right along the way.)


If you're interested in making zsh provide sh (either for real, or just theoretically), read on.

Problems With The shzsh Procedure You Attempted

As a general procedure, cd /bin; rm sh; ln -s /bin/zsh /bin/sh (as prescribed in your lab exercise) is bad advice for at least two reasons:

  1. /bin/zsh sometimes doesn't exist even if zsh is installed. This depends on how it was installed and what OS is being used. zsh is a large, complex shell that's not very frequently used as /bin/sh and thus ordinarily doesn't need to be accessible in single-user mode or otherwise before a separate /usr partition might be mounted. Executables not needed in single-user mode are usually located in subdirectories of /usr.

    Ubuntu's zsh does provide /bin/sh. But on other systems it may be /usr/bin/zsh or even /usr/local/bin/sh (as on my FreeBSD system where I have it installed via pkg).

  2. The motivation behind this exercise may have been to harden a system against "Shellshock" (or other possible parsing bugs arising from the way bash accepts shell functions passed in environment variables). But it is not a widely appropriate course of action for this purpose.

    Although many GNU/Linux systems, such as Fedora, RHEL, and Slackware, have bash provide /bin/sh, in many others some other shell provides /bin/sh. This includes Ubuntu, which uses dash. Like zsh, dash is not vulnerable to "Shellshock" and does not import function definitions from environment variables (or at all) using any mechanism, so no similar bug is likely to affect it.

So depending on context, this exercise as it was presented to you might have been flawed. You might want to discuss the matter with your professor. Perhaps the curriculum, or the way in which it is conveyed, could be improved.

Depending (even more heavily) on context, these considerations may also be causes for concern:

  1. Often, sh is a symbolic link, hard link, or copy of another shell that is installed. But on some systems, particularly some Unix-like systems that are not GNU/Linux systems, sh might be a separate executable from anything else. Except when this is known not to be the case, it's a good idea to check before rming it! mving might be more appropriate in that case.

  2. Exercises that alter a system's configuration, particular those that require running commands as root to perform unusual actions, should not typically be performed on production machines. Experimentation and exploration are both practically necessary and intrinsically valuable. But when they may involve breaking things, they are best carried out on installations whose continued functioning is not essential to important work that needs to get done.

    In other words, it's good to test things out before deploying them "for real." (Virtual machines are often good for this.)

Ubuntu's zsh Install zsh does provide a copy of the shell3 in /bin as well as /usr/bin. But by default in Ubuntu, zsh is not installed at all.

Symbolic links don't require their targets to exist:

ek@Ilex:~$ rm foo
rm: cannot remove ‘foo’: No such file or directory
ek@Ilex:~$ ln -s foo bar
ek@Ilex:~$ ls -l foo bar
ls: cannot access foo: No such file or directory
lrwxrwxrwx 1 ek ek 3 Oct  2 20:25 bar -> foo
ek@Ilex:~$ file bar
bar: broken symbolic link to `foo'

Since /bin/sh is the interpreter for many important scripts used to boot the system and perform other tasks, it needs to exist. Making it a broken link will render an Ubuntu system non-functioning.

Getting zsh to Provide /bin/sh

Ubuntu is designed to use dash for sh, and is not developed or tested with zsh as sh in mind. Please don't attempt this on a system you need for critical tasks. This is strictly for education/fun, and should be done in a non-critical virtual machine or other non-critical system.2

  1. Install zsh Install zsh; by default in Ubuntu, it is not installed.

    sudo apt-get update
    sudo apt-get install zsh
    
  2. Point sh at zsh instead of dash by running cd /bin; rm sh; ln -s /bin/zsh /bin/sh (as you did).

  3. Verify sh is a good link to zsh by running file sh (or if you're no longer in /bin, use file /bin/sh).

    You should see sh: symbolic link to `zsh' (or /bin/sh: symbolic link to `zsh').

  4. Reboot and see if Ubuntu still works.


Notes

  1. And apparently also, at least sometimes, from a text-based virtual console, also as explained in Termhn's answer. This worked for me one of the times I tested it2, but failed another time I tested it. And I know it did not work for you. (In contrast, the live CD method is very reliable.)
  2. Testing for this answer was performed on a 64-bit Ubuntu Mate 14.10 Utopic Unicorn (beta) system running in a VirtualBox virtual machine. (Not because there's anything about that configuration that best models this problem, but just because that was the desktop Ubuntu system I had on hand for testing.) That something worked for me does not guarantee it will work for you, even on the same version of Ubuntu.
  3. On Ubuntu, /bin/zsh is usually a symlink to /etc/alternatives/zsh which is usually a symlink to /bin/zsh5 (which is the actual Z Shell executable). But since both /bin and /etc are located on the root filesystem even when /usr is mounted over a network or otherwise on a separate volume, this is fine.
Eliah Kagan
  • 117,780