echo
simplemente una envoltura simple alrededor de write
(esto es una simplificación, ver la edición más abajo para los detalles sangrientos), por lo que para determinar si el eco es atómico, es útil buscar escribir. Desde el single UNIX specification:
Atómica/no atómica: Una escritura es atómica si toda la cantidad escrita en una sola operación no está intercalada con los datos de cualquier otro proceso. Esto es útil cuando hay escritores múltiples que envían datos a un solo lector. Las aplicaciones necesitan saber qué tan grande se puede esperar que se realice una solicitud de escritura atómicamente. Este máximo se llama {PIPE_BUF}. Este volumen de IEEE Std 1003.1-2001 no dice si las solicitudes de escritura para más de {PIPE_BUF} bytes son atómicas, sino que requiere que las escrituras de {PIPE_BUF} o menos bytes sean atómicas.
Puede verificar PIPE_BUF
en su sistema con un simple programa en C. Si solo imprime una sola línea de salida, que no es ridículamente larga, debería ser atómica.
Aquí es un programa sencillo para comprobar el valor de PIPE_BUF
:
#include <limits.h>
#include <stdio.h>
int main(void) {
printf("%d\n", PIPE_BUF);
return 0;
}
En Mac OS X, que me da 512 (el minimum allowed value para PIPE_BUF
). En Linux, obtengo 4096. Por lo tanto, si sus líneas son bastante largas, asegúrese de verificarlas en el sistema en cuestión.
edit para agregar: Decidí consultar the implementation of echo
en Bash, para confirmar que se imprimirá atómicamente. Resulta que echo
usa putchar
o printf
dependiendo de si usa la opción -e
. Estas son operaciones stdio almacenadas en búfer, lo que significa que llenan un búfer, y realmente lo escriben solo cuando se llega a una nueva línea (en modo buffer de línea), el búfer se llena (en modo búfer de bloque), o se vacía explícitamente la salida con fflush
. Por defecto, una secuencia estará en modo de línea protegida si es una terminal interactiva, y bloqueará el modo almacenado si es cualquier otro archivo. Bash nunca establece el tipo de almacenamiento en búfer, por lo que para su archivo de registro, debe establecerse de forma predeterminada para bloquear el modo de almacenamiento en búfer. En ese momento end of the echo
builtin, Bash calls fflush
para enjuagar el flujo de salida. Por lo tanto, la salida siempre se purgará al final de echo
, pero puede enjuagarse antes si no cabe en el búfer.
El tamaño del búfer utilizado puede ser BUFSIZ
, aunque puede ser diferente; BUFSIZ
es el tamaño predeterminado si configura el búfer de forma explícita utilizando setbuf
, pero no hay forma portátil de determinar el tamaño real de su búfer. Tampoco hay pautas portátiles para lo que es BUFSIZ
, pero cuando lo probé en Mac OS X y Linux, era dos veces el tamaño de PIPE_BUF
.
¿Qué significa todo esto? Como la salida de echo
está almacenada en el búfer, no llamará realmente al write
hasta que se llene el búfer o se llame al fflush
. En ese punto, la salida debe escribirse, y debe aplicarse la garantía de atomicidad que mencioné anteriormente. Si el tamaño del búfer estándar es mayor que PIPE_BUF
, entonces PIPE_BUF
será la unidad atómica más pequeña que se pueda escribir. Si PIPE_BUF
es más grande que el tamaño del búfer estándar, el flujo escribirá el búfer cuando el búfer se llene.
Así, echo
sólo se garantiza para escribir atómicamente secuencias más cortas que el más pequeño de PIPE_BUF
y el tamaño del búfer de salida estándar, que es más probable BUFSIZ
. En la mayoría de los sistemas, BUFSIZ
es más grande que PIPE_BUF
.
tl; dr: echo
saldrán líneas atómicamente, siempre que esas líneas sean lo suficientemente cortas. En los sistemas modernos, probablemente tenga una seguridad de hasta 512 bytes, pero no es posible determinar el límite de forma portátil.
No creo que bash sea la herramienta adecuada para este trabajo. Recomendaría algo más poderoso (perl, python, ruby ...) – Daenyth
Por cierto, si tiene un * lote * de datos en este registro, entonces puede encontrar que abrir y cerrar continuamente el archivo de registro es una mala idea. Puede abrir permanentemente un archivo con 'exec 3 >> $ {LOG_FILE}' y luego escribir en él cuando lo desee con 'echo whatever> & 3'. Puede cerrar el archivo con 'exec 3> & -', pero eso ocurrirá cuando el script salga de todos modos. El único problema es que debe elegir manualmente un número para cada archivo que abre, y 0, 1 y 2 ya están ocupados. – ams