我设法在我正在处理的初始化脚本中跟踪完成了一个奇怪的问题。我在以下示例中简化了问题:
> 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
命令,因为我需要确保在运行 celeryd 之前设置用户的 virtualenv。 --chuid
不会提供这个
最佳答案
因为当你尝试执行你的命令时
$cmd
只有一层膨胀发生。 $cmd
包含 echo "hello this is a test"
,扩展为 6 个空格分隔的标记:
回显
“你好
这个
是
一个
测试”
这就是 set -x
输出向您展示的内容:它在包含双引号的标记周围加上单引号,以便清楚各个标记是什么。
如果您希望将 $cmd
扩展为一个字符串,然后再次应用所有 bash 引用规则,请尝试执行您的命令:
bash -c "$cmd"
或者(正如@bitmask 在评论中指出的那样,这可能更有效)
eval "$cmd"
不仅仅是
$cmd
关于Bash在执行前将引号插入字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6087494/