2015-10-08 7 views
5

Ich habe einen Befehl, den ich würde laufen zufällige Zeichenfolge zu generieren:Piping aus Python genannt Ergebnisse in Rohrbruch in Shell-Skript mit dem Hinterkopf

var=`< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c8` 

Wenn ich diesen Befehl in der interaktiven Bash-Sitzung ausführen bekomme ich absolut keine Fehler . Aber wenn ich diesen Befehl in ein Skript einfüge und es als Skript ausführe, erhalte ich den Fehler gebrochener Pipe, der durch tr angezeigt wird. Ich habe mehrere verwandte Themen gelesen, habe aber immer noch keine Antwort, warum Skript und interaktives Verhalten anders sind und gibt es eine Möglichkeit, es mit Shell-Optionen oder mit etwas anderem zu steuern?

Edit I:

In Bezug auf Kommentare gegeben Ich fand, dass Rohrbruch Fehler anzeigt, über gesteuert werden kann:

trap - SIGPIPE # to ignore errors 

und

trap "" SIGPIPE # to display errors 

bearbeiten II:

Nun, ich habe falsche Informationen über die Reproduktionsbedingungen angegeben. Schließlich scheint es, dass Problem mit dem Python-Wrapper verursacht, die das Skript mit dem os.system() aufgerufen:

python -c "import os; os.system('sh -c \"< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c8\"')" 

gegeben Linie Rohrbruch Fehler unabhängig von gebrauchten OS erzeugt.

bearbeiten III:

Dieses Thema hier diskutiert wurde: https://mail.python.org/pipermail/python-dev/2005-September/056341.html

+1

Klingt wie das Problem [hier] (https://github.com/koalaman/shellcheck/issues/494) und in der genannten Ausgabe diskutiert. (Shellcheck ist hier nicht beteiligt, es ist nur eine Diskussion über dieses genaue Problem und die Diskussion über Shellcheck, was ein großartiges Werkzeug ist, warnt genau über diese Art von Sache.) –

+0

Funktioniert perfekt unter Cygwin/bash-4.1.10 (4) ... (Richte deine Zeile und ein 'echo $ var' in einem Skript ein, nichts anderes außer '#!/Bin/sh'.) – Amessihel

+1

Fangen Sie SIGPIPE im Skript ab? – PSkocik

Antwort

3

Wenn einer der übergeordneten Prozesse sigpipe einfängt, dann wird die Pipeline die ignore Signal Disposition erben, die dieses Problem verursachen du erlebst.

Dies kann (sicher) wiedergegeben werden, mit:

(trap '' pipe; var=`< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c8) 

Normalerweise wird der head -c8 Befehl ziemlich bald, an dem stdin geschlossen ist darauf seine erfolgen. Da es stdin ist, ist eine Rohrleitung an die stdout von tr angeschlossen, es macht jetzt keinen Sinn mehr für tr zu schreiben stdout. Sobald es versucht wird, wird das System es mit SIGPIPE töten. Es sei denn tr ignoriert dieses Signal oder hat die ignore (SIG_IGN) Disposition für dieses Signal von seinem Elternteil geerbt. Dann ein write zu tr 's gebrochen stdout wird einfach einen regulären Fehler verursachen und errno auf EPIPE zu diesem Zeitpunkt tr wird höchstwahrscheinlich stringifizieren und gibt diesen Fehler auf seine stderr und beenden.