Angesichts der Tatsache, dass der Konsens die #sh
Methode von Rake zu bevorzugen scheint , OP jedoch ausdrücklich Bash anfordert, kann diese Antwort von Nutzen sein.
Dies ist relevant, da Rake#sh
der Kernel#system
Aufruf zum Ausführen von Shell-Befehlen verwendet wird. Ruby codiert das fest /bin/sh
und ignoriert dabei die konfigurierte Shell des Benutzers oder $SHELL
die Umgebung.
Hier ist eine Problemumgehung, mit der bash aufgerufen wird /bin/sh
, sodass Sie die sh
Methode weiterhin verwenden können :
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
wird von Schienen ausgeliehen:
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/string/strip.rb
Sie könnten es wahrscheinlich erhalten, indem Sie active_support benötigen, oder es wird automatisch geladen, wenn Sie sich in einem Rails-Projekt befinden, aber ich habe diese externen Rails verwendet und musste es daher selbst definieren.
Es gibt zwei Heredocs, einen äußeren mit den Markern EOS
und einen inneren mit den Markern BASH
.
Die Art und Weise, wie dies funktioniert, besteht darin, den inneren Heredoc zwischen den BASH-Markern dem Bash-Standard zuzuführen. Beachten Sie, dass es im Kontext von ausgeführt wird/bin/sh
, es ist also ein Posix Heredoc, kein Ruby. Normalerweise muss sich die Endmarkierung in Spalte 1 befinden, was hier aufgrund des Einrückens nicht der Fall ist.
Da es jedoch in einen Rubin-Heredoc eingewickelt ist, wird es durch die dort strip_heredoc
angewandte Methode entfernt und die gesamte linke Seite des inneren Heredocs in Spalte 1 platziert, bevor es /bin/sh
angezeigt wird.
/bin/sh
würde normalerweise auch Variablen innerhalb des Heredocs erweitern, was das Skript stören könnte. Die einfachen Anführungszeichen um den Startmarker 'BASH' weisen darauf hin, dass /bin/sh
im Heredoc nichts erweitert werden soll, bevor es an bash übergeben wird.
Wendet /bin/sh
jedoch immer noch Escapezeichen auf die Zeichenfolge an, bevor sie an bash übergeben wird. Das bedeutet, dass Backslash-Fluchten verdoppelt werden müssen, um /bin/sh
zu Bash zu gelangen, dh \
zu werden\\
.
Die Bash-Optionen -xeu
sind optional.
Die -eu
Argumente weisen bash an, im strengen Modus ausgeführt zu werden, wodurch die Ausführung bei einem Fehler oder Verweis auf eine undefinierte Variable gestoppt wird. Dies gibt einen Fehler an Rake zurück, wodurch die Rake-Task gestoppt wird. Normalerweise ist dies das, was Sie wollen. Die Argumente können gelöscht werden, wenn Sie ein normales Bash-Verhalten wünschen.
Die -x
Option zum Bash und {verbose: false}
Argumentieren, um gemeinsam zu #sh
arbeiten, sodass Rake nur die Bash-Befehle druckt, die tatsächlich ausgeführt werden. Dies ist nützlich, wenn Ihr Bash-Skript nicht vollständig ausgeführt werden soll, z. B. wenn es einen Test enthält, mit dem es ordnungsgemäß im Skript beendet werden kann.
Achten Sie darauf, keinen anderen Exit-Code als 0 festzulegen, wenn die Rake-Task nicht fehlschlagen soll. Normalerweise bedeutet dies, dass Sie keine || exit
Konstrukte verwenden möchten, ohne den Exit-Code explizit festzulegen, d || exit 0
. H.
%{
so%x(
, und das gibt stdout als Zeichenfolge zurück, anstatt es zu drucken.