Bash вставка цитат в строку перед выполнением
Мне удалось отслеживать сложную проблему в init script, над которой я работаю. Я упростил проблему в следующем примере:
> 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
не предоставит этого
Ответы
Ответ 1
Потому что, когда вы пытаетесь выполнить команду с помощью
$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