Skip to content

Commit

Permalink
fix unsetting of current environment in env.sh script produced by run…
Browse files Browse the repository at this point in the history
…_shell_cmd
  • Loading branch information
boegel committed May 31, 2024
1 parent 3338c61 commit a2b9e06
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 8 deletions.
8 changes: 5 additions & 3 deletions easybuild/tools/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,15 @@ def create_cmd_scripts(cmd_str, work_dir, env, tmpdir):

env_fp = os.path.join(tmpdir, 'env.sh')
with open(env_fp, 'w') as fid:
# unset all environment variables in current environment first to start from a clean slate;
# we need to be careful to filter out functions definitions, so first undefine those
fid.write("unset -f $(env | grep '%=' | cut -f1 -d'%' | sed 's/BASH_FUNC_//g')\n")
fid.write("unset $(env | cut -f1 -d=)\n")

# excludes bash functions (environment variables ending with %)
fid.write('\n'.join(f'export {key}={shlex.quote(value)}' for key, value in sorted(env.items())
if not key.endswith('%')) + '\n')

# unset environment variables in current environment if they're not defined in environment used to run command
fid.write('\n'.join(f'unset {key}' for key in os.environ if key not in env and not key.endswith('%')))

fid.write('\n\nPS1="eb-shell> "')

# also change to working directory (to ensure that working directory is correct for interactive bash shell)
Expand Down
16 changes: 11 additions & 5 deletions test/framework/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,10 @@ def test_run_shell_cmd_basic(self):
self.assertIn("history -s 'echo hello'", env_script_txt)

with self.mocked_stdout_stderr():
res = run_shell_cmd(f"source {env_script}; echo $FOOBAR; history")
res = run_shell_cmd(f"source {env_script}; echo $USER; echo $FOOBAR; history")
self.assertEqual(res.exit_code, 0)
self.assertTrue(res.output.startswith('foobar\n'))
user = os.getenv('USER')
self.assertTrue(res.output.startswith(f'{user}\nfoobar\n'))
self.assertTrue(res.output.endswith("echo hello\n"))

# check on cmd.sh script that can be used to create interactive shell environment for command
Expand Down Expand Up @@ -268,18 +269,23 @@ def test_run_shell_cmd_env(self):
self.assertEqual(len(paths), 1)
cmd_tmpdir = paths[0]

# set environment variable in current environment,
# this should not be set in shell environment produced by scripts
os.environ['TEST123'] = 'test123'

env_script = os.path.join(cmd_tmpdir, 'env.sh')
self.assertExists(env_script)
env_script_txt = read_file(env_script)
self.assertTrue(env_script_txt.startswith('export FOOBAR=foobar\nexport PATH'))
self.assertTrue(env_script_txt.startswith('unset -f $('))
self.assertIn('\nexport FOOBAR=foobar\nexport PATH', env_script_txt)

cmd_script = os.path.join(cmd_tmpdir, 'cmd.sh')
self.assertExists(cmd_script)

with self.mocked_stdout_stderr():
res = run_shell_cmd(f"{cmd_script} -c 'echo $FOOBAR'", fail_on_error=False)
res = run_shell_cmd(f"{cmd_script} -c 'echo $FOOBAR; echo TEST123:$TEST123'", fail_on_error=False)
self.assertEqual(res.exit_code, 0)
self.assertTrue(res.output.endswith('\nfoobar\n'))
self.assertTrue(res.output.endswith('\nfoobar\nTEST123:\n'))

def test_fileprefix_from_cmd(self):
"""test simplifications from fileprefix_from_cmd."""
Expand Down

0 comments on commit a2b9e06

Please sign in to comment.