From 6640bb2d26817f6a781febf41e45982679376e7c Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 16 Jul 2026 20:01:18 +0200 Subject: [PATCH 1/2] anchorMC: Fail hard if modulecmd not found for 2-tag operations --- MC/run/ANCHOR/anchorMC.sh | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 9425f8dfb..8b814f05e 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -178,9 +178,38 @@ fi export > env_base.env +# The 2-tag / alternative-reco setup below uses 'module save/purge/restore' to stash +# and swap the software environment. If the shell provides no 'module' function, build +# one on a 'modulecmd' binary. Its location varies by version, so resolve it flexibly +# (was hardwired to /usr/bin/modulecmd) and verify it supports saved collections. Fail +# hard -- but only when an alternative-reco tag is set, since single-tag jobs never call +# 'module' -- instead of silently no-op'ing every 'module' call (cf. O2-7070). if ! declare -F module > /dev/null; then + MODULECMD_BIN="" + for _cand in "${MODULECMD}" "/usr/bin/modulecmd" "$(command -v modulecmd 2>/dev/null)" "${MODULESHOME:+${MODULESHOME}/libexec/modulecmd}"; do + if [ -n "${_cand}" ] && [ -x "${_cand}" ] && "${_cand}" bash savelist > /dev/null 2>&1; then + MODULECMD_BIN="${_cand}" + break + fi + done + if [ -n "${MODULECMD_BIN}" ]; then + echo_info "Using modulecmd at ${MODULECMD_BIN}" + elif [ "${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG}" ]; then + echo_error "Alternative-reco (2-tag) requested (ALIEN_JDL_O2DPG_ASYNC_RECO_TAG=${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG})" + echo_error "but no 'modulecmd' supporting saved collections (save/restore) was found." + echo_error " Looked at: \$MODULECMD='${MODULECMD}', /usr/bin/modulecmd, PATH, \$MODULESHOME/libexec/modulecmd." + echo_error " Diagnostics: MODULESHOME='${MODULESHOME}' PATH='${PATH}'" + exit 1 + else + echo_info "No 'modulecmd' found, but no alternative-reco tag is set, so 'module' is not needed; continuing." + fi + export MODULECMD_BIN module() { - eval "$(/usr/bin/modulecmd bash "$@")"; + if [ -z "${MODULECMD_BIN}" ]; then + echo_error "'module ${*}' invoked but no usable 'modulecmd' was found (see earlier diagnostics)." + return 127 + fi + eval "$("${MODULECMD_BIN}" bash "$@")"; } export -f module fi From f11f17ad58cc5e926bbc8c3ed80ebb971f2e87d8 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 16 Jul 2026 20:45:28 +0200 Subject: [PATCH 2/2] anchorMC: resolve modulecmd via readlink -f + /usr/share/Modules fallback Extend the modulecmd candidate search with 'readlink -f /usr/bin/modulecmd' and the canonical environment-modules install (/usr/share/Modules/{,*/}libexec/ modulecmd*). On some HPC/container setups /usr/bin/modulecmd is a *dangling* symlink (-> /etc/alternatives -> the real .tcl) that exec's as "No such file or directory"; resolving the link / probing the real install recovers when the binary is still reachable, and otherwise still fails hard (a Modules tree missing from the job's mount namespace is a site-side problem). cf. O2-7070 (Perlmutter). Co-Authored-By: Claude Opus 4.8 --- MC/run/ANCHOR/anchorMC.sh | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 8b814f05e..087b4870b 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -184,9 +184,18 @@ export > env_base.env # (was hardwired to /usr/bin/modulecmd) and verify it supports saved collections. Fail # hard -- but only when an alternative-reco tag is set, since single-tag jobs never call # 'module' -- instead of silently no-op'ing every 'module' call (cf. O2-7070). +# The candidate list also resolves symlinks ('readlink -f') and probes the canonical +# environment-modules install (/usr/share/Modules): on some HPC/container setups +# /usr/bin/modulecmd is a *dangling* symlink (-> /etc/alternatives -> the real .tcl), +# which exec's as "No such file or directory"; this recovers when the real binary is +# still reachable, and otherwise still fails hard (a genuinely missing Modules tree in +# the job's mount namespace is a site-side problem). if ! declare -F module > /dev/null; then MODULECMD_BIN="" - for _cand in "${MODULECMD}" "/usr/bin/modulecmd" "$(command -v modulecmd 2>/dev/null)" "${MODULESHOME:+${MODULESHOME}/libexec/modulecmd}"; do + for _cand in "${MODULECMD}" "/usr/bin/modulecmd" "$(command -v modulecmd 2>/dev/null)" \ + "${MODULESHOME:+${MODULESHOME}/libexec/modulecmd}" \ + "$(readlink -f /usr/bin/modulecmd 2>/dev/null)" \ + /usr/share/Modules/libexec/modulecmd* /usr/share/Modules/*/libexec/modulecmd*; do if [ -n "${_cand}" ] && [ -x "${_cand}" ] && "${_cand}" bash savelist > /dev/null 2>&1; then MODULECMD_BIN="${_cand}" break @@ -197,8 +206,9 @@ if ! declare -F module > /dev/null; then elif [ "${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG}" ]; then echo_error "Alternative-reco (2-tag) requested (ALIEN_JDL_O2DPG_ASYNC_RECO_TAG=${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG})" echo_error "but no 'modulecmd' supporting saved collections (save/restore) was found." - echo_error " Looked at: \$MODULECMD='${MODULECMD}', /usr/bin/modulecmd, PATH, \$MODULESHOME/libexec/modulecmd." - echo_error " Diagnostics: MODULESHOME='${MODULESHOME}' PATH='${PATH}'" + echo_error " Looked at: \$MODULECMD='${MODULECMD}', /usr/bin/modulecmd (+readlink -f), PATH," + echo_error " \$MODULESHOME/libexec/modulecmd, /usr/share/Modules/{,*/}libexec/modulecmd*." + echo_error " Diagnostics: MODULESHOME='${MODULESHOME}' /usr/bin/modulecmd -> '$(readlink -f /usr/bin/modulecmd 2>/dev/null)' PATH='${PATH}'" exit 1 else echo_info "No 'modulecmd' found, but no alternative-reco tag is set, so 'module' is not needed; continuing."