Bash: Warum wird der Alias ​​nach einer neuen Zeile bei der Remote-Ausführung ignoriert?

Bash: Warum wird der Alias ​​nach einer neuen Zeile bei der Remote-Ausführung ignoriert?

In Bash führe ich aus:

alias myalias='echo foo
echo bar
echo baz'
myalias

was zurückgibt:

foo
bar
baz

Aber:

ssh localhost "shopt -s expand_aliases &>/dev/null;
alias myalias='echo foo
echo bar
echo baz'
myalias"

Kehrt zurück:

foo

Warum?

Antwort1

Ich glaube, Sie haben einen Fehler in Bash gefunden. Dieser Fehler betrifft nur die Option -c.

Die Remote-Ausführung hat nichts mit Ihrem Problem mit dem mehrzeiligen Alias ​​zu tun. Sie können es in Ihrer lokalen Bash versuchen. Aber nicht in einem Bash-Skript oder einer interaktiven Bash. Versuchen Sie es mit einer -cOption wie dieser

bash -c "shopt -s expand_aliases &>/dev/null;
alias myalias='echo foo
echo bar
echo baz'
myalias"

Dieselbe Ausgabe wie bei Ihrem Problem. Es foowird nur gedruckt.

Um die richtige (erwartete) Ausgabe zu erhalten, müssen Sie, myaliaswie @cuonglm vorgeschlagen hat, mindestens eine weitere Zeile nach hinzufügen.

bash -c "shopt -s expand_aliases &>/dev/null;
alias myalias='echo foo
echo bar
echo baz'
myalias
:"

Warum sollte das so passieren? Warum myaliashilft eine weitere Zeile danach?

Ich möchte nur sagen, dass das keinen Sinn ergibt. Kein Dokument in Bash erklärt oder erwähnt diesen Fall, nicht im Geringsten. Es sollte nicht so laufen. Das ist ein Fehler. Nachdem Sie den Code gelesen haben, werden Sie sich dessen sicher sein.

Gehen Sie zurück zum ersten problematischen Befehl. Ändern Sie diesmal nichts, sondern kompilieren Sie Bash einfach neumit "ONESHOT" undefined, dann erhalten Sie die richtige (erwartete) Ausgabe. Ja, Sie haben richtig gehört, der Befehl hat zwei verschiedene Verhaltensweisen, nur aufgrund unterschiedlicher Konfigurationen zur Kompilierungszeit.

Ob definiert ONESHOToder nicht, führt zu zwei völlig unterschiedlichen Routen im Bash-Code -c "command". Wenn ONESHOT nicht definiert wird, -c "command"wird die normale Coderoute ausgeführt, die die Coderoute für fast alle Bash-Ausführungen ist, wie z. B. interaktive Befehle und Bash-Skripte. Wenn ONESHOT jedoch definiert wird, -c "command"wird eine andere spezielle Route ausgeführt, die speziell nur dafür entwickelt wurde, um die Leistung durch Vermeidung von Forks zu verbessern.

In diesem Fall kann die normale und meistverwendete Methode die richtige Ausgabe liefern, während die spezielle Methode dies nicht kann. Ich denke, das inkonsistente Verhalten ist nicht das, was die Bash-Autoren wollen. Was das richtige Verhalten angeht, neige ich dazu, zu glauben, dass die normale Methode richtig ist.

Einige Details zu diesem Fehler

Der folgende Codeabschnitt ist mit dem Fehler verbunden. Er stammt aus der Funktion parse_and_execute() in der Datei builtins/evalstring.c

while (*(bash_input.location.string))
  {
    ...
  }

Diese whileSchleife wird zeilenweise ausgeführt, wobei in einer Schleife jeweils eine Zeile verarbeitet wird. Nach dem Lesen myaliasder letzten Zeile im Befehl (siehe oben) whilewird die Bedingung falsch. myaliaswird auf drei Echozeilen erweitert, aber in dieser Schleife wird nur ein Echo verarbeitet; die beiden anderen Echos werden in der nächsten Schleife verarbeitet, aber... es gibt keine weitere Schleife.

Wenn Sie myaliasnach read eine weitere Zeile hinzufügen, bleibt myaliasdie Bedingung in erfüllt, sodass die beiden anderen Echos die Chance erhalten, in der nächsten Schleife ausgeführt zu werden. Die letzte Zeile danach wird verarbeitet, nachdem alle durch erweiterten Echos verarbeitet wurden.whilemyaliasmyalias

AKTUALISIEREN

Ich habe vergessen, die Version von Bash anzugeben, die von diesem Problem betroffen ist.

GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)

Antwort2

Problemumgehung (inspiriert von @cuonglm):

ssh localhost "shopt -s expand_aliases &>/dev/null;
alias myalias='ls
echo foo
echo bar
echo baz'
myalias &&
true"

Dadurch bleibt der Exit-Code erhalten. Das true, jedochmussin einer neuen Zeile stehen.

Es ist immer noch nicht erklärt, warum. Aber es sieht immer mehr nach einem Fehler aus.

verwandte Informationen