我正在创建一个安装程序 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
。将按原样正常工作。
使用eval
或sh -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 {
}
但无需混合使用这两种语法;)