diff --git a/documentation/content/en/books/handbook/linuxemu/_index.adoc b/documentation/content/en/books/handbook/linuxemu/_index.adoc index a799fbbc71..7e53866cf9 100644 --- a/documentation/content/en/books/handbook/linuxemu/_index.adoc +++ b/documentation/content/en/books/handbook/linuxemu/_index.adoc @@ -1,503 +1,503 @@ --- title: Chapter 12. Linux Binary Compatibility part: Part II. Common Tasks prev: books/handbook/printing next: books/handbook/wine description: FreeBSD provides binary compatibility with Linux, allowing users to install and run most Linux binaries on a FreeBSD system without having to first modify the binary tags: ["linux", "linuxulator", "emulation", "binary", "compatibility"] showBookMenu: true weight: 15 path: "/books/handbook/linuxemu/" --- [[linuxemu]] = Linux Binary Compatibility :doctype: book :toc: macro :toclevels: 1 :icons: font :sectnums: :sectnumlevels: 6 :sectnumoffset: 12 :partnums: :source-highlighter: rouge :experimental: :images-path: books/handbook/linuxemu/ ifdef::env-beastie[] ifdef::backend-html5[] :imagesdir: ../../../../images/{images-path} endif::[] ifndef::book[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] toc::[] endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../../shared/asciidoctor.adoc[] endif::[] endif::[] ifndef::env-beastie[] toc::[] include::../../../../../shared/asciidoctor.adoc[] endif::[] [[linuxemu-synopsis]] == Synopsis FreeBSD provides *optional* binary compatibility with Linux(R), commonly referred to as Linuxulator, allowing users to install and run unmodified Linux binaries. It is available for the x86 (both 32 and 64 bit) and AArch64 architectures. Some Linux-specific operating system features are not yet supported; this mostly happens with functionality specific to hardware or related to system management, such as cgroups or namespaces. Before reading this chapter, you should: * Know how to install crossref:ports[ports,additional third-party software]. After reading this chapter, you will know: * How to enable Linux binary compatibility on a FreeBSD system. * How to install additional Linux shared libraries. * How to install Linux applications on a FreeBSD system. * The implementation details of Linux compatibility in FreeBSD. [[linuxemu-lbc-install]] == Configuring Linux Binary Compatibility By default, man:linux[4] binary compatibility is not enabled. To enable the Linux ABI at boot time, execute the following command: [.programlisting] .... # sysrc linux_enable="YES" .... Once enabled, it can be started without rebooting by executing the following command: [source,shell] .... # service linux start .... This is enough for statically linked Linux binaries to work. The Linux service will load necessary kernel modules and mount filesystems expected by Linux applications under [.filename]#/compat/linux#. They can be started in the same way native FreeBSD binaries can; they behave almost exactly like native processes and can be traced and debugged the usual way. The current content of [.filename]#/compat/linux# can be checked executing the following command: [source,shell] .... # ls -l /compat/linux/ .... The output should be similar to the following: [.programlisting] .... total 1 dr-xr-xr-x 13 root wheel 512 Apr 11 19:12 dev dr-xr-xr-x 1 root wheel 0 Apr 11 21:03 proc dr-xr-xr-x 1 root wheel 0 Apr 11 21:03 sys .... [[linux-userlands]] == Linux userlands Linux software requires more than just an ABI to work. In order to run Linux software a Linux userland must be installed first. [TIP] ==== If all that is wanted is to run some software already included in the Ports tree, it can be installed via package manager and man:pkg[8] will automatically setup the required Linux userland. For example, to install Sublime Text 4, along with all the Linux libraries it depends on, run this command: [source,shell] .... # pkg install linux-sublime-text4 .... ==== [[linuxemu-rockylinux]] === Rocky Linux Base System from FreeBSD Packages To install the Rocky Linux 9 userland execute the following command: [source,shell] .... # pkg install linux_base-rl9 .... -package:emulators/linux_rl9[] will place the base system derived from Rocky Linux 9 into [.filename]#/compat/linux#. +package:emulators/linux_base-rl9[] will place the base system derived from Rocky Linux 9 into [.filename]#/compat/linux#. After installing the package, the contents of [.filename]#/compat/linux# can be verified by running the following command to check that the Rocky Linux userland has been installed: [source,shell] .... # ls -l /compat/linux/ .... The output should be similar to the following: [.programlisting] .... total 36 drwxr-xr-x 2 root wheel 512 Oct 9 17:28 afs lrwxr-xr-x 1 root wheel 7 May 16 2022 bin -> usr/bin drwxr-xr-x 3 root wheel 512 Oct 9 17:28 dev drwxr-xr-x 24 root wheel 1536 Oct 9 17:28 etc lrwxr-xr-x 1 root wheel 7 May 16 2022 lib -> usr/lib lrwxr-xr-x 1 root wheel 9 May 16 2022 lib64 -> usr/lib64 drwxr-xr-x 2 root wheel 512 Oct 9 17:28 opt drwxr-xr-x 2 root wheel 512 Oct 9 17:28 proc lrwxr-xr-x 1 root wheel 8 Oct 1 03:11 run -> /var/run lrwxr-xr-x 1 root wheel 8 May 16 2022 sbin -> usr/sbin drwxr-xr-x 2 root wheel 512 Oct 9 17:28 srv drwxr-xr-x 2 root wheel 512 Oct 9 17:28 sys drwxr-xr-x 8 root wheel 512 Oct 9 17:28 usr drwxr-xr-x 16 root wheel 512 Oct 9 17:28 var .... [[linuxemu-centos]] === CentOS Base System from FreeBSD Packages [WARNING] ==== package:emulators/linux_base-c7[] has been deprecated following the deprecation of the upstream project. This means package:emulators/linux_base-c7[] will not receive security updates. The use of crossref:linuxemu[linuxemu-rockylinux, the Rocky Linux Base System] is recommended unless 32-bit compatibility is needed. ==== To install the CentOS userland execute the following command: [source,shell] .... # pkg install linux_base-c7 .... package:emulators/linux_base-c7[] will place the base system derived from CentOS 7 into [.filename]#/compat/linux#. After installing the package, the contents of [.filename]#/compat/linux# can be verified by running the following command to check that the CentOS userland has been installed: [source,shell] .... # ls -l /compat/linux/ .... The output should be similar to the following: [.programlisting] .... total 30 lrwxr-xr-x 1 root wheel 7 Apr 11 2018 bin -> usr/bin drwxr-xr-x 13 root wheel 512 Apr 11 21:10 dev drwxr-xr-x 25 root wheel 64 Apr 11 21:10 etc lrwxr-xr-x 1 root wheel 7 Apr 11 2018 lib -> usr/lib lrwxr-xr-x 1 root wheel 9 Apr 11 2018 lib64 -> usr/lib64 drwxr-xr-x 2 root wheel 2 Apr 11 21:10 opt dr-xr-xr-x 1 root wheel 0 Apr 11 21:25 proc lrwxr-xr-x 1 root wheel 8 Feb 18 02:10 run -> /var/run lrwxr-xr-x 1 root wheel 8 Apr 11 2018 sbin -> usr/sbin drwxr-xr-x 2 root wheel 2 Apr 11 21:10 srv dr-xr-xr-x 1 root wheel 0 Apr 11 21:25 sys drwxr-xr-x 8 root wheel 9 Apr 11 21:10 usr drwxr-xr-x 16 root wheel 17 Apr 11 21:10 var .... [[linuxemu-debootstrap]] === Debian / Ubuntu Base System with debootstrap An alternative way of providing Linux shared libraries is by using package:sysutils/debootstrap[]. This has the advantage of providing a full Debian or Ubuntu distribution. To install debootstrap execute the following command: [source,shell] .... # pkg install debootstrap .... man:debootstrap[8] needs man:linux[4] ABI enabled. Once enabled, execute the following command to install Ubuntu or Debian in [.filename]#/compat/ubuntu#: [source,shell] .... # debootstrap focal /compat/ubuntu .... [NOTE] ==== While it is technically possible to install into [.filename]#/compat/linux# instead, it's discouraged due to possible clashes with CentOS-based packages. Instead, derive the directory name from the distribution or version name, e.g., [.filename]#/compat/ubuntu#. ==== The output should be similar to the following: [.programlisting] .... I: Retrieving InRelease I: Checking Release signature I: Valid Release signature (key id F6ECB3762474EDA9D21B7022871920D1991BC93C) I: Retrieving Packages I: Validating Packages I: Resolving dependencies of required packages... I: Resolving dependencies of base packages... I: Checking component main on http://archive.ubuntu.com/ubuntu... [...] I: Configuring console-setup... I: Configuring kbd... I: Configuring ubuntu-minimal... I: Configuring libc-bin... I: Configuring ca-certificates... I: Base system installed successfully. .... Then set up mounts in [.filename]#/etc/fstab#. [TIP] ==== If the contents of the home directory should be shared and to be able to run X11 applications, [.filename]#/home# and [.filename]#/tmp# should be mounted in the linux compat area using man:nullfs[5] for loopback. The following example can be added to [.filename]#/etc/fstab#: [.programlisting] .... # Device Mountpoint FStype Options Dump Pass# devfs /compat/ubuntu/dev devfs rw,late 0 0 tmpfs /compat/ubuntu/dev/shm tmpfs rw,late,size=1g,mode=1777 0 0 fdescfs /compat/ubuntu/dev/fd fdescfs rw,late,linrdlnk 0 0 linprocfs /compat/ubuntu/proc linprocfs rw,late 0 0 linsysfs /compat/ubuntu/sys linsysfs rw,late 0 0 /tmp /compat/ubuntu/tmp nullfs rw,late 0 0 /home /compat/ubuntu/home nullfs rw,late 0 0 .... Then execute man:mount[8]: [source,shell] .... # mount -al .... ==== To access the system using man:chroot[8] execute the following command: [source,shell] .... # chroot /compat/ubuntu /bin/bash .... Then man:uname[1] can be executed to check the Linux environment: [source,shell] .... # uname -s -r -m .... The output should be similar to the following: [.programlisting] .... Linux 3.17.0 x86_64 .... Once inside the chroot, the system behaves as in a normal Ubuntu installation. While systemd doesn't work, the man:service[8] command works as usual. [TIP] ==== To add the package repositories missing from defaults edit the file [.filename]#/compat/ubuntu/etc/apt/sources.list#. For amd64 the following example can be used: [.programlisting] .... deb http://archive.ubuntu.com/ubuntu focal main universe restricted multiverse deb http://security.ubuntu.com/ubuntu/ focal-security universe multiverse restricted main deb http://archive.ubuntu.com/ubuntu focal-backports universe multiverse restricted main deb http://archive.ubuntu.com/ubuntu focal-updates universe multiverse restricted main .... For arm64 this other example can be used: [.programlisting] .... deb http://ports.ubuntu.com/ubuntu-ports bionic main universe restricted multiverse .... ==== [[linuxemu-advanced]] == Advanced Topics A list of all Linux-related man:sysctl[8] knobs can be found in man:linux[4]. Some applications require specific filesystems to be mounted. This is normally handled by the [.filename]#/etc/rc.d/linux# script but can be disabled at boot executing the following command: [.programlisting] .... sysrc linux_mounts_enable="NO" .... Filesystems mounted by the rc script will not work for Linux processes inside chroots or jails; if needed, configure them in [.filename]#/etc/fstab#: [.programlisting] .... devfs /compat/linux/dev devfs rw,late 0 0 tmpfs /compat/linux/dev/shm tmpfs rw,late,size=1g,mode=1777 0 0 fdescfs /compat/linux/dev/fd fdescfs rw,late,linrdlnk 0 0 linprocfs /compat/linux/proc linprocfs rw,late 0 0 linsysfs /compat/linux/sys linsysfs rw,late 0 0 .... Since the Linux binary compatibility layer has gained support for running both 32- and 64-bit Linux binaries, it is no longer possible to link the emulation functionality statically into a custom kernel. [[linuxemu-libs-manually]] === Installing Additional Libraries Manually [NOTE] ==== For base system subdirectories created with man:debootstrap[8], use the instructions above instead. ==== If a Linux application complains about missing shared libraries after configuring Linux binary compatibility, determine which shared libraries the Linux binary needs and install them manually. From a Linux system using the same CPU architecture, `ldd` can be used to determine which shared libraries the application needs. For example, to check which shared libraries `linuxdoom` needs, run this command from a Linux system that has Doom installed: [source,shell] .... % ldd linuxdoom .... The output should be similar to the following: [.programlisting] .... libXt.so.3 (DLL Jump 3.1) => /usr/X11/lib/libXt.so.3.1.0 libX11.so.3 (DLL Jump 3.1) => /usr/X11/lib/libX11.so.3.1.0 libc.so.4 (DLL Jump 4.5pl26) => /lib/libc.so.4.6.29 .... Then, copy all the files in the last column of the output from the Linux system into [.filename]#/compat/linux# on the FreeBSD system. Once copied, create symbolic links to the names in the first column. This example will result in the following files on the FreeBSD system: [.programlisting] .... /compat/linux/usr/X11/lib/libXt.so.3.1.0 /compat/linux/usr/X11/lib/libXt.so.3 -> libXt.so.3.1.0 /compat/linux/usr/X11/lib/libX11.so.3.1.0 /compat/linux/usr/X11/lib/libX11.so.3 -> libX11.so.3.1.0 /compat/linux/lib/libc.so.4.6.29 /compat/linux/lib/libc.so.4 -> libc.so.4.6.29 .... If a Linux shared library already exists with a matching major revision number to the first column of the `ldd` output, it does not need to be copied to the file named in the last column, as the existing library should work. It is advisable to copy the shared library if it is a newer version, though. The old one can be removed, as long as the symbolic link points to the new one. For example, these libraries already exist on the FreeBSD system: [.programlisting] .... /compat/linux/lib/libc.so.4.6.27 /compat/linux/lib/libc.so.4 -> libc.so.4.6.27 .... and `ldd` indicates that a binary requires a later version: [.programlisting] .... libc.so.4 (DLL Jump 4.5pl26) -> libc.so.4.6.29 .... Since the existing library is only one or two versions out of date in the last digit, the program should still work with the slightly older version. However, it is safe to replace the existing [.filename]#libc.so# with the newer version: [.programlisting] .... /compat/linux/lib/libc.so.4.6.29 /compat/linux/lib/libc.so.4 -> libc.so.4.6.29 .... Generally, one will need to look for the shared libraries that Linux binaries depend on only the first few times that a Linux program is installed on FreeBSD. After a while, there will be a sufficient set of Linux shared libraries on the system to be able to run newly installed Linux binaries without any extra work. === Branding Linux ELF Binaries The FreeBSD kernel uses several methods to determine if the binary to be executed is a Linux one: it checks the brand in the ELF file header, looks for known ELF interpreter paths and checks ELF notes; finally, by default, unbranded ELF executables are assumed to be Linux anyway. Should all those methods fail, an attempt to execute the binary might result in error message: [source,shell] .... % ./my-linux-elf-binary .... The output should be similar to the following: [.programlisting] .... ELF binary type not known Abort .... To help the FreeBSD kernel distinguish between a FreeBSD ELF binary and a Linux binary, use man:brandelf[1]: [source,shell] .... % brandelf -t Linux my-linux-elf-binary .... === Installing a Linux RPM Based Application To install a Linux RPM-based application, first install the package:archivers/rpm4[] package or port. Once installed, `root` can use this command to install a [.filename]#.rpm#: [source,shell] .... # cd /compat/linux # rpm2cpio < /path/to/linux.archive.rpm | cpio -id .... If necessary, `brandelf` the installed ELF binaries. Note that this will prevent a clean uninstall. === Configuring the Hostname Resolver If DNS does not work or this error appears: [.programlisting] .... resolv+: "bind" is an invalid keyword resolv+: "hosts" is an invalid keyword .... configure [.filename]#/compat/linux/etc/host.conf# as follows: [.programlisting] .... order hosts, bind multi on .... This specifies that [.filename]#/etc/hosts# is searched first and DNS is searched second. When [.filename]#/compat/linux/etc/host.conf# does not exist, Linux applications use [.filename]#/etc/host.conf# in the host system but they complain since that file does not exist in FreeBSD. Remove `bind` if a name server is not configured using [.filename]#/etc/resolv.conf#. [[linuxemu-misc]] === Miscellaneous More information on how binary compatibility works with Linux(R) can be found in the article link:{linux-emulation}[Linux emulation in FreeBSD].