我已经设法跟踪我正在工作的初始化脚本中的一个奇怪的问题。 我在下面的例子中简化了这个问题:
> set -x # <--- Make Bash show the commands it runs > cmd="echo \"hello this is a test\"" + cmd='echo "hello this is a test"' > $cmd + echo '"hello' this is a 'test"' # <--- Where have the single quotes come from? "hello this is a test"
为什么bash插入这些额外的单引号到执行的命令?
在上面的例子中,额外的引号不会造成任何问题,但它们真的让我很头疼。
对于好奇,实际的问题代码是:
cmd="start-stop-daemon --start $DAEMON_OPTS \ --quiet \ --oknodo \ --background \ --make-pidfile \ $* \ --pidfile $CELERYD_PID_FILE --exec /bin/su -- -c \"$CELERYD $CELERYD_OPTS\" - $CELERYD_USER"
这产生这个:
start-stop-daemon --start --chdir /home/continuous/ci --quiet --oknodo --make-pidfile --pidfile /var/run/celeryd.pid --exec /bin/su -- -c '"/home/continuous/ci/manage.py' celeryd -f /var/log/celeryd.log -l 'INFO"' - continuous
因此:
/bin/su: invalid option -- 'f'
注:我在这里使用su
命令,因为我需要确保用户的virtualenv是在celeryd运行之前设置的。 --chuid
不会提供这个
因为当你尝试执行你的命令
$cmd
只有一层扩展发生。 $cmd
包含echo "hello this is a test"
,它扩展到6个空格分隔的标记:
echo
"hello
this
is
a
test"
这就是set -x
输出向你展示的内容:它将包含双引号的记号放在单引号内,以清楚表示单个记号是什么。
如果你希望把$cmd
扩展成一个字符串,然后再应用所有的bash引用规则,试着用下面的命令执行你的命令:
bash -c "$cmd"
或者(如@bitmask在评论中指出的,这可能更有效)
eval "$cmd"
而不是仅仅
$cmd