65

I accidentally renamed the directory /usr into /usr_bak.

I want to change it back, so I append the path /usr_bak/bin to $PATH to allow the system to find the command sudo.

But now sudo mv /usr_bak /usr gives me the error:

sudo: error while loading shared libraries: libsudo_util.so.0: cannot open shared object file: No such file or directory

Is there a way to rename the /usr_bak as /usr besides reinstalling the system?

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
Yves
  • 3,291
  • 2
    Which OS is this? I wonder how sudo even got to library stage, it's usually in /usr/bin/ and should have failed with a command-not-found error. Also, do you have a root password set? – muru Mar 19 '18 at 03:24
  • 3
    @muru It's Ubuntu. You are right, I did get the error about not found before so I appended the new path /usr_bak/bin to $PATH and now I get the error in my post here... – Yves Mar 19 '18 at 03:27
  • And do you have a root password set? – muru Mar 19 '18 at 03:30
  • 1
    @muru Yes, I have. – Yves Mar 19 '18 at 03:31
  • What's your Ubuntu release? In my installation ldd /usr/bin/sudo only shows shared libraries outside of /usr. – David Foerster Mar 19 '18 at 14:47
  • @DavidFoerster at least on 16.04 there's a single library needed from /usr (libsudo_util.so.0 => /usr/lib/sudo/libsudo_util.so.0 (0x00007faf9855d000)) – muru Mar 19 '18 at 15:04
  • @DavidFoerster Ubuntu 16.04 and Ubuntu 17.10 – Yves Mar 19 '18 at 17:51
  • 2
    @user1717828 it's complicated. I have to compile a project, developed on Ubuntu 16.04, on Ubuntu 17.10. So I'm thinking if I can simply copy the /usr of Ubuntu 16.04 to overwrite the /usr of Ubuntu 17.10... – Yves Mar 19 '18 at 17:55
  • 6
    Have you considered using a VM to compile the project instead of such drastic changes? – Kevin Mar 19 '18 at 23:50
  • @Kevin My working environment is totally linux without desktop. I have only used VM in Windows, if there is a way to use VM in linux without desktop, I will really appreciate if you tell me. – Yves Mar 20 '18 at 01:11
  • 3
    You can run virtualbox in headless mode. It may be easiest to set up a guest on another machine, or get a pre-configured one. – Kevin Mar 20 '18 at 01:47
  • @Yves For example a virtual box image from here or the iso (server one maybe) from the official server... – Hastur Mar 20 '18 at 07:25
  • all the VMs have the ability to run without a desktop environment, like qemu -nographic or pref.vmplayer.exit.vmAction = "disconnect" – phuclv Mar 21 '18 at 03:00
  • @LưuVĩnhPhúc dude, if you know about qemu, could you please help me here: https://unix.stackexchange.com/questions/432470/how-to-use-qemu-without-desktop – Yves Mar 21 '18 at 03:17
  • @Kevin (and Yves): you don't need a whole VM to build packages for another version of Ubuntu, because you don't need security isolation. The easiest and most efficient way is with a chroot. Debian/Ubuntu already have good support for setting up (https://help.ubuntu.com/community/DebootstrapChroot) and using (with schroot) an alternate distro version inside a chroot. IIRC, there's maybe some integration with package build scripts. – Peter Cordes Mar 21 '18 at 10:35
  • And BTW, if you'd used sudo -s to get a root shell before temporarily breaking your system, I think you could have run /bin/mv, or even used LD_LIBRARY_PATH=/usr_bak/lib to run /usr_bak/bin/whatever foo bar. But LD_LIBRARY_PATH doesn't apply to setuid executables, so that only worksif you have a root shell already or can log in to one on a text console or whatever.) – Peter Cordes Mar 21 '18 at 10:40

5 Answers5

112

Since you have set a password for root, use su and busybox, installed by default in Ubuntu. All of su's required libraries are in /lib. Busybox is a collection of utilities that's statically linked, so missing libraries shouldn't be a problem. Do:

su -c '/bin/busybox mv /usr_bak /usr'

