echo
nur ein einfacher Wrapper um write
(dies ist eine Vereinfachung; siehe unten für die blutigen Details), um festzustellen, ob Echo atomar ist, ist es sinnvoll, nachschlagen zu schreiben. Vom single UNIX specification:
Atomic/Nicht-Atom: Ein Schreib ist atomar, wenn die ganze Menge in einem Vorgang geschrieben wird nicht mit Daten aus anderen Prozessen verschachtelt. Dies ist nützlich, wenn mehrere Writer Daten an einen einzelnen Reader senden. Anwendungen müssen wissen, wie groß eine Schreibanforderung voraussichtlich atomar ausgeführt werden kann. Dieses Maximum wird {PIPE_BUF} genannt. Dieses Volumen von IEEE Std 1003.1-2001 sagt nicht, ob Schreibanforderungen für mehr als {PIPE_BUF} Bytes atomar sind, erfordert jedoch, dass Schreibvorgänge von {PIPE_BUF} oder weniger Bytes atomar sein müssen.
Sie können PIPE_BUF
auf Ihrem System mit einem einfachen C-Programm überprüfen. Wenn Sie nur eine einzige Ausgabezeile drucken, die nicht lächerlich lang ist, sollte sie atomar sein.
Hier ist ein einfaches Programm, um den Wert von PIPE_BUF
zu überprüfen:
#include <limits.h>
#include <stdio.h>
int main(void) {
printf("%d\n", PIPE_BUF);
return 0;
}
Unter Mac OS X, das mir 512 (die minimum allowed value für PIPE_BUF
) gibt. Unter Linux bekomme ich 4096. Wenn Ihre Zeilen also ziemlich lang sind, überprüfen Sie es auf dem betreffenden System.
bearbeiten hinzufügen: Ich entschied mich zu überprüfen the implementation of echo
in Bash, um zu bestätigen, dass es atomar gedruckt wird. Es stellt sich heraus, echo
verwendet putchar
oder printf
je nachdem, ob Sie die Option -e
verwenden. Dies sind gepufferte stdio-Operationen, was bedeutet, dass sie einen Puffer füllen und ihn nur dann schreiben, wenn ein Zeilenumbruch erreicht ist (im liniengepufferten Modus), der Puffer gefüllt ist (im blockgepufferten Modus) oder Sie explizit spülen der Ausgang mit fflush
. Standardmäßig befindet sich ein Stream im Zeilenpuffermodus, wenn es sich um ein interaktives Terminal handelt, und im Blockpuffermodus, wenn es sich um eine andere Datei handelt. Bash legt niemals den Pufferungstyp fest, daher sollte er für die Protokolldatei standardmäßig den Puffermodus blockieren. Um dann end of the echo
builtin Bash calls fflush
den Ausgangsstrom zu spülen. Daher wird die Ausgabe immer am Ende von echo
geleert, kann aber früher gelöscht werden, wenn sie nicht in den Puffer passt.
Die Größe des verwendeten Puffers kann BUFSIZ
sein, obwohl es anders sein kann; BUFSIZ
ist die Standardgröße, wenn Sie den Puffer explizit mit setbuf
festlegen, aber es gibt keinen portablen Weg, um die tatsächliche Größe Ihres Puffers zu bestimmen. Es gibt auch keine tragbaren Richtlinien für das, was BUFSIZ
ist, aber wenn ich es unter Mac OS X und Linux getestet habe, war es doppelt so groß wie PIPE_BUF
.
Was bedeutet das alles? Da die Ausgabe von echo
vollständig gepuffert ist, ruft sie die write
nicht wirklich auf, bis der Puffer voll ist oder fflush
aufgerufen wird. An diesem Punkt sollte die Ausgabe geschrieben werden, und die oben erwähnte Atomaritätsgarantie sollte gelten. Wenn die Stdout-Puffergröße größer als PIPE_BUF
ist, dann ist PIPE_BUF
die kleinste atomare Einheit, die ausgeschrieben werden kann. Wenn PIPE_BUF
größer ist als die Puffergröße von stdout, schreibt der Stream den Puffer, wenn der Puffer voll ist.
So, echo
ist nur garantiert, um Sequenzen kürzer als die kleinere von PIPE_BUF
und die Größe des Stdout-Puffer, die am wahrscheinlichsten ist BUFSIZ
atomar schreiben. Bei den meisten Systemen ist BUFSIZ
größer als PIPE_BUF
.
tl; dr: echo
werden Zeilen atomar ausgeben, solange diese Zeilen kurz genug sind. Auf modernen Systemen sind Sie wahrscheinlich bis zu 512 Byte sicher, aber es ist nicht möglich, das Limit portabel zu bestimmen.
Ich denke nicht, Bash ist das richtige Werkzeug für diesen Job. Ich würde etwas mächtigeres empfehlen (Perl, Python, Ruby ..) – Daenyth
Übrigens, wenn Sie eine * Menge * von Daten in dieses Protokoll gehen dann können Sie feststellen, dass das ständige Öffnen und Schließen der Protokolldatei eine schlechte Idee ist. Sie können eine Datei dauerhaft mit 'exec 3 >> $ {LOG_FILE}' öffnen und dann jederzeit mit 'echo whatever> & 3' dorthin schreiben. Sie können die Datei mit 'exec 3> & -' schließen, aber das passiert, wenn das Skript trotzdem beendet wird. Das einzige Problem ist, dass Sie für jede geöffnete Datei manuell eine Nummer auswählen müssen und 0, 1 und 2 bereits vergeben sind. – ams