我试图用来eval运行传递给函数的命令$@.
这是我的代码:
run_command() {
: some logic not relevant to this question
eval "$@"
}
Run Code Online (Sandbox Code Playgroud)
我正在运行它:
run_command "ls" "|" "wc -l" # works, runs "ls | wc -l"
run_command "ls | wc -l" # works as above
Run Code Online (Sandbox Code Playgroud)
现在,我尝试列出一个包含空格的文件:
> "file with space"
run_command "ls" "-l" "file with space"
Run Code Online (Sandbox Code Playgroud)
这一次,我得到了这些错误:
ls: file: No such file or directory
ls: space: No such file or directory
ls: with: No such file or directory
Run Code Online (Sandbox Code Playgroud)
因此,很明显"$@"会导致单词分裂.有没有办法防止这个问题,以便run_command功能免受白色空间,小球和任何其他特殊字符的影响?
eval将所有参数组合成单个字符串,并将该字符串作为代码进行计算.因此,eval "ls" "-l" "file with space"与eval ls -l file with space或完全相同eval "ls -l file with space".
正如BashFAQ#50中给出的那样 - 以下运行其精确的参数列表作为简单命令的参数向量.
run_command() {
"$@"
}
Run Code Online (Sandbox Code Playgroud)
这提供了许多保证:
>foo将传递具有精确字符串的数组条目,而不是导致foo创建名为的文件.如果需要使用管道包装命令,可以通过将该管道封装在函数中来完成:
run_pipeline() { foo "$@" | bar; }
run_command run_pipeline "argument one" "argument two"
Run Code Online (Sandbox Code Playgroud)
要明确:我不建议使用此代码.通过免除|以下最佳做法提供的通常保护,它削弱了所述做法所提供的安全性.但是,它确实按照你的要求行事.
run_command() {
local cmd_str='' arg arg_q
for arg; do
if [[ $arg = "|" ]]; then
cmd_str+=" | "
else
printf -v arg_q '%q' "$arg"
cmd_str+=" $arg_q"
fi
done
eval "$cmd_str"
}
Run Code Online (Sandbox Code Playgroud)
在这种形式中,参数|将导致生成的字符串包含复合命令,在该参数的位置拆分为简单命令.
现在 - 为什么尝试在这种情况下允许语法元素被处理为坏主意?考虑以下:
echo '<hello>'
Run Code Online (Sandbox Code Playgroud)
这里,字符串中的<和已被引用,因此不再具有其原始行为.但是,一旦将这些值分配给数组或参数列表,就像在><hello>
args=( 'echo' '<hello>' )
Run Code Online (Sandbox Code Playgroud)
...不再存在关于引用或不引用哪些字符的元数据.从而,
echo hello '|' world
Run Code Online (Sandbox Code Playgroud)
变得完全无法区分
echo hello | world
Run Code Online (Sandbox Code Playgroud)
即使作为单独的命令,这些行为也会有不同的行为.
考虑以下:
run_command rm -rf -- "$tempdir" "$pidfile"
Run Code Online (Sandbox Code Playgroud)
在"最佳实践"示例中,无论这些值是什么,都可以保证将传递给的文件名tempdir和pidfile文件名都视为文件名rm.
但是,使用"允许管道"示例,上面可以调用rm -rf -- | arbitrary-command-here,应该tempfile='|'和pidfile=arbitrary-command-here.
为壳变量从该组当前的环境变量的初始化,和环境变量是经常外部可控-这表现在用于远程攻击的存在弹震 -这不是一个纯理论的或空闲的关注.
| 归档时间: |
|
| 查看次数: |
287 次 |
| 最近记录: |