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. diff --git a/call_host.sh b/call_host.sh index 462f052..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 @@ -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,42 @@ 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 + declare -A CONDOR_OS + CONDOR_OS[7]="SL7" + CONDOR_OS[8]="EL8" + CONDOR_OS[9]="EL9" + + # 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 + call_host_debug_print "echo \"could not determine condor OS from $OS_VERSION\";" + fi + fi +} +export -f call_host_plugin_01 # concept based on https://stackoverflow.com/questions/32163955/how-to-run-shell-script-on-host-from-docker-container @@ -63,6 +106,7 @@ listenhost(){ # using { bash -c ... } >& is less fragile than eval tmpexit=0 cmd="$(cat "$1")" + call_host_debug_print "cmd: $cmd" { bash -c "$cmd" || tmpexit=$? } >& "$2" @@ -99,7 +143,12 @@ call_host(){ else FUNCTMP="${FUNCNAME[0]}" fi - echo "cd $PWD; $FUNCTMP $*" > "$HOSTPIPE" + + # 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" return "$(cat < "$EXITPIPE")" }