From 63f2698e0554c0c893136c697ca7a4a9b1049d11 Mon Sep 17 00:00:00 2001 From: Paul Menzel Date: Wed, 21 Oct 2026 07:11:48 +0200 Subject: [PATCH] bee-mxqsub: Run only install and packaging under fakeroot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bee-mxqsub runs all of beesh under fakeroot, so the stat, chmod and chown calls of every configure and build process go through the one faked daemon. Large packages pay for this most: the Firefox build on a full 256-processor node was killed while packaging, 14:38.60 E make[2]: *** Waiting for unfinished jobs.... /home/pmenzel/bee-files/scripts/bee-mxqsub: line 1: 222979 CPU time limit exceeded (core dumped) ${sandbox[@]+"${sandbox[@]}"} fakeroot beesh "${beesh_args[@]}" "${beefile}" and without the preload `mach build` took 11:34 instead of 17:37. bee’s beesh gains `--fakeroot` (branch beesh-add-fakeroot-option), which starts faked right before the install step and stops it after packaging. Use it when the installed beesh lists it in `--help`, and keep calling all of beesh under fakeroot otherwise, so jobs on nodes with an older bee behave as before. beesh then reads its configuration with the real UID, for which beerc picks the repository below ~/.local and the user’s package database and cache. Export BEE_REPOSITORY_PREFIX, BEE_METADIR and BEE_CACHEDIR from `fakeroot bee --print-config`, which the job reads anyway, so the packages still go to /src/mariux/beeroot unless --repository says otherwise. The overlay sandbox runs beesh as UID 0 and has its own cache, so it needs neither. Tested by running the job phase locally with a package whose Makefile installs with `-o root`, mode 4755 and `-o 1234`: with the new beesh, the build step ran with the real UID and the package has the same owners and modes as with the installed beesh, which takes the fallback. Assisted-by: claude-opus-5.5 (Claude Code) --- scripts/bee-mxqsub | 45 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/scripts/bee-mxqsub b/scripts/bee-mxqsub index a1c28212e..d9df882db 100755 --- a/scripts/bee-mxqsub +++ b/scripts/bee-mxqsub @@ -59,6 +59,9 @@ buildroot= # like 0, so beerc picks bee's default for root, /src/mariux/beeroot, which is # where the artifacts belong. Pass --repository to build into a private tree. repository= +# beesh --fakeroot runs only the install and packaging under fakeroot, and +# configures and builds with the real UID; see the job phase. Without it, the +# whole of beesh runs under fakeroot. use_fakeroot=1 keep_buildroot=0 # The staging directory has to be readable from the cluster nodes, so it must @@ -112,7 +115,9 @@ Options: pull a bee-file away from the running job (default: /scratch/tmp/bee-mxqsub-\$USER) --no-stage build from the bee-files in the repository - --fakeroot call beesh under fakeroot (default) + --fakeroot install and package under fakeroot, configure and + build without it if beesh has --fakeroot, else + call all of beesh under fakeroot (default) --no-fakeroot call beesh without fakeroot --overlay install each package into an overlay, so that the following bee-files find it, and build in a sandbox @@ -410,11 +415,6 @@ if (( run_job )); then echo "=== buildroot: ${buildroot}" echo "=== repository: ${repository:-}" echo "=== makeflags: ${makeflags}" - if (( use_fakeroot )); then - echo "=== fakeroot: yes" - else - echo "=== fakeroot: no" - fi if (( overlay )); then echo "=== overlay: ${overlay_root} over ${overlay_dirs[*]}" else @@ -437,6 +437,24 @@ if (( run_job )); then export "${assignment?}" done + # Under fakeroot, the stat, chmod and chown calls of every build process + # go through the one faked daemon, which made the Firefox build take 17:37 + # instead of 11:34. Only installing and packaging need the fake root, and + # beesh --fakeroot confines it to them. Older beesh versions lack the + # option and get the whole of beesh run under fakeroot as before. Ask + # only now, as --env may have set PATH to another bee. + beesh_fakeroot=0 + if (( use_fakeroot )); then + if beesh --help 2>/dev/null | grep -q -e '--fakeroot'; then + beesh_fakeroot=1 + echo "=== fakeroot: install and packaging only (beesh --fakeroot)" + else + echo "=== fakeroot: all of beesh (beesh lacks --fakeroot)" + fi + else + echo "=== fakeroot: no" + fi + # mxqd hands a job the usual soft limit of 1024 open files while the hard # limit is higher, and raising the soft limit to the hard one needs no # privileges. Every process of every build inherits it, fuse-overlayfs @@ -500,6 +518,17 @@ if (( run_job )); then else config=$(bee --print-config) fi + # beesh --fakeroot reads the configuration with the real UID, for which + # beerc picks the private repository below ~/.local and the user's + # package database and cache instead of root's. Hand it the paths of + # root's configuration, as a beesh running under fakeroot would use. + if (( beesh_fakeroot )) && ! (( overlay )); then + for var in BEE_REPOSITORY_PREFIX BEE_METADIR BEE_CACHEDIR; do + value=$(sed -n "s/^${var}=//p" <<< "${config}") + [ -n "${value}" ] || die "cannot read ${var} from bee --print-config" + export "${var}=${value}" + done + fi pkgdir=$(sed -n 's/^BEE_PKGDIR=//p' <<< "${config}") [ -n "${pkgdir}" ] || die "cannot read BEE_PKGDIR from bee --print-config" mkdir -p "${pkgdir}" 2>/dev/null @@ -539,7 +568,9 @@ if (( run_job )); then # A .be0/.bee is a beesh script: its mee_* hooks are called by # beesh, so running it with plain bash only defines the functions # and builds nothing. - if (( use_fakeroot )); then + if (( beesh_fakeroot )); then + ${sandbox[@]+"${sandbox[@]}"} beesh --fakeroot "${beesh_args[@]}" "${beefile}" + elif (( use_fakeroot )); then ${sandbox[@]+"${sandbox[@]}"} fakeroot beesh "${beesh_args[@]}" "${beefile}" else ${sandbox[@]+"${sandbox[@]}"} beesh "${beesh_args[@]}" "${beefile}"