传递命令以在 Bash 中运行



我正在创建一个安装程序 bash 脚本,以便我可以快速设置我的服务器。

在 run 函数中,我想传递命令,然后 run 函数将验证该命令是否成功。

function run () {
if output=$( $1 ); 
then printf 'OK. («%s»)n' "$output"; 
else printf 'Failed! («%s»)n' "$output"; 
fi
}
printf 'Setting up «uni» as system group...'
run " if [ ! $( getent group uni ) ]; 
then sudo addgroup --system uni; 
else echo 'Group exists.'; 
fi "

但是,这会导致错误:setup.sh: line 5: if: command not found

当我这样做时,它工作正常,但我想消除重复的代码,因为我有很多命令:

if output=$(
if [ ! $( getent group uni ) ]; then sudo addgroup --system uni; else echo 'Group exists.'; fi
); 
then printf 'OK. («%s»)n' "$output"; 
else printf 'Failed! («%s»)n' "$output"; 
fi

我做错了什么?

将代码传递给函数的安全方法是...将该代码封装在另一个函数中。

run() {
local output
if output=$("$@"); then 
printf 'OK. («%s»)n' "$output"; 
else
printf 'Failed! («%s»)n' "$output"; 
fi
}
printf 'Setting up «uni» as system group...'
step1() {
if [ ! "$(getent group uni)" ]; then 
sudo addgroup --system uni; 
else
echo 'Group exists.'; 
fi
}
run step1

如果你的代码不涉及流控制运算符(并且符合"简单命令"的定义),你甚至不需要这样做;使用上面的run定义(使用"$@"而不是$1),

run sudo addgroup --system uni

。将按原样正常工作。


使用evalsh -c都会使您面临严重的安全问题;有关高级概述,请参阅 BashFAQ #48,请参阅 BashFAQ #50 以讨论为什么代码不应作为文本传递(以及首先避免需要这样做的首选方法!

您已选择将 shell 命令字符串传递给您的函数(也称为system(3)语义)。这意味着您必须使用eval来评估它:

function run () {
if output=$( eval "$1" ); 
then printf 'OK. («%s»)n' "$output"; 
else printf 'Failed! («%s»)n' "$output"; 
fi
}

请注意,带有命令的参数将正常展开,因此如果您希望在run函数中而不是在其之前计算$(getent),则需要对其进行转义:

run " if [ ! $( getent group uni ) ]; 
then sudo addgroup --system uni; 
else echo 'Group exists.'; 
fi "

如果你想将一段 bash 代码作为函数 args 传递,以便在子 shell 中进行评估并测试成功,你可以这样做:

#!/bin/bash 
run () {
# Here I'm not sure what you want to test, so I assume that you want to test if the piece of bash pass as an arg is failing or not
# Do not forget to quote the value in order to take all the string
# You can also try with "eval" instead of "bash -c"
if output=$( bash -c "${1}" ); then 
echo "OK. («${output}»)"
else 
echo "Failed! («${output}»)" 
fi
}
# Do not forget to escape the $ here to be evaluated after in the `run` function
# Do not forget to exit with a code different of 0 to indicate there is a failure for the test in the "run" function
run "if [[ ! $( getent group uni ) ]]; then sudo addgroup --system uni else echo 'Group exists.'; exit 1; fi"

警告:我发布了这段代码,以使您的脚本按照您似乎想要的方式工作(有一个函数可以从字符串中评估您的代码并解释结果),但由于这个原因,它根本不安全正如Charles Duffy在评论部分指出的那样。

制作类似的东西可能更安全:

#!/bin/bash
run () {
if output=$("${@}"); then 
echo "OK. («${output}»)"
else 
echo "Failed! («${output}»)" 
fi
}
one_of_your_functions_you_want_to_eval() {
if [[ ! $( getent group uni ) ]]; then 
sudo addgroup --system uni 
else 
echo 'Group exists.'
# do not forget to exit with something different than 0 here
exit 1
fi
}
run one_of_your_functions_you_want_to_eval

注意:为了声明一个函数,你可以像这样声明它(符合POSIX的语法):

your_function() {
}

要么只使用 bash 语法(我认为最好避免"bashism",因为它没有给你的脚本带来真正的价值):

function your_function {
}

但无需混合使用这两种语法;)

相关内容

  • 没有找到相关文章

最新更新