From 27f288d9f0d3c5f9d27730db01ac737a13e8b372 Mon Sep 17 00:00:00 2001 From: Kevin Pedro Date: Mon, 22 Sep 2025 18:07:20 -0500 Subject: [PATCH 1/5] first version with automatic condor OS setting --- call_host.sh | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/call_host.sh b/call_host.sh index 462f052..0773e3a 100755 --- a/call_host.sh +++ b/call_host.sh @@ -52,6 +52,19 @@ call_host_disable(){ } export -f call_host_disable +# provide htcondor-specific info in container +call_host_condor_os(){ + OS_VERSION="$1" + + declare -A CONDOR_OS + CONDOR_OS[7]="SL7" + CONDOR_OS[8]="EL8" + CONDOR_OS[9]="EL9" + + echo "${CONDOR_OS[$OS_VERSION]}" +} +export -f call_host_condor_os + # concept based on https://stackoverflow.com/questions/32163955/how-to-run-shell-script-on-host-from-docker-container # execute command sent to host pipe; send output to container pipe; store exit code @@ -63,6 +76,7 @@ listenhost(){ # using { bash -c ... } >& is less fragile than eval tmpexit=0 cmd="$(cat "$1")" +# echo "cmd: $cmd" { bash -c "$cmd" || tmpexit=$? } >& "$2" @@ -99,7 +113,21 @@ call_host(){ else FUNCTMP="${FUNCNAME[0]}" fi - echo "cd $PWD; $FUNCTMP $*" > "$HOSTPIPE" + + # extra environment settings for htcondor on cmslpc + # has to be set every time because commands are executed on host in subshell + EXTRA="" + if [[ "$(uname -a)" == *cms*.fnal.gov* ]]; then + OS_VERSION=$(sed -nr 's/[^0-9]*([0-9]+).*/\1/p' /etc/redhat-release 2>&1) + CONDOR_OS=$(call_host_condor_os "$OS_VERSION") + if [ -n "$CONDOR_OS" ]; then + EXTRA="export FERMIHTC_OS_OVERRIDE=$CONDOR_OS;" + else + EXTRA="echo \"could not determine condor OS from $OS_VERSION\";" + fi + fi + + echo "cd $PWD; $EXTRA $FUNCTMP $*" > "$HOSTPIPE" cat < "$CONTPIPE" return "$(cat < "$EXITPIPE")" } From 0492df02553eb06d85298d97258765999291a6d6 Mon Sep 17 00:00:00 2001 From: Kevin Pedro Date: Tue, 23 Sep 2025 13:51:24 -0500 Subject: [PATCH 2/5] refactor toward plugin system --- call_host.sh | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/call_host.sh b/call_host.sh index 0773e3a..3a4f144 100755 --- a/call_host.sh +++ b/call_host.sh @@ -52,18 +52,25 @@ call_host_disable(){ } export -f call_host_disable -# provide htcondor-specific info in container -call_host_condor_os(){ - OS_VERSION="$1" - +call_host_plugin_01(){ + # provide htcondor-specific info in container declare -A CONDOR_OS CONDOR_OS[7]="SL7" CONDOR_OS[8]="EL8" CONDOR_OS[9]="EL9" - echo "${CONDOR_OS[$OS_VERSION]}" + # todo: only activate if function name (call_host args) includes condor? + if [[ "$(uname -a)" == *cms*.fnal.gov* ]]; then + OS_VERSION=$(sed -nr 's/[^0-9]*([0-9]+).*/\1/p' /etc/redhat-release 2>&1) + CONDOR_OS_VAL="${CONDOR_OS[$OS_VERSION]}" + if [ -n "$CONDOR_OS_VAL" ]; then + echo "export FERMIHTC_OS_OVERRIDE=$CONDOR_OS_VAL;" + else + echo "echo \"could not determine condor OS from $OS_VERSION\";" + fi + fi } -export -f call_host_condor_os +export -f call_host_plugin_01 # concept based on https://stackoverflow.com/questions/32163955/how-to-run-shell-script-on-host-from-docker-container @@ -114,18 +121,9 @@ call_host(){ FUNCTMP="${FUNCNAME[0]}" fi - # extra environment settings for htcondor on cmslpc - # has to be set every time because commands are executed on host in subshell - EXTRA="" - if [[ "$(uname -a)" == *cms*.fnal.gov* ]]; then - OS_VERSION=$(sed -nr 's/[^0-9]*([0-9]+).*/\1/p' /etc/redhat-release 2>&1) - CONDOR_OS=$(call_host_condor_os "$OS_VERSION") - if [ -n "$CONDOR_OS" ]; then - EXTRA="export FERMIHTC_OS_OVERRIDE=$CONDOR_OS;" - else - EXTRA="echo \"could not determine condor OS from $OS_VERSION\";" - fi - fi + # extra environment settings; set every time because commands are executed on host in subshell + # todo: evolve into full plugin system that executes detected functions/executables in order (like config.d) + EXTRA="$(call_host_plugin_01)" echo "cd $PWD; $EXTRA $FUNCTMP $*" > "$HOSTPIPE" cat < "$CONTPIPE" From a132c948291130801ef315afeaa3530878e3c2a7 Mon Sep 17 00:00:00 2001 From: Kevin Pedro Date: Tue, 23 Sep 2025 14:53:18 -0500 Subject: [PATCH 3/5] add debug toggle --- call_host.sh | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/call_host.sh b/call_host.sh index 3a4f144..309c21b 100755 --- a/call_host.sh +++ b/call_host.sh @@ -8,14 +8,21 @@ if [ -f "$CALL_HOST_CONFIG" ]; then source "$CALL_HOST_CONFIG" fi +# validation +call_host_valid(){ + VAR_TO_VALIDATE="$1" + # shellcheck disable=SC2076 + if [[ ! " enable disable " =~ " ${!VAR_TO_VALIDATE} " ]]; then + echo "Warning: unsupported value ${!VAR_TO_VALIDATE} for $VAR_TO_VALIDATE; disabling" + eval "export $VAR_TO_VALIDATE=disable" + fi +} + # default values -# shellcheck disable=SC2076 -if [ -z "$CALL_HOST_STATUS" ]; then - export CALL_HOST_STATUS=enable -elif [[ ! " enable disable " =~ " $CALL_HOST_STATUS " ]]; then - echo "Warning: unsupported value $CALL_HOST_STATUS for CALL_HOST_STATUS; disabling" - export CALL_HOST_STATUS=disable -fi +: ${CALL_HOST_STATUS:=enable} +call_host_valid CALL_HOST_STATUS +: ${CALL_HOST_DEBUG:=disable} +call_host_valid CALL_HOST_DEBUG if [ -z "$CALL_HOST_DIR" ]; then if [[ "$(uname -a)" == *cms*.fnal.gov* ]]; then export CALL_HOST_DIR=~/nobackup/pipes @@ -51,6 +58,22 @@ call_host_disable(){ export CALL_HOST_STATUS=disable } export -f call_host_disable +# single toggle for debug printouts +call_host_debug(){ + if [ "$CALL_HOST_DEBUG" = "enable" ]; then + export CALL_HOST_DEBUG=disable + else + export CALL_HOST_DEBUG=enable + fi +} +export -f call_host_debug +# helper for debug printouts +call_host_debug_print(){ + if [ "$CALL_HOST_DEBUG" = "enable" ]; then + echo "$@" + fi +} +export -f call_host_debug_print call_host_plugin_01(){ # provide htcondor-specific info in container @@ -66,7 +89,7 @@ call_host_plugin_01(){ if [ -n "$CONDOR_OS_VAL" ]; then echo "export FERMIHTC_OS_OVERRIDE=$CONDOR_OS_VAL;" else - echo "echo \"could not determine condor OS from $OS_VERSION\";" + call_host_debug_print "echo \"could not determine condor OS from $OS_VERSION\";" fi fi } @@ -83,7 +106,7 @@ listenhost(){ # using { bash -c ... } >& is less fragile than eval tmpexit=0 cmd="$(cat "$1")" -# echo "cmd: $cmd" + call_host_debug_print "cmd: $cmd" { bash -c "$cmd" || tmpexit=$? } >& "$2" From 583e1f79ee74925dd56b266a4f0dd3752dfaf51b Mon Sep 17 00:00:00 2001 From: Kevin Pedro Date: Tue, 23 Sep 2025 14:53:22 -0500 Subject: [PATCH 4/5] update docs --- README.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 50a7b34..c204619 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ Table of Contents * [Automatic](#automatic) * [Details](#details) * [Options](#options) + * [HTCondor jobs](#htcondor-jobs) * [Caveats](#caveats) * [bind_condor.sh](#bind_condorsh) * [Usage](#usage-1) @@ -147,10 +148,19 @@ or placed in a file `~/.callhostrc` (automatically detected and sourced by `call ```bash CALL_HOST_STATUS=disable cmssw-el7 ... ``` +* To enable debug printouts by default: + ```bash + export CALL_HOST_DEBUG=enable + ``` + or to toggle debug printouts on or off during a session: + ```bash + call_host_debug + ``` + (if you call this inside a container, it will not silence debug printouts from the host) -### Caveats +### HTCondor jobs -* cmslpc autodetection of the correct operating system for jobs is currently based on the host OS. Therefore, if you are submitting jobs in a container with a different OS, you will have to manually specify in your JDL file (the `X` in `condor_submit X`): +* On cmslpc, the container OS will automatically be detected (for RHEL-based containers) and used for HTCondor jobs. To specify the job OS manually instead, include in your JDL file (the `X` in `condor_submit X`): ``` +DesiredOS = SL7 ``` @@ -160,6 +170,9 @@ or placed in a file `~/.callhostrc` (automatically detected and sourced by `call +ApptainerImage = "/path/to/your/container" ``` * Using the `ENV()` function in the JDL file may not function as intended, since it will be evaluated on the host node, rather than inside the container with your environment set up. + +### Caveats + * Commands that require tty input (such as `nano` or `emacs -nw`) will not work with `call_host`. * Occasionally, if a command fails (especially when calling multiple commands separated by semicolons), the pipe will break and the terminal will appear to hang. The message "Interrupted system call" may be shown. It is necessary to exit and reenter the container (in order to create a new pipe) if this occurs. From 8e424e48d00524e3ffc71c8f1702bb18af9143ff Mon Sep 17 00:00:00 2001 From: Kevin Pedro Date: Tue, 23 Sep 2025 15:00:24 -0500 Subject: [PATCH 5/5] disable incorrect warning --- call_host.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/call_host.sh b/call_host.sh index 309c21b..3535b12 100755 --- a/call_host.sh +++ b/call_host.sh @@ -1,5 +1,5 @@ #!/bin/bash -# shellcheck disable=SC2155 +# shellcheck disable=SC2155,SC2223 # check for configuration CALL_HOST_CONFIG=~/.callhostrc