2013-12-21 11 views
7
#beginning of bashscript1.sh 
source bashscript2.sh 
echo $variable 

und hier ist die Quelldatei:Kann ein Shell-Skript sich selbst löschen oder überschreiben?

#beginning of bashscript2.sh 
rm -f bashscript2.sh 
variable = "integer of some kind" 

Wie der Bash-Skript behandelt werden? Lädt es zuerst die Quelldatei und löscht sie dann, oder wird die Variable einen Wert in bash script 1 haben?

+1

Haben Sie es versucht? Was geschieht? – elnigno

+2

Haben Sie es versucht? – bnjmn

+0

Ich wette: Die Datei wird ausgeführt, auch wenn sie gelöscht wurde. –

Antwort

16

Auf Unix-ähnlichen Betriebssystemen ist das Entfernen einer Datei möglich, wenn sie noch geöffnet ist. Der Dateiname wird nicht mehr existieren, aber die Daten selbst bleiben bestehen, und alle Programme, die ein offenes Handle haben, einschließlich bash, können weiterhin mit diesem Handle lesen (und sogar schreiben). Nur wenn das letzte Programm seinen Handle schließt, wird die Datei wirklich gelöscht.

Also, in gewissem Sinne, ja, kann ein Shell-Skript selbst löschen, aber es wird nicht wirklich gelöscht werden, bis nach der Ausführung des Skripts beendet.

Beachten Sie, dass Sie andere Ergebnisse erhalten, wenn Sie die Datei überschreiben, anstatt sie zu löschen. Shells können (und tun) Pufferung verwenden, um das Lesen von jeweils einem Byte zu vermeiden, aber der Puffer hat eine endliche Größe. Wenn sich der Dateiinhalt über das hinaus ändert, was die Shell bereits in den Speicher gelesen hat, wird der neue Inhalt angezeigt. Sie können ein einfaches Beispiel dafür erstellen, wenn Sie untersuchen, wie groß die Puffergröße für Ihr System ist. Auf meinem System sind es 8 KiB. So ein Shell-Skript, das

echo line 1 
>test.sh 
# (8167 random characters) 
echo line 4 

so der zweite Block von Daten enthält, ist "cho line 4", auf meinem System, Ausgänge

 
$ bash test.sh 
line 1 
test.sh: line 4: e: command not found 

weil die e bereits gelesen wurde, und die Schale gestoßen EOF, wenn versuche den Rest der Zeile zu lesen.

Update: Rici zeigt, dass mit einem anderen Beispiel des Überschreibens der Datei die neu geschriebenen Inhalte verwendet werden. Nacharbeiten, dass:

script="`tr 12 21 <test.sh`" 
env echo "$script" >test.sh 
echo toggle: 1 

Die zweite Zeile absichtlich nicht bash-interne nicht verwendet echo Befehl, weil das manchmal nicht bash nicht dazu führen, dass das Skript erneut zu lesen, nach den Kommentaren, aber gerade wenn es funktioniert und ist mir nicht unklar. bash gibt den neu geschriebenen Toggle-Wert aus, wenn die dritte Zeile erreicht wird. Der relevante Unterschied zwischen diesem und meinem früheren Beispiel scheint zu sein, dass bash hier die aktuelle Position suchen kann, wenn es zu Zeile 3 kommt, während dies in meinem früheren Beispiel unmöglich ist, weil diese Position nicht mehr existiert, wie die Datei ist leer.

+1

Sind Sie sicher? :) Versuchen Sie, diese zwei Zeilen in 'echo.sh' zu setzen, und fügen Sie die dritte Zeile hinzu:' echo line 1' 'echo echo overwrite | dd = echo.sh obs = 1 suchen = $ (head -n2 echo.sh | wc -c) ' – rici

+0

@rici Huh, interessant. Es scheint ein bisschen von beidem zu sein: Bash puffert wie ich beschrieben habe, aber * versucht * die Datei erneut zu lesen (vermutlich genau um dies zu unterstützen), wenn es zur nächsten Zeile kommt. In Ihrem Beispiel funktioniert das. Bei mir ist das nicht der Fall (weil die angestrebte Position nicht mehr gültig ist). Wird bearbeiten. Vielleicht beachtenswert: Der Bindestrich druckt nicht "überschreiben" mit Ihrem Beispiel. – hvd

+0

hvd: Auf meinem System (Bash 4.2.25 auf Ubuntu 12.04) funktioniert @ Ricis Beispiel, aber das Beispiel aus deinem Update funktioniert nicht - der neue Wert des Toggle wird NICHT gemeldet. Wo siehst du dein Beispiel? – mklement0

2

Ist das eine Neugier, die Sie haben oder was Sie eigentlich wollen?

Wie auch immer, ich habe versucht, mich dieses einfache Skript (test_script.sh):

rm -f test_script.sh 
echo "Still here!" 

und er druckt Still here!, so dass die Datei vor der Ausführung geladen wurde. Die Ausführung ist beim zweiten Mal nicht möglich.

Um Ihre Frage zu beantworten, ja und nein. Die Befehle im Skript werden geladen und ausgeführt und können die Quelldatei des Skripts löschen. Dies macht es natürlich unmöglich, die gleiche Datei erneut auszuführen, beeinflusst jedoch nicht die erste Ausführung.

+0

Es ist beides. Ich bin gespannt wie es sich verhält und warum. Außerdem denke ich daran, einen hässlichen Hack zu machen, für den ich eine Quelldatei zum Verschwinden brauche, während mein erstes Skript immer noch alle Variablen enthält, während es noch läuft. – Paolo

+0

Es scheint mir, dass der Code, den Sie gepostet haben, ziemlich genau das ist, liege ich falsch? – elnigno

Verwandte Themen