(While Busybox itself also has a su applet, the /bin/busybox binary is not setuid and so doesn't work unless ran as root.)

If you don't have a root password, you could probably use Gilles' solution here using LD_LIBRARY_PATH, or(Gilles says this won't work with setuid binaries like sudo) reboot and edit the GRUB menu to boot with init=/bin/busybox as a kernel parameter and move the folder back.

muru
  • 72,889
  • 77
    Now, don't accidentally rename /lib. – sleblanc Mar 19 '18 at 12:40
  • 2
    @sleblanc lol... Seriously, what if I accidentally rename /lib? Can I use the same method to repair it? – Yves Mar 19 '18 at 18:00
  • 2
    If your /lib is a symlink to /usr/lib, it get's more interesting :) LD_LIBRARY_PATH & PATH to save the day. [or busybox should still work too] – Mark K Cowan Mar 19 '18 at 20:14
  • 5
    LD_LIBRARY_PATH wouldn't help to run sudo since sudo is setuid. If its libraries aren't in the right place, sudo won't work until root repairs it. – Gilles 'SO- stop being evil' Mar 19 '18 at 21:43
  • 3
    @Yves historical note: old flavors of Unix (that are much much older than Linux) included a small collection of statically-linked binaries in /sbin for precisely that kind of scenario: "I'm doing some activity where runtime libraries will be juggled around but need to still manipulate files." Basically the same approach before Busybox was invented. (The number of commands available in this fashion was very limited, because those statically linked binaries gobble up diskspace.) – Ti Strga Mar 19 '18 at 22:30
  • 8
    @Yves if you renamed /lib, then you'd probably have to reboot to init=/bin/busybox – muru Mar 19 '18 at 23:54
  • 4
    @Yves: Boot from a USB stick, with a live distro that can mount your filesystems, and you're all set to fix anything. Even downloading replacement files from package mirrors if you deleted something. – Peter Cordes Mar 20 '18 at 22:55
  • 1
    Regular /bin/mv should work after you su to root; it's dynamically linked, but only against libs in /lib. If you already had a root shell, a statically linked busybox could help you fix /lib if you broke it. But if you need su to work, other stuff in /bin should work, too. – Peter Cordes Mar 21 '18 at 10:47
  • 3
    @TiStrga I'd often wondered what /sbin was... I'd assumed/seen something like "secure" binaries. Now I know it was static binaries. – TripeHound Mar 21 '18 at 16:25
  • This answer saved me from a lot of headache, after naively running mv /usr /usr_corrupt and then failing to run mv /usr_restored /usr. I just had to change it to /usr_restored/bin/busybox mv /usr_restored /usr because apparently these days /bin is just a symlink to /usr/bin. – Bart van Heukelom Jul 07 '23 at 15:31
35

In addition to muru's answer:

  • you could have used some rescue boot USB key to repair your system; e.g. if your system is some Debian or Ubuntu, boot the installation USB key in rescue mode, and do the appropriate mount and mv and umount.

  • to be able to repair more easily such mistakes, I generally also install a static shell with several builtin commands (notably with some cp, rm, mv-like builtins) such as sash (it is packaged in Debian & Ubuntu, and also available as sash-3.8.tar.gz in source form) and boot with init=/bin/sash passed to Grub.

PS: sash is slightly buggy, and not entirely Posix compliant, but still very useful.

5

I think the best safest way is to reboot using a USB, CD or DVD booted OS (Debian, Ubuntu, Suse, etc). Then mount the drive containing the problems and do the rename.

Safer than booting into a minefield with /usr or /lib effectively missing.

Larry
  • 51
  • 1
0

I ran into a similar problem where I renamed /usr/bin to /usr/bin_bkp for some test and then I wasn't able to rename (as the command didn't find the sudo in the standard directory which is /usr/bin) and then I went to the /usr/bin_bkp directory manually (using File manager) and most of the functions (including the rename) on the right click are disabled.

Then I tried the following command and it fixed the issue

$/usr/bin_bkp/sudo mv /usr/bin_bkp/ /usr/bin/

I invoked the sudo from the current path and it worked, now everything's back to normal.

OS: Xubuntu 14.04

Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232
geek
  • 1
-5

I can't try this right now (and am not sure I'd want to), but it seems like it ought to work to create yourself a new "/usr" as a hard link (not a soft link) to your "/usr_bak, then delete the "/usr_bak"

ln /usr_bak /usr
rm /usr_bak

The hard link created by "ln" (with no "-s" argument) in the file system should make both the usr and usr_bak directories equally valid links to the directories in question. "rm" just removes the one link you asked it to remove, not both of them. Since there's still a valid link to the contents, they should remain accessible through the remaining link at "/usr".

