merge-usr is a script which may be used to migrate a system from the legacy "split-usr" layout to the newer "merged-usr" layout as well as the "sbin merge". This is often referred to as the "/usr merge" where the /bin, /sbin, /lib, and /lib64 are permanently migrated to the /usr/bin, /usr/sbin, /usr/lib and /usr/lib64 directories respectively. As part of the migration, the former non-/usr directories will then populated with symlinks pointing to the new locations for each of binaries to ensure backwards compatibility.
In addition, the script applies the "sbin merge" at the same time where /sbin and /usr/sbin are both actually merged to /usr/bin.
The underlying motivation for this change is compatibility: in theory this change should allow increased interoperability between Linux distributions. Scripts, especially, should "just work" under the new system and not fail due to binaries being in unexpected locations when run from a Linux distribution other than the one they were written on.
This will soon be required for systemd due to changes upstream but remain optional for other init systems.
Here is an overview of the filesystem before the migration:
tree -L 1
/ ├── bin ├── boot ├── dev ├── etc ├── home ├── lib ├── lib64 ├── lost+found ├── media ├── mnt ├── opt ├── proc ├── root ├── run ├── sbin ├── srv ├── sys ├── tmp ├── usr └── var
In the merged-usr layout, /bin and /lib are symlinks targeted at corresponding directories under the /usr directory.
To perform a migration, install the sys-apps/merge-usr package.
emerge --ask sys-apps/merge-usr
It is recommended to attempt a dry run first to find any conflicts and correct them first which may involve deleting some conflicting files. If in doubt, please seek support in a Gentoo support channel first.
The script may then be run without options as root to perform the actual migration.
Here is an overview of the filesystem after the migration:
tree -L 1
/ ├── bin -> usr/bin ├── boot ├── dev ├── etc ├── home ├── lib -> usr/lib ├── lib64 -> usr/lib64 ├── lost+found ├── media ├── mnt ├── opt ├── proc ├── root ├── run ├── sbin -> usr/bin ├── srv ├── sys ├── tmp ├── usr └── var
Then switch to a merged-usr profile, for example:
eselect profile set default/linux/amd64/17.1/systemd/merged-usr
Finally, complete a world upgrade with --newuse or --changed-use:
emerge -uDN @world
Note that advanced users do not strictly need to use the merged-usr profiles and can instead mask split-usr in /etc/portage/profile/use.mask and set the same UNINSTALL_IGNORE value from the profiles in /etc/portage/make.conf.
Frequently Asked Questions
How does the script work?
For each directory D in (bin, sbin, lib*), the script compares the contents of /D to /usr/D (except /sbin goes to /usr/bin).
For each file or symlink it finds in /D, it checks to see if the same object exists in /usr/D. If there are no conflicts, the file is moved from /D to /usr/D. If conflicts exist, an error message is output.
If /D and /usr/D reside on the same filesystem, hard links are used to avoid copying any data. Otherwise, the file is copied along with any permissions, timestamps, and extended attributes.
The original file in /D is replaced with a symlink to the new path under /usr/D. Once all files have been moved, /D is replaced with a symlink to /usr/D.
What do I do if the migration fails or is interrupted?
Do I need to reboot after the migration?
This isn't strictly necessary, but it's probably a good idea in case any system services are holding open files under the directories that have been replaced with symlinks.
How much disk space do I need?
If the contents of the /bin and /lib directories live on the same filesystem as /usr/bin and /usr/lib, the disk space requirement is very small. Only a minuscule about of space is needed for some hard links and symlinks.
If /bin and /lib live on a different filesystem from /usr/bin and /usr/lib, it will be necessary to ensure that /usr is large enough to hold the copied files. The du command can be used to calculate space consumption.
The following will output a human readable summary of disk space for the /usr directory:
du -su /usr
Repeat the same for /bin and /lib to determine if they will fit under /usr.
I'm using some exotic filesystem. Will this work on my system?
The script has been well-tested with typical filesystems — ext2, ext3, ext4, XFS, btrfs, and ZFS — on local storage. The script can work on remote storage too, but some manual intervention is required.
The script does work on NFS, for example, but some paths must be manually cleaned up after rebooting, due to the weird way NFS deals with deletion of open files. The script will warn about the paths that could not be deleted automatically.
The script has also been tested on overlayfs. The replacement of directories with symlinks is slightly less atomic than with other filesystems because overlayfs does not allow directories to be renamed in a single operation.
If an issue is encountered with some other exotic filesystem, please report a bug.
Feel free to add a note to this article, in case of a positive experience with some other filesystem.