我设法在正在处理的init脚本中完成了一个奇怪的问题。在下面的示例中,我将问题简化了:
> 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不会提供这个
su
--chuid
因为当您尝试执行命令时
$cmd
仅发生一层扩展。 $cmdcontains echo "hello this is a test",它扩展为6个以空格分隔的标记:
echo "hello this is a test"
echo
"hello
this
is
a
test"
这就是set -x输出显示的内容:它将单引号括在包含双引号的标记周围,以明确各个标记的含义。
set -x
如果要$cmd扩展为一个字符串,然后再次应用所有bash引用规则,请尝试使用以下命令执行命令:
bash -c "$cmd"
或(如@bitmask在注释中指出,这可能更有效)
eval "$cmd"
而不只是