T.E.D.
  • 291
  • 1
  • 6
  • I suppose if the "rm" scares you, you could just skip it and leave the "/usr_bak" link there too. Its the "ln" command that gets you your "/usr" directory link back. – T.E.D. Mar 20 '18 at 20:11
  • 6
    I was under the impression that Linux (or at least Ubuntu) does not allow hard links to directories. E.g., https://askubuntu.com/questions/210741/why-are-hard-links-not-allowed-for-directories – Chris Bouchard Mar 20 '18 at 21:03
  • @ChrisBouchard It's not Linux specific. Edit: iirc from years ago it's something to do with cross-filesystems but I'm uncertain of that now; ln(1) doesn't state that specifically so I could be remembering wrong or mixing it up with something similar. – Pryftan Mar 20 '18 at 21:28
  • 4
    @Chris: Right, Linux does not allow directory hardlinks (other than . and .., so the link count on a directory tells you the number of first-level subdirs). Also, rm doesn't work on directories, you'd have to use rmdir. (ln and rm work on symlinks to directories, but we're talking about an actual directory). Also, this doesn't solve the problem, because it requires root just like mv, because of the permissions on /. If you could run this, you could run mv instead like a normal person. – Peter Cordes Mar 20 '18 at 22:59
  • 2
    Hardlinks to directories are not supported on most (all?) Unices because it's too difficult for software doing a recursive file system crawl to detect infinite loops. It's possible if the software keeps track of all inodes visited and it's crawling an inode aware filesystem (i.e. not FAT32/NTFS), but checking for symbolic links and not traversing them is much easier. All that's needed is a quick call to lstat(2) to check file type. – penguin359 Mar 21 '18 at 05:29
  • 2
    @Pryftan, my ln(1) on Debian says this for the the -d/-F/--directory option: "allow the superuser to attempt to hard link directories (note: will probably fail due to system restrictions, even for the superuser)". So you're free to try, but your filesystem probably won't let you. – Toby Speight Mar 21 '18 at 10:35
  • @TobySpeight Yes I know that :) I was saying that it's not Linux specific. My edit is irrelevant to the truth; that is to say that I had a very vague memory about it being cross filesystems and that's what I was referencing - a memory of; on the other hand this could be semantics. Either way I know it can be attempted but then again so can other syscalls (it uses link(2)); e.g. socket(2) even if the process doesn't have authorisation (and/or it's something not supported and/or any other error conditions). – Pryftan Mar 21 '18 at 22:21
  • Sorry, I didn't mean to imply disagreement @Pryftan. Just saying that for a root user it depends on the filesystem type more than on the OS kernel. I think most Unix flavours will attempt the operation for a root user (who is supposed to understand the consequences, such as inconsistent .. entries). Returning to the question, I have serious doubts about the rm command being willing to remove a non-empty directory inode like that - that's what unlink is for. – Toby Speight Mar 22 '18 at 08:20
  • @TobySpeight No worries :) As for your curiosity we can assume that the link syscall works for discussion. Now what happens if you remove a file with more than one reference? Or let's put it another way: if you have two file descriptors in a C program and then the path is unlink() what happens? Well I know from doing C but let the man page say the relevant part: If the name was the last link to a file but any processes still have the file open, the file will remain in existence until the last file descriptor referring to it is closed. 1/2 – Pryftan Mar 24 '18 at 18:07
  • @TobySpeight Okay but what about directories? remove(3) will call rmdir(2) which specifically says this: rmdir() deletes a directory, which must be empty. and in the case it isn't empty it returns ENOTEMPTY or EEXISTS (POSIX.1 allows the latter). (Well, the errno is that value I should say) So you're absolutely correct. 2/2 – Pryftan Mar 24 '18 at 18:09
  • 1
    @TobySpeight Another thought: see also symlink(7) which says: Hard links may not refer to directories (to prevent the possibility of loops within the filesystem tree, which would confuse many programs) and may not refer to files on different filesystems (because inode numbers are not unique across filesystems). This makes me think that the hard link attempt might actually be the way of wording something else that happens namely that the function is called but it fails exactly because it is a directory. (The filesystem reference is what I was thinking of in another comment) – Pryftan Mar 24 '18 at 18:14