18 Stimmen

Kann ein Shell-Skript angeben, dass seine Zeilen zunächst in den Speicher geladen werden sollen?

UPDATE: dies ist eine Neuveröffentlichung von Wie man Shell-Skripte so gestaltet, dass sie während ihrer Ausführung keine Änderungen am Quelltext erfahren

Das ist eine Kleinigkeit, die mich hin und wieder stört:

  1. Ich schreibe ein Shell-Skript (bash) für eine schnelle und schmutzige Arbeit
  2. Ich führe das Skript aus, und es läuft eine ganze Weile lang
  3. Während es läuft, bearbeite ich ein paar Zeilen im Skript und konfiguriere es für einen anderen Auftrag
  4. Aber der erste Prozess liest immer noch dieselbe Skriptdatei und gerät völlig durcheinander.

Offenbar wird das Skript interpretiert, indem jede Zeile aus der Datei wie es erforderlich ist . Gibt es eine Möglichkeit, der Shell mitzuteilen, dass die gesamte Skriptdatei auf einmal in den Speicher eingelesen werden soll? Perl-Skripte scheinen dies zum Beispiel zu tun: Die Bearbeitung der Codedatei wirkt sich nicht auf einen Prozess aus, der sie gerade interpretiert (weil sie zunächst geparst/kompiliert wird?).

Mir ist klar, dass es viele Möglichkeiten gibt, dieses Problem zu umgehen. Ich könnte zum Beispiel etwas wie folgt versuchen:

cat script.sh | sh

o

sh -c "`cat script.sh`"

... obwohl diese möglicherweise nicht korrekt funktionieren, wenn die Skriptdatei groß ist und es Grenzen für die Größe von Stream-Puffern und Befehlszeilenargumenten gibt. Ich könnte auch einen Hilfs-Wrapper schreiben, der eine Skriptdatei in eine gesperrte temporäre Datei kopiert und sie dann ausführt, aber das scheint nicht sehr portabel zu sein.

Ich hoffte also auf die einfachste Lösung, bei der nur das Skript geändert wird, nicht aber die Art und Weise, in der es aufgerufen wird. Kann ich einfach eine oder zwei Zeilen am Anfang des Skripts hinzufügen? Ich weiß nicht, ob eine solche Lösung existiert, aber ich vermute, sie könnte die Variable $0 verwenden...

20voto

Anonymous Punkte 888

Die beste Antwort, die ich gefunden habe, ist eine sehr leichte Abwandlung der Lösungen, die für Wie man Shell-Skripte so gestaltet, dass sie während ihrer Ausführung keine Änderungen am Quelltext erfahren . Danke an camh für den Hinweis auf die Wiederveröffentlichung!

#!/bin/sh
{
    # Your stuff goes here
    exit
}

Dies stellt sicher, dass Ihr gesamter Code zunächst geparst wird; beachten Sie, dass das "exit" entscheidend dafür ist, dass die Datei später nicht aufgerufen wird, um zu sehen, ob es noch weitere Zeilen zu interpretieren gibt. Wie im vorherigen Beitrag erwähnt, ist dies auch keine Garantie dafür, dass andere Skripte, die von Ihrem Skript aufgerufen werden, sicher sind.

Vielen Dank an alle für die Hilfe!

5voto

ephemient Punkte 189038

Verwenden Sie einen Editor, der die bestehende Datei nicht verändert, sondern eine neue Datei erstellt und die alte Datei ersetzt. Zum Beispiel mit :set writebackup backupcopy=no in Vim.

2voto

R Samuel Klatchko Punkte 72641

Wie wäre es mit einer Lösung, wie Sie es bearbeiten.

Wenn das Skript läuft, gehen Sie wie folgt vor, bevor Sie es bearbeiten:

mv script script-old
cp script-old script
rm script-old

Da die Shell die Datei offen hält, solange Sie den Inhalt des offenen Inodes nicht ändern, wird alles gut funktionieren.

Dies funktioniert, weil mv den alten Inode beibehält, während cp einen neuen erstellt. Da der Inhalt einer Datei nicht wirklich entfernt wird, wenn sie geöffnet wird, können Sie sie sofort entfernen und sie wird aufgeräumt, sobald die Shell die Datei schließt.

1voto

Norman Ramsey Punkte 193087

Laut der Bash-Dokumentation wird anstelle von

#!/bin/bash
body of script

Sie versuchen

#!/bin/bash
script=$(cat <<'SETVAR'
body of script
SETVAR)
eval "$script"

dann denke ich, dass Sie im Geschäft sind.

1voto

Acorn Punkte 718

Ein eigenständiger Weg, ein Skript resistent gegen dieses Problem zu machen, besteht darin, dass das Skript sich selbst kopiert und erneut ausführt, etwa so:

#!/bin/bash

if [[ $0 != /tmp/copy-* ]] ; then
    rm -f /tmp/copy-$$
    cp $0 /tmp/copy-$$
    exec /tmp/copy-$$ "$@"
    echo "error copying and execing script"
    exit 1
fi

rm $0

# rest of script...

(Dies funktioniert nicht, wenn das Originalskript mit den Zeichen /tmp/copy- )

(Dies ist inspiriert von R Samuel Klatchkos Antwort )

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X