Merge the /usr
Directory of a Gentoo Installation
Update on December 15, 2022:
This tutorial is deprecated. Gentoo has started to officially support
/usr
-merged file system layout in response to systemd’s plan to drop support
for unmerged /usr
in 2023.
There is no need to follow this tutorial to merge /usr
anymore. One of
the following actions is recommended instead, depending on the situation:
-
Users performing a new Gentoo installation may choose a stage tarball whose file name contains
mergedusr
to install a/usr
-merged system. -
Users of an existing system with unmerged
/usr
can use the new, officialsys-apps/merge-usr
utility to carry out the merge. More instructions are available in this news item and on Gentoo Wiki. -
Users who have followed this tutorial before to merge
/usr
are recommended, but not necessarily required, to go through these steps:-
Switch to a
merged-usr
profile. Candidate profiles can be found by running:$ eselect profile list | grep merged-usr
Then, use
eselect profile set
to select a proper profile. -
Delete the
split-usr
USE flag from file/etc/portage/profile/use.mask
. It is no longer needed when amerge-usr
profile is selected. -
If any tasks in the Additional Tasks section below were done, undo the changes by removing the relevant file and configuration.
-
If the first variant of
/usr
merge was used, then runningsys-apps/merge-usr
is still recommended. Gentoo has officially adopted the second variant, so the first variant might not receive official support when an issue occurs later.merge-usr
is able to convert the first variant to the second variant:$ ls -dl /sbin /usr/sbin lrwxrwxrwx 1 root root 8 Dec 13 2020 /sbin -> usr/sbin drwxr-xr-x 1 root root 6680 Nov 29 09:03 /usr/sbin $ merge-usr --dryrun WARNING: Already a symlink: '/bin' WARNING: Already a symlink: '/sbin' INFO: Migrating files from '/usr/sbin' to '/usr/bin' INFO: No problems found for '/usr/sbin' WARNING: Already a symlink: '/lib' WARNING: Already a symlink: '/lib64'
In this case,
merge-usr
will not replace/sbin
with a symbolic link tousr/bin
(it would if the system’s/usr
was not merged), but this should not negatively affect system functionality because the links are eventually chained together as/sbin -> /usr/sbin -> /usr/bin
. For those who want a direct link instead, the target of/sbin
can be manually changed tousr/bin
:# rm /sbin && ln -s usr/bin /sbin
-
This tutorial is preserved for historical purposes.
The /usr
merge, sometimes also known as /usr
move, refers to a process
on a Filesystem Hierarchy Standard (FHS) compliant system, which most
GNU/Linux distributions are, that moves all contents under /bin
, /lib
,
/lib64
and /sbin
into /usr/bin
, /usr/lib
, /usr/lib64
and /usr/sbin
respectively, and then replace each of /bin
, /lib
, /lib64
and /sbin
with a symbolic link to the directory with the same name under /usr
. More
information about /usr
merge is available on freedesktop.org
and Fedora Wiki.
The trend of /usr
merge in GNU/Linux distributions seemed to be started by
Fedora in 2012, and then, we can see that many well-known and popular
distributions, including Debian Ubuntu and Arch Linux, have made the move.
It was similar to the wide adoption of systemd in GNU/Linux distributions, both
of which were started by Red Hat’s desire to shape all modern Linux-based
systems at their discretion and Lennart Poettering’s support,
then made their debut in Fedora, and finally accepted by other distributions.
Update on April 7, 2022: After reading the new, hot
LWN.net report covering the /usr
merge dilemma Debian is still
facing, I am perplexed by how I got the impression that Debian had completed
the /usr
merge when I wrote the initial version of this article. To show
what a silly mistake I made, I am crossing out Debian and replacing it with
Ubuntu instead. Interestingly, Ubuntu, as a Debian derivative, has
accomplished the /usr
merge even earlier than Debian.
Gentoo, being one of the few distributions that still do not use systemd as
the default init system, is also absent from the group of distributions that
have completed the judging from a /usr
merge. By default, in the root file system of a
Gentoo installation, /bin
, /lib
, /lib64
and /sbin
are still standalone
directories instead of symbolic links. Butsplit-usr
global Portage USE flag, there might have already been plans to
merge /usr
in Gentoo. At the time when the first revision of this post was
published, the USE flag was forcibly declared, to indicate that /bin
, /lib
,
/lib64
and /sbin
were still split from /usr
; in the future, the USE
flag might become optional when Gentoo is fully ready for the /usr
merge.
This article will show you how to merge is by no means suggesting that
/usr
on a Gentoo installation now,
when it is yet to be officially supported. It/usr
split is a definitely beneficial decision, and the advantages of /usr
merge are not the subject of discussion here. The sole purpose of this post is
to help people who are interested in making the merge to do it.
Variants of /usr
Merge
It is worth mentioning that there are two different ways of merging /usr
that
can be found in various GNU/Linux distributions:
-
Merge
/bin
into/usr/bin
,/lib
into/usr/lib
,/lib64
into/usr/lib64
, and/sbin
into/usr/sbin
. This kind of merge is what Fedora andDebianUbuntu do.$ ls -dl /bin /lib /lib64 /sbin /usr/sbin lrwxrwxrwx 1 root root 7 Dec 13 14:11 /bin -> usr/bin lrwxrwxrwx 1 root root 7 Dec 13 14:11 /lib -> usr/lib lrwxrwxrwx 1 root root 9 Dec 13 14:11 /lib64 -> usr/lib64 lrwxrwxrwx 1 root root 8 Dec 13 14:11 /sbin -> usr/sbin drwxr-xr-x 1 root root 7006 Dec 26 09:50 /usr/sbin
-
Perform not only the merges mentioned above but also another one that moves contents of
/usr/sbin
into/usr/bin
. Arch Linux merges/usr
in this way, and from theebuild
for Gentoo packagesys-apps/baselayout
, which already supports thesplit-usr
USE flag, this islikely to behow Gentoo merges/usr
too. (Update on December 15, 2022: this is exactly how Gentoo merges/usr
now that the distribution officially supports it.)$ ls -dl /bin /lib /lib64 /sbin /usr/sbin lrwxrwxrwx 1 root root 7 Dec 13 14:11 /bin -> usr/bin lrwxrwxrwx 1 root root 7 Dec 13 14:11 /lib -> usr/lib lrwxrwxrwx 1 root root 9 Dec 13 14:11 /lib64 -> usr/lib64 lrwxrwxrwx 1 root root 7 Dec 13 14:11 /sbin -> usr/bin lrwxrwxrwx 1 root root 3 Dec 13 14:11 /usr/sbin -> bin
The command output snippets above are only for demonstrating the difference of
/usr/sbin
in both methods of merging /usr
; they might slightly differ from
the actual file system layout you might encounter.
This article will mainly focus on the first way because the resulting merged
file system layout is what I am personally more familiar with, and I prefer
that layout because I have used Fedora and Debian Ubuntu, but not Arch
Linux. Even if you would like to perform the second type of merge, this should
not matter too much because it is the way Gentoo devises. Doing the first type
of merge, on the other hand, is actually a little more complicated because of
this. If I provide you a guide for a more difficult goal, then you should be
able to use it to achieve an easier goal, though you might need to slightly
change some commands for your special situation.
Prerequisites
-
The
/usr
merge can be performed either during installation of a new system or on an existing installation. The steps slightly differ, and this article will cover both cases in two separate sections. -
Please make sure you have another bootable drive (e.g. a USB drive with Gentoo minimal installation CD image applied) available before you start. Obviously, if you are installing Gentoo, you must have had such a drive for installation. If you are doing
/usr
merge on an existing system, you will need to shut down the system and modify file system layout for the merge while the system is not running, so you need another bootable media with an environment from which you can work on an existing Gentoo installation.
Merge During System Installation
The following instruction assumes you are following installation steps outlined in the Gentoo Handbook.
-
After you have unpacked the stage tarball under the “Installing stage3” step, enter the extracted
usr
directory, and re-extract./bin
,./lib
,./lib64
and./sbin
from the stage tarball.livecd /mnt/gentoo # cd usr livecd /mnt/gentoo/usr # tar xpvf ../stage3-*.tar.xz --xattrs-include='*.*' --numeric-owner ./{bin,lib,lib64,sbin}
-
Go back to the parent directory, and replace each of
bin
,lib
,lib64
andsbin
with symbolic link to the directory underusr
with the same name.livecd /mnt/gentoo/usr # cd .. livecd /mnt/gentoo # rm -rf bin lib lib64 sbin livecd /mnt/gentoo # ln -s usr/bin bin livecd /mnt/gentoo # ln -s usr/lib lib livecd /mnt/gentoo # ln -s usr/lib64 lib64 livecd /mnt/gentoo # ln -s usr/sbin sbin
If you wish to have the second type of
/usr
merge, you should additionally move everything inusr/sbin
intousr/bin
and replaceusr/sbin
with a symbolic link to theusr/bin
directory:livecd /mnt/gentoo # cd usr livecd /mnt/gentoo/usr # mv sbin/* bin livecd /mnt/gentoo/usr # rmdir sbin livecd /mnt/gentoo/usr # ln -s bin sbin
The result of this operation is something like the following. Note that
bin
,lib
,lib64
andsbin
are now symbolic links:livecd /mnt/gentoo # ls -l total 16 lrwxrwxrwx 1 root root 7 Dec 28 04:07 bin -> usr/bin drwxr-xr-x 1 root root 10 Dec 23 05:20 boot drwxr-xr-x 1 root root 1686 Dec 23 05:25 dev drwxr-xr-x 1 root root 1546 Dec 23 06:32 etc drwxr-xr-x 1 root root 10 Dec 23 05:20 home lrwxrwxrwx 1 root root 7 Dec 28 04:07 lib -> usr/lib lrwxrwxrwx 1 root root 9 Dec 28 04:07 lib64 -> usr/lib64 drwxr-xr-x 1 root root 10 Dec 23 05:20 media drwxr-xr-x 1 root root 10 Dec 23 05:20 mnt drwxr-xr-x 1 root root 10 Dec 23 05:20 opt drwxr-xr-x 1 root root 0 Dec 23 03:28 proc drwx------ 1 root root 10 Dec 23 05:20 root drwxr-xr-x 1 root root 10 Dec 23 05:20 run lrwxrwxrwx 1 root root 8 Dec 28 04:08 sbin -> usr/sbin drwxr-xr-x 1 root root 10 Dec 23 05:20 sys drwxrwxrwt 1 root root 10 Dec 23 06:32 tmp drwxr-xr-x 1 root root 128 Dec 23 05:29 usr drwxr-xr-x 1 root root 66 Dec 23 05:20 var
-
Continue to follow Gentoo Handbook’s instruction, until you have
chroot
ed into/mnt/gentoo
. -
Find broken symbolic links under
/usr
by usingfind -L /usr -type l
. The command’s output will show all broken links.(chroot) livecd / # find -L /usr -type l /usr/sbin/resolvconf /usr/bin/awk
Here,
/usr/sbin/resolvconf
and/usr/bin/awk
are broken links – they point to path that does not exist. This can cause problems when other programs and scripts need to use the files pointed by those links. For instance,awk
is a very important program required for compiling many other packages; since/usr/bin/awk
is a broken symbolic link, theawk
command is unavailable, and you might have trouble installing packages that requireawk
to build.(chroot) livecd / # /usr/bin/awk bash: /usr/bin/awk: No such file or directory
To fix a broken symbolic link, first enter the directory containing it, then use
ls -l
to find the file that link points to.(chroot) livecd / # cd /usr/bin/ (chroot) livecd /usr/bin # ls -l awk lrwxrwxrwx 1 root root 15 Dec 23 05:26 awk -> ../usr/bin/gawk
The
awk
symbolic link was supposed to be under/bin
, and/bin/../usr/bin/gawk
, which is equivalent to/usr/bin/gawk
, is a valid path. Because it is now moved to/usr
, and/usr/bin/../usr/bin/gawk
, i.e./usr/usr/bin/gawk
, does not exist, the symbolic link is thus broken. To fix it, remove the old link and create a new one with correct target:(chroot) livecd /usr/bin # rm awk (chroot) livecd /usr/bin # ln -s gawk awk
Apply the same procedure for
/usr/sbin/resolvconf
:(chroot) livecd / # cd /usr/sbin/ (chroot) livecd /usr/sbin # ls -l resolvconf lrwxrwxrwx 1 root root 21 Dec 23 06:28 resolvconf -> ../usr/bin/resolvectl (chroot) livecd /usr/sbin # rm resolvconf (chroot) livecd /usr/sbin # ln -s ../bin/resolvectl resolvconf
If you run
find -L /usr -type l
again now, nothing should be printed, which indicates that all broken symbolic links have been fixed.find -L -type l
is the panacea for finding broken symbolic links.find
is a basic but powerful command that is usually preinstalled on most GNU/Linux distributions. There is no need to install other packages likesymlinks
for this purpose!The
find(1)
manual page says:-type c File is of type c: l symbolic link; this is never true if the -L option or the -follow option is in effect, unless the symbolic link is broken. If you want to search for symbolic links when -L is in effect, use -xtype.
-
Mask the
split-usr
USE flag, so packages can know the current system has its/usr
merged if they support it. Declaring-split-usr
is not sufficient to mask the USE flag becausesplit-usr
is forcibly enabled; you need to mask the USE flag in/etc/portage/profile/use.mask
instead:# /etc/portage/profile/use.mask # Mask the USE flag for split /usr file system layout split-usr
Please visit this Gentoo Wiki page for more information.
-
Complete the remaining steps in the Gentoo Handbook as instructed. Be sure to update the
@world
set to apply thesplit-usr
USE flag change.When you run a command installed to
/sbin
or/usr/sbin
, you may see a “command not found” error message. For example, if you choose GRUB as the bootloader, you will need to run/usr/sbin/grub-install
, but an error will occur when it is invoked. You can use thewhereis
program to confirm that the command is installed to/usr/sbin
.(chroot) livecd ~ # grub-install --target=x86_64-efi --efi-directory=/boot bash: grub-install: command not found (chroot) livecd ~ # whereis grub-install grub-install: /usr/sbin/grub-install /usr/share/man/man8/grub-install.8.bz2
The reason for this error is that
/usr/sbin
is not added to thePATH
environment variable:(chroot) livecd ~ # printenv PATH /usr/local/bin:/usr/bin:/opt/bin
To complete the installation, you can use the quickest way to solve this issue, which is to add
/usr/sbin
temporarily toPATH
by runningexport PATH="/usr/sbin:$PATH"
. This needs to be done every time when you start a new shell. For a permanent solution, please look at the “Permanently Add/usr/sbin
toPATH
” section below.(chroot) livecd ~ # export PATH="/usr/sbin:$PATH" (chroot) livecd ~ # printenv PATH /usr/sbin:/usr/local/bin:/usr/bin:/opt/bin (chroot) livecd ~ # grub-install --target=x86_64-efi --efi-directory=/boot Installing for x86_64-efi platform. Installation finished. No error reported.
Merge on an Installed System
-
Boot your computer from the bootable drive you prepared, and mount your system’s root partition. The subsequent steps assume your root partition is mounted to
/mnt/gentoo
. Switch to the directory where the partition is mounted.livecd ~ # cd /mnt/gentoo
-
Using the
\cp
command with-r
,--preserve=all
and--remove-destination
options, copy everything insidebin
,lib
,lib64
andsbin
intousr/bin
,usr/lib
,usr/lib64
andusr/sbin
respectively.livecd /mnt/gentoo # \cp -rv --preserve=all --remove-destination bin/* usr/bin livecd /mnt/gentoo # \cp -rv --preserve=all --remove-destination lib/* usr/lib livecd /mnt/gentoo # \cp -rv --preserve=all --remove-destination lib64/* usr/lib64 livecd /mnt/gentoo # \cp -rv --preserve=all --remove-destination sbin/* usr/sbin
The
-v
option forcp
allows you to see the copying progress. Feel free to omit it if you do not need it.Adding a backslash
\
in front ofcp
ignores any alias set forcp
. If you are using the Gentoo minimal installation CD image, the default alias forcp
iscp -i
, which letscp
ask for your confirmation on every file being overwritten.livecd ~ # alias cp alias cp='cp -i'
Using
\cp
instead ofcp
ignores the alias. Alternatively, you may also useunalias cp
to remove that alias and continue to invokecp
without\
in front, or pipe in a lot ofy
’s withyes | cp ...
.livecd /mnt/gentoo # unalias cp livecd /mnt/gentoo # cp -rv --preserve=all --remove-destination bin/* usr/bin livecd /mnt/gentoo # cp -rv --preserve=all --remove-destination lib/* usr/lib livecd /mnt/gentoo # cp -rv --preserve=all --remove-destination lib64/* usr/lib64 livecd /mnt/gentoo # cp -rv --preserve=all --remove-destination sbin/* usr/sbin
livecd /mnt/gentoo # yes | cp -rv --preserve=all --remove-destination bin/* usr/bin livecd /mnt/gentoo # yes | cp -rv --preserve=all --remove-destination lib/* usr/lib livecd /mnt/gentoo # yes | cp -rv --preserve=all --remove-destination lib64/* usr/lib64 livecd /mnt/gentoo # yes | cp -rv --preserve=all --remove-destination sbin/* usr/sbin
-
Replace each of
bin
,lib
,lib64
andsbin
with symbolic link to the directory underusr
with the same name.livecd /mnt/gentoo # rm -rf bin lib lib64 sbin livecd /mnt/gentoo # ln -s usr/bin bin livecd /mnt/gentoo # ln -s usr/lib lib livecd /mnt/gentoo # ln -s usr/lib64 lib64 livecd /mnt/gentoo # ln -s usr/sbin sbin
If you wish to have the second type of
/usr
merge, you should additionally move everything insbin
andusr/sbin
intousr/bin
, and replaceusr/sbin
with a symbolic link to theusr/bin
directory. Please see here for commands you may use to do this. -
Restart your computer and boot into your system (not the bootable drive). As long as you have correctly copied the contents of
/bin
,/lib
,/lib64
and/sbin
into/usr
and established the symbolic links, your system should boot up normally. -
Fix broken symbolic links under
/usr
by following step 4 for the method to merge/usr
during system installation. However, you do not need to manually fix all broken symbolic links:-
If you use systemd and dracut, you may see some broken links whose names are something like
dracut-*.service
. These links can be easily fixed by reinstallingsys-kernel/dracut
after systemd is rebuilt withsplit-usr
USE flag masked. -
It should be fine to leave
/usr/lib/modules/*.*.*/build
and/usr/lib/modules/*.*.*/source
unfixed.
Any other broken symbolic links, like
/usr/bin/awk
and/usr/sbin/resolvconf
, still require manual intervention. -
-
Mask the
split-usr
USE flag by following step 5 for the method to merge/usr
during system installation. -
Update the
@world
set of Portage to rebuild packages that had thesplit-usr
USE flag enabled.# emerge --ask --update --deep --newuse @world
If you are using systemd and dracut, you can rebuild dracut now to fix the broken
dracut-*.service
symbolic links. Run the following command only if you intend to use dracut, because otherwise it will install dracut onto your system.# emerge --ask --oneshot sys-kernel/dracut
Additional Tasks
After following the steps above, your file system is /usr
-merged, and the
operating system should still function as if /usr
is not merged. There are
some additional tasks which would not cause system to malfunction if you chose
not to perform them, but they fix minor issues which would arise after /usr
merge.
Permanently Add /usr/sbin
to PATH
This task is not required if you are using the second variant of /usr
merge.
As mentioned briefly when discussing how Gentoo intends to merge
/usr
, /usr/sbin
is planned to be merged into /usr/bin
. If
you look carefully at the ebuild
for sys-apps/baselayout
, you
may find that when the split-usr
USE flag is disabled, /usr/sbin
is removed
from the PATH
environment variable, because every file that was supposed to
be under /usr/sbin
is now in /usr/bin
, which is already in PATH
.
However, if you are doing the first kind of /usr
merge, this is
not the desired result. Executables under /usr/sbin
are not moved in this
case, but /usr/sbin
is removed from PATH
if we disable the split-usr
USE
flag, so we cannot directly invoke any command installed to that location
without prepending /usr/sbin/
to the front of the command name!
The way I suggest to add /usr/sbin
back to PATH
is to define it globally
with a file under /etc/env.d
. Create a file with any name you like (e.g.
50baselayout-sbin
) under that path, and add the following PATH
and
ROOTPATH
definitions:
# /etc/env.d/50baselayout-sbin
PATH="/usr/local/sbin:/usr/sbin"
ROOTPATH="/usr/local/sbin:/usr/sbin"
In this example, I have added not only /usr/sbin
but also /usr/local/sbin
to PATH
because /usr/local/sbin
is removed from PATH
if split-usr
is
disabled for sys-apps/baselayout
too.
Then, update your environment to apply the change:
# /usr/sbin/env-update
$ source /etc/profile
For more information about using the /etc/env.d
directory, please refer to
this Gentoo Handbook section covering it.
Remove Messages Regarding Symbolic Links from emerge
You may see a warning message like the following one when you update or
uninstall a package with emerge
:
* One or more symlinks to directories have been preserved in order to
* ensure that files installed via these symlinks remain accessible. This
* indicates that the mentioned symlink(s) may be obsolete remnants of an
* old install, and it may be appropriate to replace a given symlink with
* the directory that it points to.
*
* /bin
* /lib64
* /sbin
*
This kind of messages is expected, because /bin
, /lib
, /lib64
and /sbin
are indeed symbolic links rather than directories now.
If you are interested in suppressing those messages, you may add the following
line to /etc/portage/make.conf
:
UNINSTALL_IGNORE="/bin /lib /lib64 /sbin"