[英]Escape single quote inside double quote for executing a command in shell scripting
function install_rubygems {
#install rubygems
ruby_cmd=("sudo gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3"
"bash -c 'curl -sSL https://get.rvm.io|bash -s stable'"
"source /etc/profile.d/rvm.sh"
#"rvm install 1.9.2 --with-zlib-directory=/usr/local/rvm/usr --with-openssl-directory=/usr/local/rvm/usr"
#"rvm --default use 1.9.2"
#"gem install soap4r-ruby1.9 log4r net-ldap json httpclient"
)
for cmd in "${ruby_cmd[@]}"
do
$cmd
exit_status=$?
if [ "$exit_status" -ne "0" ]; then
echo "Error occured while running: $cmd. Exiting..."
exit
fi
done
}
我要一一执行ruby_cmd数组中列出的命令,然后检查每个命令的退出状态并在此之后执行一些操作。 但是,当我在shell中执行上述脚本时,出现以下错误:
-sSL:-c:第0行:寻找匹配的`''时出现意外的EOF -sSL:-c:第1行:语法错误:文件意外结束
我对Shell脚本还很陌生,有人可以告诉我编写上述命令的正确方法是什么? PS:命令是正确的,并且如果直接在bash上运行,它将正确执行
有关该主题的一般讨论,请参见BashFAQ#50 。
有几种方法可用:
install_rubygems() {
sudo gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 && \
curl -sSL https://get.rvm.io | bash -s stable && \
source /etc/profile.d/rvm.sh
)
install_rubygems || {
retval=$?
echo "Error occurred while running; exiting..." >&2
exit "$retval"
}
仅当您的字符串都不能包含用户输入时,此方法才是安全的。 否则,它将使您容易受到shell注入攻击。
install_rubygems=(
"sudo gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3"
"curl -sSL https://get.rvm.io | bash -s stable"
"source /etc/profile.d/rvm.sh"
)
for cmd in "${install_rubygems[@]}"; do
eval "$cmd" || {
retval=$?
echo "Error occurred while running $cmd; exiting..." >&2
exit "$retval"
}
done
因为这里的每个数组只有一个简单的命令-在评估时没有管道,没有间接调用,没有执行替换-因此它比eval
方法更安全:仅在通过扩展显式运行代码的地方放置(例如bash -c
的参数) bash -c
或显式的eval
)容易发生不确定的行为,因此您可以放心地在其他位置(例如--keyserver
的参数)使用不受信任的数据,即使外壳不会对它造成任何不良影响,也可以放心使用数据正在尝试进行外壳注入攻击。
install_rubygems_01=( sudo gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 )
install_rubygems_02=( eval 'curl -sSL https://get.rvm.io | bash -s stable' )
install_rubygems_03=( source /etc/profile.d/rvm.sh )
for varname in "${!install_rubygems_@}"; do
# there's a safer way to do this in bash 4.3, but that's not widely deployed yet
# (this particular command shouldn't ever be unsafe unless varname has been tampered
# with, but it had to be constructed very carefully).
eval "cmd=( \"\${$varname[@]}\" )"
## ...specifically, in bash 4.3, you could do this instead of the above eval:
#declare -n cmd=$varname
# evaluate array as an exact argv
"${cmd[@]}" || {
retval=$?
printf -v cmd_str '%q ' "${cmd[@]}"
echo "Error occurred while running ${cmd_str% }; exiting..." >&2
exit "$retval"
}
##Using bash 4.3 namevars instead of the eval above, you'd want to do this here:
#unset -n cmd
done
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.