In Bash stelle ich fest, dass alle Programme, die zuvor ausgeführt wurden, nicht ausgeführt werden, wenn ein Befehl mit Umleitung fehlschlagen würde.
Beispielsweise öffnet dieses Programm die Datei "a" und schreibt 50 Bytes in die Datei "a". Wenn Sie diesen Befehl jedoch mit Umleitung zu einer Datei mit unzureichenden Berechtigungen (~ root / log) ausführen, ändert sich die Dateigröße von "a" nicht.
$ ./write_file.py >> ~root/log
-bash: /var/root/log: Permission denied
cdal at Mac in ~/experimental/unix_write
$ ls -lt
total 16
-rw-rw-r-- 1 cdal staff 0 Apr 27 08:54 a <-- SHOULD BE 50 BYTES
Man würde denken, das Programm würde laufen, jede Ausgabe erfassen (aber auch in die Datei "a" schreiben) und dann keine Ausgabe in ~ root / log schreiben. Stattdessen wird das Programm nie ausgeführt.
Warum ist das so und wie wählt bash die Reihenfolge der "Überprüfungen", die es vor der Ausführung eines Programms durchführt? Werden auch andere Prüfungen durchgeführt?
ps Ich versuche festzustellen, ob ein unter cron ausgeführtes Programm tatsächlich ausgeführt wurde, wenn es in eine Datei mit der Berechtigung "Berechtigung verweigert" umgeleitet wurde.
quelle
stdout
, um genau das zu tun. Sie sehen also keine Ausgabe, obwohl Ihr Programm ausgeführt wurde.write_file.py
Programm aus und senden Sie seine Ausgabe an~root/log
bash:" Entschuldigung, aber Sie dürfen nicht in diese Datei schreiben! "Die Shell tut genau das, was sie tun soll. Wenn sie nicht das tun kann, worum Sie es gebeten haben Wenn Sie dies tun, werden Sie sofort darüber informiert, warum ein Problem vorliegt, und Sie können entscheiden, wie Sie damit umgehen möchten. Nach Ansicht aller Bash-Betreuer können sehr schlimme Dinge passieren, wenn Sie diesen Befehl ausführen und die Ausgabe nicht speichern können. Wenn es wichtig genug wäre, dass Sie einen Ort zum Speichern festgelegt haben, wäre es falsch, ASS | U | ME zu verwenden. Es war in Ordnung, ohne Speichern von stdout zu laufen.Antworten:
Es geht nicht wirklich darum, Schecks zu bestellen, sondern nur um die Reihenfolge, in der die Shell die Dinge einrichtet. Umleitungen werden eingerichtet, bevor der Befehl ausgeführt wird. In Ihrem Beispiel versucht die Shell, sie
~root/log
zum Anhängen zu öffnen , bevor Sie versuchen, etwas zu tun, das sie betrifft./write_file.py
. Da die Protokolldatei nicht geöffnet werden kann, schlägt die Umleitung fehl und die Shell beendet die Verarbeitung der Befehlszeile an diesem Punkt.Eine Möglichkeit, dies zu demonstrieren, besteht darin, eine nicht ausführbare Datei zu verwenden und zu versuchen, sie auszuführen:
Dies zeigt, dass die Shell nicht einmal sieht,
./demo
wann die Umleitung nicht eingerichtet werden kann.quelle
Auf der Bash-Manpage, Abschnitt REDIRECTION (Hervorhebung von mir):
Die Shell versucht also, die Zieldatei für zu öffnen
stdout
, was fehlschlägt, und der Befehl wird überhaupt nicht ausgeführt.quelle
Es ist zu beachten, dass die Shell vor dem Starten des Programms Umleitungen einrichten muss .
Betrachten Sie Ihr Beispiel:
Was in der Shell passiert, ist:
fork()
; Der untergeordnete Prozess erbt die offenen Dateideskriptoren von seinem übergeordneten Prozess (der Shell).fopen()
(die Erweiterung von) "~ root / log" unddup2()
es zu fd 1 (undclose()
dem temporären fd). Wenn diesfopen()
fehlschlägt, rufen Sieexit()
an, um den Fehler dem übergeordneten Element zu melden.exec()
"./write_file.py". Dieser Prozess führt jetzt keinen unserer Codes mehr aus (es sei denn, wir haben ihn nicht ausgeführt. In diesem Fall müssen wirexit()
den Fehler dem übergeordneten Code melden).wait()
das Kind beenden und seinen Exit-Code verarbeiten ($?
zumindest durch Kopieren in ).Die Umleitung muss also im untergeordneten Element zwischen
fork()
und erfolgenexec()
: Sie kann nicht vorher erfolgen,fork()
da sie das Standardout der Shell nicht ändern darf, und sie kann nicht danach erfolgen,exec()
da der Dateiname und der ausführbare Code der Shell jetzt durch das Python-Programm ersetzt wurden . Das übergeordnete Element hat keinen Zugriff auf die Dateideskriptoren des untergeordneten Elements (und selbst wenn dies der Fall ist, kann nicht garantiert werden, dass zwischenexec()
und dem ersten Schreiben in stdout umgeleitet wird ).quelle
Es tut mir leid, Ihnen mitteilen zu müssen, dass das Gegenteil der Fall ist. Die Shell muss zuerst ihre E / A öffnen und dann die Steuerung an das Programm übergeben.
tee
könnte sich in diesem Fall als hilfreich erweisen:./write_file.py | tee -a ~root/log > /dev/null
quelle