Lug*_*axx 6 scripting bash shell-script
我必须编写一个 Bash 脚本来检查另一个 Bash 脚本是否包含某个命令行。由于 Bash 允许您将命令行拆分为多行,因此我的脚本必须能够在进行实际模式匹配之前合并相应的行。
如何在 Bash 脚本中将所有多行解析为单行命令?
例子
我想检查某个脚本是否包含ls命令 - 如果它包含ls命令,我想知道将哪些参数传递给ls命令。要回答这个问题,我可以使用sed。但因此我必须先合并所有多行命令。
输入:
# My comment \
ls \
-a \
-l
Run Code Online (Sandbox Code Playgroud)
输出:
# My comment \
ls -a -l
Run Code Online (Sandbox Code Playgroud)
无效输出示例:
# My comment ls -a -l
Run Code Online (Sandbox Code Playgroud)
就在 shellshock 之前,我在 StackOverflow 上回答了一个关于消除 bash 脚本中的注释的问题。我的回答使用了通过将脚本文件的内容包含在 中来创建函数的简单技巧tmp_() { ... }
,然后使用declare -f tmp_
来漂亮地打印函数。在漂亮打印的输出中,没有注释,并且以反斜杠换行符继续的行已解析为单行。(除了内部反引号命令替换。)
还进行了其他一些重新格式化。例如,复合命令被分成几行。并且某些形式的行延续没有重新格式化;例如,以管道符号结尾的行不会改变。但它应该满足这个问题中的用例。(请参阅下面的示例输出。)
当然,需要对函数定义进行评估,这意味着被漂亮打印的脚本可能包含注入攻击。在我建议的代码中,函数定义是通过 bash 功能评估的,该功能允许导出函数并与子进程共享。在我写这个小技巧的时候,我相信这个机制比调用 更安全eval
,但事实证明我错了。
自 shellshock 以来,对 bash 用于导入函数定义的代码进行了许多改进,至少关闭了一些注入攻击的大门,但显然不能保证该过程是完全安全的。
如果您要运行正在分析的脚本,那么使用此过程来漂亮地打印它可能不会增加您的漏洞;攻击者可以简单地直接在脚本中插入危险代码,而无需通过可能绕过函数导入代码中的安全检查的方式跳过箍来隐藏攻击。
尽管如此,您应该仔细考虑安全问题,无论是使用这个小程序还是使用您可能必须执行任意脚本的任何计划。
这是漂亮打印机的版本,它适用于后 shellshock 修补的 bash(并且不适用于以前的 bash 版本):
env "BASH_FUNC_tmp_%%=() {
$(<script_name)
}" bash -c 'declare -f tmp_' | tail -n+2
Run Code Online (Sandbox Code Playgroud)
将包含脚本的文件名替换为script_name
, 在第二行中。您可能想要调整tail
命令;它会删除包装函数名称,但不会删除围绕脚本主体的大括号。
可以在引用的 SO 答案中找到原始版本,该版本适用于 bash 的 pre-shellshock 版本。
根据Stéphane Chazelas提供的输入进行测试:
{
echo \\;
echo a#b;
echo 'foo\
bar';
cat <<EOF
thisis joined
this 'aswell'
$(ls -l)
EOF
cat <<'EOF'
this is\
not joined
EOF
echo "$(ls -l)";
echo `ls \\
-l`
}
Run Code Online (Sandbox Code Playgroud)
这与 Stéphane 的建议输出不同:
cat << E\OF
已更改为cat <<'EOF'
,这在语义上是相同的。$(...)
命令替换中的续行被删除。)