Я использую capistrano для развертывания приложения Ruby on Rails. Я ранее использовал Centos. В преобразовании моей задачи, которая будет использоваться с Ubuntu, у меня есть задача, которую я использовал для Centos, был:
capture("env | grep ENV_VAR").split("=").last
Это получило бы вывод той переменной в удаленной системе, которая будет использоваться в моем коде. Однако этот код, кажется, не работает с Ubuntu. Кто-либо может сказать мне, как я могу получить вывод переменной с помощью capistrano и человечности?
Я попробовал
capture("echo $ENV_VAR")
Но это распечатывает пустую строку. Я предполагаю, что проблемой является reated к "$", но я не уверен.
Спасибо за любую справку заранее.
Я наконец споткнулся через этот ответ. Способ сделать это должно загрузить оболочку удара и передать команду ему.
capture("/bin/sh -c 'echo $ENV_VAR'")
Использовать printenv
вместо этого, который не требует оболочки:
capture('printenv ENV_VAR')
Замена ENV_VAR
с названием переменной среды Вы хотите. Не предварительно ожидать $
.
Хотя printenv
не POSIX, системы GNU/Linux как Debian, Ubuntu, Fedora, и CentOS поддерживают его, потому что GNU, который Coreutils обеспечивает ему, и это работает над многими другой *, отклоняют системы, как FreeBSD. Причина необходимо использовать printenv
вместо env
это printenv ENV_VAR
производит значение ENV_VAR
, в то время как env ENV_VAR
попытки выполнить названную команду ENV_VAR
, который не является тем, что Вы хотите.
Остальная часть этого сообщения покрывает другие методы, их ограничения, и как они могут быть улучшены. Это - дополнительное чтение с тех пор printenv
просто и решает проблему полностью.
Ваш исходный метод, capture("env | grep ENV_VAR").split("=").last
, не должен использоваться даже в системе, где это, действительно кажется, работает, потому что это ненадежно. Это grep
s для имени переменной везде в VAR=val
строка, и таким образом возвратит результаты для переменных, имена которых - или даже оценивает - содержат название желаемой переменной. Используя ^ENV_VAR=
вместо ENV_VAR
решает эту проблему путем соответствия имени только, когда это появляется в начале строки (^
) и требование a =
символ для появления прямо после него. Однако для значения переменной среды возможно содержать =
символ, и так как Вы звоните split
и last
, Вы на самом деле получаете самую длинную запаздывающую подстроку значения, которое содержит нет =
. Даже при фиксации этого метод все еще напрасно сложен, когда все, в чем Вы нуждаетесь, printenv
.
Решение Вы нашли, capture("/bin/sh -c 'echo $ENV_VAR'")
, будет работать большую часть времени, но возвратит неправильное значение, когда переменная (a) содержит пробел кроме символов одиночного пробела, окруженных непробелом, или (b) содержит globbing символы как *
, ?
, и [
если они, оказывается, соответствуют каким-либо именам файлов. Проблема состоит в том, что, в оболочке управляют echo $ENV_VAR
, расширение параметра $ENV_VAR
не заключается в кавычки, таким образом, разделение слова и globbing выполняются. echo
повторно вставляет пробел, но не всегда таким же образом: echo foo bar
печать foo bar
, но так делает echo foo bar
. Эта проблема может быть решена путем размещения "
"
кавычки вокруг расширения, хотя необходимо будет или выйти из них так интерпретатор Ruby, не берут их в качестве окончания "
- заключенная в кавычки строка и запуск нового, или Вы можете '
- заключите строку Ruby в кавычки и выйдите из любого внутреннего '
персонажи.
Вы также получаете неправильный результат в менее общей ситуации что значение ENV_VAR
начинается с опции это echo
поддержки. Отличающийся echo
реализации поддерживают различные варианты; -n
и -e
распространены. Большинство оболочек имеет echo
как встроенное и может поддерживать различные варианты от других оболочек и от /bin/echo
. Это должно сказать это echo
не является очень портативным. Разумно для осмотра переменных среды в интерактивном режиме, когда Вы, вероятно, поймете, происходит ли что-то нечетное, но меньше для сценариев. echo
горе мобильности усилено как /bin/sh
не всегда bash
. В Ubuntu это dash
. При помощи этого можно избежать printf '%s\n'
или printf "%s\n"
вместо echo
(или, в Вашем случае, printf %s
мог бы быть достаточным).
Таким образом Ваше решение может быть улучшено до capture('/bin/sh -c \'printf "%s\n" "$ENV_VAR"\'')
. Это может выглядеть неправильным опытным сценаристам оболочки, которые не знают Ruby; обратите внимание, что Ruby, в отличие от Bash и других оболочек стиля Границы, рассматривает \'
как литерал '
внутри a '
'
- заключенная в кавычки строка. Даже при том, что это корректно, Ваши коллеги должны будут посмотреть на него дважды для удовлетворения этого, даже если они являются опытными и в Ruby и в сценариях оболочки. capture('printenv ENV_VAR')
более просто.