GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wie liest man das gesamte Shell-Skript, bevor man es ausführt?

Wenn Sie ein Skript bearbeiten, sind normalerweise alle laufenden Verwendungen des Skripts fehleranfällig.

Soweit ich es verstehe, liest Bash (auch andere Shells?) Das Skript inkrementell. Wenn Sie also die Skriptdatei extern ändern, beginnt es, die falschen Dinge zu lesen. Gibt es eine Möglichkeit, dies zu verhindern?

Beispiel:

sleep 20

echo test

Wenn Sie dieses Skript ausführen, liest bash die erste Zeile (z. B. 10 Bytes) und geht in den Ruhezustand. Wenn es fortgesetzt wird, kann es ab dem 10. Byte unterschiedliche Inhalte im Skript geben. Möglicherweise befinde ich mich mitten in einer Zeile im neuen Skript. Dadurch wird das laufende Skript beschädigt.

Akzeptierte Antwort:

Ja, Shells und bash Achten Sie insbesondere darauf, die Datei zeilenweise zu lesen, damit sie genauso funktioniert wie bei interaktiver Verwendung.

Sie werden feststellen, dass, wenn die Datei nicht durchsucht werden kann (wie eine Pipe), bash liest sogar jeweils ein Byte, um sicherzugehen, dass nicht über den \n hinaus gelesen wird Charakter. Wenn die Datei durchsuchbar ist, wird sie optimiert, indem ganze Blöcke auf einmal gelesen werden, aber nach dem \n zurückgesucht wird .

Das bedeutet, dass Sie Dinge tun können wie:

bash << \EOF
read var
var's content
echo "$var"
EOF

Oder schreiben Sie Skripte, die sich selbst aktualisieren. Was Sie nicht tun könnten, wenn es Ihnen diese Garantie nicht geben würde.

Nun, es ist selten, dass Sie so etwas tun möchten, und wie Sie herausgefunden haben, neigt diese Funktion dazu, öfter im Weg zu sein, als es nützlich ist.

Um dies zu vermeiden, könnten Sie versuchen, sicherzustellen, dass Sie die Datei nicht an Ort und Stelle ändern (z. B. eine Kopie ändern und die Kopie an Ort und Stelle verschieben (wie sed -i oder perl -pi und manche Redakteure zum Beispiel)).

Oder Sie könnten Ihr Skript wie folgt schreiben:

{
  sleep 20
  echo test
}; exit

(Beachten Sie, dass es wichtig ist, dass der exit in derselben Zeile sein wie }; obwohl Sie es auch in die geschweiften Klammern direkt vor die schließende einfügen könnten).

oder:

main() {
  sleep 20
  echo test
}
main "[email protected]"; exit

Die Shell muss das Skript bis zum exit lesen bevor Sie anfangen, etwas zu tun. Dadurch wird sichergestellt, dass die Shell nicht erneut aus dem Skript liest.

Das bedeutet jedoch, dass das gesamte Skript im Speicher gespeichert wird.

Das kann sich auch auf das Parsen des Skripts auswirken.

Zum Beispiel in bash :

export LC_ALL=fr_FR.UTF-8
echo $'St\ue9phane'

Würde das in UTF-8 kodierte U+00E9 ausgeben. Wenn Sie es jedoch ändern in:

{
  export LC_ALL=fr_FR.UTF-8
  echo $'St\ue9phane'
}

Der \ue9 wird in dem Zeichensatz expandiert, der zu dem Zeitpunkt gültig war, als dieser Befehl geparst wurde, was in diesem Fall vorher ist den export Befehl wird ausgeführt.

Verwandte:SSH – Skript zur Automatisierung von scp im Netzwerk?

Beachten Sie auch, dass wenn die source auch bekannt als . Befehl verwendet wird, haben Sie bei einigen Shells die gleiche Art von Problem für die Quelldateien.

Das ist bei bash nicht der Fall obwohl dessen source Der Befehl liest die Datei vollständig, bevor er sie interpretiert. Wenn für bash geschrieben wird Insbesondere könnten Sie dies tatsächlich nutzen, indem Sie am Anfang des Skripts hinzufügen:

if [[ ! $already_sourced ]]; then
  already_sourced=1
  source "$0"; exit
fi

(Ich würde mich jedoch nicht darauf verlassen, da Sie sich zukünftige Versionen von bash vorstellen könnten könnte dieses Verhalten ändern, was derzeit als Einschränkung angesehen werden kann (bash und AT&T ksh sind die einzigen POSIX-ähnlichen Shells, die sich so verhalten, soweit ich das beurteilen kann) und der already_sourced Trick ist ein bisschen spröde, da er davon ausgeht, dass die Variable nicht in der Umgebung ist, ganz zu schweigen davon, dass sie den Inhalt der BASH_SOURCE-Variablen beeinflusst)


Linux
  1. So verwenden Sie ein verschlüsseltes Passwort in einem Linux-Bash-Shell-Skript

  2. Anpassen der Bash-Shell

  3. Wie debuggt man ein Bash-Skript?

  4. Wie kann man das Shell-Skript entweder verschlüsseln oder unlesbar machen?

  5. Wie überprüfe ich die Teilzeichenfolge in Shell Script Bash?

So verwenden Sie den Bash-Lesebefehl

So führen Sie ein Bash-Skript aus

Wie stoppe ich das Loop Bash-Skript im Terminal?

Wie liest man die vorletzte Zeile in einer Datei mit Bash?

Shell-Skript, nach dem Echo einer Nachricht in derselben Zeile lesen

Was ist der Unterschied zwischen der Ausführung eines Bash-Skripts und dessen Beschaffung?