Skip to content

[Bug]: [runner] Exported Bash functions corrupt /dstack/profile #4161

Description

@un-def

Steps to reproduce

Perhaps there is an easier way to reproduce it, but this is the actual setup in which the issue was discovered:

  1. Configure a Slurm cluster as a dstack backend. Important: nodes must use a distro where /bin/sh is Bash (readlink -f /bin/sh/usr/bin/bash). We deployed a cluster using GCP's cluster-toolkit, which uses Rocky Linux.
  2. Export a Bash function function via profile, e.g., add to ~/.bash_profile:
    say_hi() { echo hi; }
    export -f say_hi
    The image used by GCP's cluster-toolkit has Lmod preinstalled, which exports its functions.
  3. Submit a run with image based on a distro where /bin/sh is Bash, e.g., Fedora:
    type: task
    image: fedora
    commands:
      - printenv | grep BASH_FUNC_
  4. SSH into the run
  5. grep BASH_FUNC_ /dstack/profile

The reason why we need a distro with shbash symlink is that (d)ash (used by, e.g., Debian/Ubuntu) removes invalid variables (BASH_FUNC_<name>%% format with % is intentionally used by Bash; such a name is not a valid shell identifier) while Bash in POSIX mode bypass them to child processes (and, apparently, even source them). With the Slurm backend, we have 3 sh calls in the chain:

Actual behaviour

Run commands output:

BASH_FUNC_ml%%=() {  eval $($LMOD_DIR/ml_cmd "$@")
BASH_FUNC_which%%=() {  ( alias;
BASH_FUNC_say_hi%%=() {  echo hi
BASH_FUNC_module%%=() {  eval $($LMOD_CMD bash "$@") && eval $(${LMOD_SETTARG_CMD:-:} -s sh)

ssh run-name output:

Warning: Permanently added '[slurm-mainnodeset-0]:10022' (ED25519) to the list of known hosts.
-bash: export: `BASH_FUNC_which%%=() {  ( alias;
 eval ${which_declare} ) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot $@
}': not a valid identifier
-bash: export: `BASH_FUNC_ml%%=() {  eval $($LMOD_DIR/ml_cmd "$@")
}': not a valid identifier
-bash: export: `BASH_FUNC_say_hi%%=() {  echo hi
}': not a valid identifier
-bash: export: `BASH_FUNC_module%%=() {  eval $($LMOD_CMD bash "$@") && eval $(${LMOD_SETTARG_CMD:-:} -s sh)
}': not a valid identifier

grep BASH_FUNC_ /dstack/profile:

export BASH_FUNC_which%%='() {  ( alias;
export BASH_FUNC_ml%%='() {  eval $($LMOD_DIR/ml_cmd "$@")
export BASH_FUNC_say_hi%%='() {  echo hi
export BASH_FUNC_module%%='() {  eval $($LMOD_CMD bash "$@") && eval $(${LMOD_SETTARG_CMD:-:} -s sh)

Expected behaviour

No response

dstack version

0.21.1

Server logs

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions