bash: echo: write error: Unterbrochener Systemaufruf

9

Ich möchte eine sortierte Liste mit allen 8-stelligen Zahlen erstellen - von 00000000 bis 99999999. Ich habe die Shell eingegeben:

f() {
 while IFS="" read -r line; do
   for i in {0..9}; do 
       echo "$line$i";
   done;
 done
}

echo | f | f | f | f | f | f | f | f | tee result.txt | wc -l

Antwort ist

bash: echo: write error: Interrupted system call
bash: echo: write error: Interrupted system call
bash: echo: write error: Interrupted system call
99998890

Warum habe ich diese drei Fehler und die fehlerhafte result.txt?

ich benutze

GNU Bash, Version 4.4.12 (1) -Veröffentlichung (x86_64-pc-linux-gnu)

Debian GNU / Linux 9.6 (Stretch)

Linux-Kernel: 4.19.0 # 2 SMP Do 1. November 15:31:34 EET 2018 x86_64 GNU / Linux

hon
quelle
2
Ich kann nicht anders, als das Gefühl zu haben, dass dies nicht effizienter ist als seq -w 0 99999999.
Kusalananda
1
Dann ist die Frage unvollständig / falsch / schlecht geschrieben oder etwas anderes. Weil das Skript (wenn es mit dem abgeschlossen ist }) korrekt funktioniert. @ GAD3R
Isaac
1
Hinweis: Ich kann diese Fehler fast bei Bedarf auslösen. Sie werden häufig angezeigt, wenn ich die Größe meines konsoleFensters verändere. Eine solche Größenänderung ist in meinem Fall fast ausreichend, aber nicht notwendig.
Kamil Maciorowski
Ich kann das entfernen | tee result.txtund bekomme trotzdem den Fehler.
Strg-Alt-Delor
Ein weiterer Hinweis: Externe ausführbare Dateien ( /bin/echoin meinem Fall) anstelle von echointegrierten Funktionen machen die Funktion immun (oder zumindest weniger anfällig) für dieses Problem.
Kamil Maciorowski

Antworten:

6

Der spezifische write error: Interrupted system callFehler wird generiert, wenn die Größe des Konsolenfensters geändert wird, während das Skript ausgeführt wird.

Ein:

 trap '' SIGWINCH

wird es vermeiden.

Beachten Sie, dass a

 seq 99999999 >result.txt; wc -l <result.txt

Wird sowohl schneller sein als auch das SIGWINCHProblem vermeiden .

Isaac
quelle
5
Also, was ist los? Warum habe ich das noch nie gesehen? Warum ist ein Schreibfehler das Richtige?
Strg-Alt-Delor
4

Dies ist eigentlich ein Fehler [a] in bash, und es geschieht nicht nur auf SIGWINCH, sondern auch auf jedem Signal , für das eine Falle gestellt wurde:

{ pid=$BASHPID; trap : USR1; (sleep 1; kill -USR1 $pid) &
         printf %0100000d 1; } | sleep 3600
bash: printf: write error: Interrupted system call

Dies liegt daran bash, dass entweder a) die Signalhandler nicht mit SA_RESTART(mit Ausnahme des SIGCHLDHandlers) gesetzt werden oder b) EINTRbeim Aufrufen von write () in den printfund echobuiltins behandelt wird.

EINTR("Unterbrochener Systemaufruf") ist keine Möglichkeit, einen Fehlerzustand anzuzeigen, sondern ein Hack, mit dem der Programmierer blockierende Lese- / Schreibvorgänge / usw. mit der Verarbeitung von Signalen in der Hauptschleife kombinieren kann. Es sollte niemals an den Benutzer weitergegeben werden.

Dieser Fehler tritt nicht allzu häufig auf, da es eine ziemliche Leistung ist, die richtigen Bedingungen zu schaffen: write () sollte von einem eingebauten (nicht von einem externen Befehl) ausgeführt werden, es sollte den Pipe-Puffer (den Reader) füllen am anderen Ende sollte es viel langsamer sein oder überhaupt nicht aus der Pipe lesen, aber noch am Leben sein ), und das Skript sollte Traps verwenden oder die Größe des Terminalfensters sollte geändert werden.

Und aufgrund verschiedener Implementierungsartefakte betrifft dies nur unterbrochene write () s, nicht read () s oder open () s (wie z. B. das Blocking open () einer Named Pipe / Fifo).

[a] Eine Form davon wurde bereits voreiniger Zeit gemeldet .

Mosvy
quelle