Враховуючи, що консенсус, схоже, віддає перевагу #sh
методу rake , але OP явно вимагає bash, ця відповідь може мати певне значення.
Це актуально, оскільки Rake#sh
використовує Kernel#system
виклик для запуску команд оболонки. Застосовуйте жорсткі коди Ruby /bin/sh
, ігноруючи налаштовану користувачем оболонку або $SHELL
в оточенні.
Ось обхідний шлях, який викликає bash з /bin/sh
, дозволяючи вам як і раніше використовувати sh
метод:
task :hello_world do
sh <<-EOS.strip_heredoc, {verbose: false}
/bin/bash -xeu <<'BASH'
echo "Hello, world!"
BASH
EOS
end
class String
def strip_heredoc
gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, ''.freeze)
end
end
#strip_heredoc
запозичено з рейок:
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/string/strip.rb
Можливо, ви могли б отримати його, вимагаючи active_support, або, можливо, він завантажується автоматично, коли ви перебуваєте у проекті рейок, але я використовував це зовнішні рейки, і тому мені довелося його самому захищати.
Є два гередоки, зовнішній із маркерами EOS
та внутрішній із маркерами BASH
.
Це працює шляхом подачі внутрішнього гередоку між маркерами BASH до stdin bash. Зверніть увагу, що він працює в контексті /bin/sh
, тому це posix heredoc, а не рубіновий. Зазвичай для цього потрібно, щоб кінцевий маркер знаходився у стовпці 1, що тут не так через відступ.
Однак, оскільки він загорнутий у рубіновий гередок, strip_heredoc
застосований там метод робить його відступами, розміщуючи всю ліву сторону внутрішнього гередоку в стовпці 1 перед тим, /bin/sh
як його побачити.
/bin/sh
також, як правило, розширює змінні всередині heredoc, що може перешкоджати сценарію. /bin/sh
Поодинокі лапки навколо маркера старту, 'BASH', вказують не розширювати нічого всередині heredoc, перш ніж він буде переданий bash.
Однак /bin/sh
все ще застосовує екранування до рядка перед передачею його в bash. Це означає, що екрани зворотної риски слід подвоїти, щоб пройти через /bin/sh
bash, тобто \
стає \\
.
Параметри bash -xeu
необов’язкові.
В -eu
аргументах кажуть Башу працювати в суворому режимі, який зупиняє виконання за будь-якої несправності або посилань на невизначений змінний. Це поверне помилку рейку, що зупинить завдання граблі. Зазвичай, це те, що ви хочете. Аргументи можна скинути, якщо ви хочете нормальної поведінки bash.
-x
bash і {verbose: false}
аргумент для спільної #sh
роботи, так що rake друкує лише команди bash, які фактично виконуються. Це корисно, якщо ваш скрипт bash не призначений для роботи в повному обсязі, наприклад, якщо у нього є тест, який дозволяє йому вийти вишукано на початку сценарію.
Будьте обережні, не встановлюйте код виходу, відмінний від 0, якщо ви не хочете, щоб завдання граблі провалилося. Зазвичай це означає, що ви не хочете використовувати будь-які || exit
конструкції без явного встановлення коду виходу, тобто || exit 0
.
%{
, це%x(
, і це повертає stdout як рядок, замість того, щоб його друкувати.