diff --git a/easybuild/tools/run.py b/easybuild/tools/run.py index 5477e07d2e..8981b6ba41 100644 --- a/easybuild/tools/run.py +++ b/easybuild/tools/run.py @@ -273,14 +273,16 @@ def create_cmd_scripts(cmd_str, work_dir, env, tmpdir, out_file, err_file): # Make script that sets up bash shell with specified environment and working directory cmd_fp = os.path.join(tmpdir, 'cmd.sh') - # using -i to force interactive shell, so env.sh is also sourced when -c is used to run commands - launch_cmd = 'bash --rcfile $EB_SCRIPT_DIR/env.sh -i "$@"' - + launch_cmd = 'bash' # prefix launch command with bwrap (if used) bwrap_cmd = os.getenv('EB_BWRAP_CMD') if bwrap_cmd: launch_cmd = bwrap_cmd + ' ' + launch_cmd + # using -i for interactive shell, so env.sh is sourced + launch_cmd_interactive = f'{launch_cmd} --rcfile $EB_SCRIPT_DIR/env.sh -i' + launch_cmd_with_args = f'BASH_ENV=$EB_SCRIPT_DIR/env.sh {launch_cmd} "$@"' + with open(cmd_fp, 'w') as fid: fid.write('#!/usr/bin/env bash\n') fid.write('# Run this script to set up a shell environment that EasyBuild used to run the shell command\n') @@ -288,7 +290,11 @@ def create_cmd_scripts(cmd_str, work_dir, env, tmpdir, out_file, err_file): 'EB_SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )', f'echo "# Shell for the command: \'"{shlex.quote(cmd_str)}"\'"', 'echo "# Use command history, exit to stop"', - launch_cmd, + 'if [ "$#" -eq 0 ]; then', + ' ' + launch_cmd_interactive, + 'else', + ' ' + launch_cmd_with_args, + 'fi', ])) os.chmod(cmd_fp, 0o775) diff --git a/test/framework/run.py b/test/framework/run.py index 5536570a77..59e04c27ae 100644 --- a/test/framework/run.py +++ b/test/framework/run.py @@ -266,20 +266,23 @@ def test_run_shell_cmd_basic(self): cmd_script = os.path.join(cmd_tmpdir, 'cmd.sh') self.assertExists(cmd_script) - cmd = f"{cmd_script} -c 'echo pwd: $PWD; echo $FOOBAR; echo $EB_CMD_OUT_FILE; cat $EB_CMD_OUT_FILE'" + cmd = f"{cmd_script} -c '" + cmd += 'echo pwd: $PWD; echo "bash_env: $BASH_ENV"; echo $FOOBAR; echo $EB_CMD_OUT_FILE; cat $EB_CMD_OUT_FILE' + cmd += "'" with self.mocked_stdout_stderr(): res = run_shell_cmd(cmd, fail_on_error=False) self.assertEqual(res.exit_code, 0) - regex = re.compile("pwd: .*\nfoobar\n.*/echo-.*/out.txt\nhello$") + regex = re.compile("pwd: .*\nbash_env: .*\nfoobar\n.*/echo-.*/out.txt\nhello$") self.assertTrue(regex.search(res.output), f"Pattern '{regex.pattern}' should be found in {res.output}") # check whether working directory is what's expected - regex = re.compile('^pwd: .*', re.M) - res = regex.findall(res.output) - self.assertEqual(len(res), 1) - pwd = res[0].strip()[5:] + matches = re.findall('^pwd: (.*)', res.output, re.M) + self.assertEqual(len(matches), 1) + pwd = matches[0] self.assertTrue(os.path.samefile(pwd, self.test_prefix)) + # BASH_ENV is that of the current shell, not the one set in the cmd.sh + self.assertEqual(re.search('^bash_env: (.*)', res.output, re.M)[1], os.environ.get('BASH_ENV', '')) cmd = f"{cmd_script} -c 'module --version'" with self.mocked_stdout_stderr(): res = run_shell_cmd(cmd, fail_on_error=False)