我有一个父脚本
while read cmd
do
nohup ./script ${cmd[@]} &>> log &
done < ~/list
执行这个子脚本
while true
do
eval "${CMD[@]}"
#${CMD[@]}
#./panic
done
与这个命令列表
node ~/www/splash/app.js
node ~/www/splash-two/app.js
当子脚本调用时,eval ${CMD[@]}
它会按照我期望的方式运行该命令,没有任何抱怨,但是当我尝试删除 eval 并使用${CMD[@]}
它运行命令时,会抛出错误:
Error: Cannot find module '/home/rumplefraggle/SYS/RABBOT/~/www/splash/app.js'
现在我认为这可能与节点命令有关,所以我尝试
ls ~
作为命令执行,但它抛出了~
无法找到的错误。
回显${@}
而不运行它会像我期望的那样扩展。
另外,手动将命令插入子脚本中也可以按预期工作
我不明白为什么eval
有效并且简单地使用命令运行${@}
却不起作用。是什么原因导致${@}
无法扩展~
?
${@}
为什么节点在使用时将目录名称附加到命令中?
答案1
这是因为波形符扩展。 eval 扩展波浪号,将其替换为主目录的完整路径。如果没有它,该命令将获取传递的文字波形符,并尝试使用相对路径(不存在)。
$ echo ~
/home/chris
$ echo "~"
~
$ eval 'echo ~'
/home/chris
答案2
您需要报价:"${cmd[@]}"
如果没有引号,数组的所有元素都会被压缩成一个字符串。使用引号,每个元素都将被单独正确处理。
从手册:
如果下标是
‘@’
or‘*’
,该词扩展到数组的所有成员姓名。仅当单词出现在双引号内时,这些下标才会有所不同。如果该词被双引号括起来,[...]${name[@]}
将名称的每个元素扩展为单独的单词。