In einem Verzeichnis befinden sich viele TXT-Dateien.
Wenn ich time wc -l *.txt | head
das tue, dauert es
real 0m0.032s
user 0m0.020s
sys 0m0.008s
Wenn ich time wc -l *.txt | tail
das tue, dauert es
real 0m0.156s
user 0m0.076s
sys 0m0.088s
Bedeutet dies, dass es wc
im Voraus weiß, dass es eine Weiterleitung an head durchführt, und nur die ersten 10 Dateien zählt und Zeit spart? Mit anderen Worten, ist es sich der Weiterleitung bewusst? Und ist das etwas Besonderes wc
oder gilt es für alle Standard-/integrierten Befehle?
Antwort1
Ich habe strace
beide Befehle ausgeführt. Interessant ist, dass beim Weiterleiten der Ausgabe an head
nur 123 Systemaufrufe erfolgen. Beim Weiterleiten an tail hingegen erfolgen 245 Systemaufrufe (oder mehr, wenn mehrere *.txt-Dateien vorhanden sind).
Fall: Kopf
Hier sind die letzten Zeilen beim Weiterleiten an head
:
open("file12.txt", O_RDONLY) = 3
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
read(3, "", 16384) = 0
write(1, "0 file12.txt\n", 13) = -1 EPIPE (Broken pipe)
--- SIGPIPE (Broken pipe) @ 0 (0) ---
+++ killed by SIGPIPE +++
Beim wc
Versuch, die Ausgabe der 12. Datei zu schreiben, tritt ein Fehler auf EPIPE
. Deshalb head
wird nach dem Abrufen der 11. Zeile beendet. Beim head
Beenden wc
wird angezeigt SIGPIPE
. Wie in der Strace-Ausgabe oben zu sehen, wc
wird zuerst versucht, in diese Pipe zu schreiben ( head
von der nicht mehr gelesen wird) und es wird ein Fehler angezeigt, dass die Pipe defekt ist.
Das Signal SIGPIPE wird an einen Prozess gesendet, wenn dieser versucht, in eine Pipe zu schreiben, ohne dass am anderen Ende ein Prozess angeschlossen ist. – vonWikipedia
Fall: Schwanz
Beim Pipen an tail
gibt es nichts Vergleichbares wie oben. wc wird ordnungsgemäß beendet, nachdem die gesamte Ausgabe an die Pipe geschrieben wurde, tail
mit der die ganze Zeit verbunden sein muss. tail
benötigt alle Zeilen, bevor es die letzten 10 davon drucken kann. Wenn keine weitere Ausgabe zum Lesen vorhanden ist, tail
druckt es die Zeilen und beendet ebenfalls ordnungsgemäß.
Antwort2
Jeder Prozess, der nicht blockiert, SIGPIPE
wird beendet, wenn seine Ausgabe an das Schreibende einer Pipe geht, aus der niemand liest.
Sobald also head
seine Eingabe geschlossen wird (d. h. beendet wird), wc
stirbt es, was weniger Zeit in Anspruch nimmt, als die gesamte Arbeit zu beenden.
Antwort3
So können Sie Ihre Dateien verschwinden lassen:
time wc -l *.txt > tee | tail
Aber Sie fügen ein bisschen Zeit für den Tee-Befehl hinzu time
.
Mit tee command
:
root@debian:/home/mohsen/test# time wc -l *.txt > tee | tail
real 0m0.005s
user 0m0.000s
sys 0m0.000s
Ohne tee command
:
root@debian:/home/mohsen/test# time wc -l *.txt | tail
8 f3.txt
7 fi.txt
5 mydata.txt
4 newfile.txt
4 t1.txt
4 t2.txt
5 test.txt
4 text.txt
0 t.txt
49 total
real 0m0.004s
user 0m0.000s
sys 0m0.000s