I'm writing a wrapper script. The original program's arguments are in a separate file, args
. The script needs to split contents of args
using shell parameter rules and then run the program. A partial solution (set
+ eval
) was offered in Splitting a string to tokens according to shell parameter rules without eval:
#!/usr/bin/env bash
STDOUT="$1"
STDERR="$2"
( set -f ; eval "set -- $(cat args)"; exec run_in_container "$@" >"$STDOUT" 2>"$STDERR" )
but in my case args
is user-generated. One can easily imagine
args
:echo "Hello, 'world'! $(rm -rf /)"
(not cool, but harmless: commands are run in a e.g. docker container)args
:bash -c "$JAVA_HOME/<...> > <...> && <...>"
(harmful:$JAVA_HOME
was intended to be container's value of environment variableJAVA_HOME
, but actually will be substituted earlier, wheneval
'ing the command in the wrapper script's subshell.)
I tried Python, and this works:
#!/usr/bin/env python
import shlex, subprocess, sys
with open('args', 'r') as argsfile:
args = argsfile.read()
with open(sys.argv[1], 'w') as outfile, open(sys.argv[2], 'w') as errfile:
exit(subprocess.call(["run_in_container"] + shlex.split(args), stdout=outfile, stderr=errfile))
Is there a way to do shlex
in bash: tokenize the string using shell parameter rules, but don't substitute any variables' values, don't execute $(...)
etc.?