¿Hay alguna manera de redirigir la salida a un archivo sin almacenar en búfer en unix / linux?

49

Tengo un proceso por lotes de larga ejecución que genera información de depuración y proceso en stdout. Si solo corro desde un terminal, puedo hacer un seguimiento de "dónde está", pero luego los datos son demasiado y se desplazan fuera de la pantalla.

Si redirijo a la salida a un archivo '> out.txt', eventualmente obtengo toda la salida, pero está almacenada en un búfer, por lo que ya no puedo ver lo que está haciendo en este momento.

¿Hay alguna manera de redirigir la salida pero hacer que no almacene sus escrituras?

James Dean
fuente
1
¿Podría echar un vistazo a mi (y @cnst 's) "debate" a continuación, supongo que lo único que desea es ver la salida al mismo tiempo que iniciar sesión en un archivo. Si ha encontrado una solución, háganos saber al respecto;)!
Benj
2
pregunta más votada unix.stackexchange.com/questions/25372
Trevor Boyd Smith

Respuestas:

52

Puede establecer explícitamente las opciones de almacenamiento en búfer de las transmisiones estándar utilizando una setvbufllamada en C (consulte este enlace ), pero si está intentando modificar el comportamiento de un programa existente, intente stdbuf(parte de coreutilscomenzar con la versión 7.5 aparentemente).

Esto amortigua stdouthasta una línea:

stdbuf -oL command > output

Esto desactiva el stdoutalmacenamiento en búfer por completo:

stdbuf -o0 command > output
Eduardo Ivanec
fuente
aaarghhh ... Mi Ubuntu solo tiene 7.4 coreutils ... :(
Calmarius
@ Calmarius: compilar coreutils debería ser bastante fácil. Simplemente tome una nueva versión de ftp.gnu.org/gnu/coreutils y pruébela . Es la ./configure && maketarifa estándar . Ni siquiera tiene que instalarlo después, solo puede usar el stdbufbinario desactivado src/.
Eduardo Ivanec
doble argh. Necesito esto en una antigua distribución de centos y OSX, así como Ubuntu.
edk750
respuesta más votada unix.stackexchange.com/a/25378/5510
Trevor Boyd Smith
¿Hay alguna manera de forzar los almacenamientos intermedios de tubería / printf externamente para el proceso en ejecución con PID conocido?
Mvorisek
9

Puede lograr una salida de línea almacenada en un archivo utilizando el scriptcomando de la siguiente manera:

stty -echo -onlcr   # avoid added \r in output
script -q /dev/null batch_process | tee output.log        # Mac OS X, FreeBSD
script -q -c "batch_process" /dev/null | tee output.log   # Linux
stty echo onlcr
fusor
fuente
-1 porque: a) a diferencia de la respuesta aceptada, esto no funciona si desea ejecutar el comando en segundo plano (el comando termina inmediatamente sin terminar batch_processsi agrega &el comando anterior, al menos en mi cuadro de Linux), lo que parece como un caso de uso extremadamente común, y b) aquí no hay explicación de cómo funciona este encantamiento.
Mark Amery
8

En Ubuntu, el paquete del unbufferprograma (del expect-dev) hizo el truco para mí. Solo corre:

unbuffer your_command

y no lo amortiguará.

Calmarius
fuente
6

La solución más fácil que encontré (no necesitaba instalar ningún paquete de terceros) se mencionó en un hilo similar en el sitio de Unix y Linux : use el scriptcomando. Es viejo y probablemente ya esté instalado.

$ script -q /dev/null long_running_command | print_progress       # FreeBSD, Mac OS X
$ script -q -c "long_running_command" /dev/null | print_progress  # Linux

Tenga en cuenta que el primer parámetro de nombre de archivo para el scriptcomando es el archivo de registro que se escribirá . Si simplemente ejecuta script -q your_command, sobrescribirá el comando que sangró para ejecutar con el archivo de registro. Verifique man script, para estar seguro, antes de intentarlo.

Steve HHH
fuente
4

prueba el scriptcomando; si su sistema lo tiene, toma un nombre de archivo como argumento, todo el texto volcado a stdout se copia en el archivo. Es muy útil cuando un programa de instalación requiere interacción.

Chris S
fuente
Sé del truco 'script -a out.txt'. Me preguntaba si hay alguna otra forma de hacer que el proceso de escritura no sea buffer.
James Dean
3

Personalmente, prefiero la salida de tubería de un comando que deseo examinar tee.

scriptregistra demasiada información, incluida la sincronización de las pulsaciones de teclas y muchos caracteres no imprimibles. Lo que teeahorra es mucho más legible para mí.

Paweł Brodacki
fuente
También agregaría "| less" a la línea de comando.
HUB
44
Estoy bastante seguro de que eso también teese ve afectado por el almacenamiento en búfer. Frecuentemente sigo mostrando líneas parciales por tee al dividir la salida de los findcomandos.
Magellan
2

Redirija la salida a un archivo y siga el archivo con el tail -fcomando.

Editar

Si esto todavía sufre de almacenamiento en búfer, utilice la función syslog (que generalmente no tiene búfer). Si el proceso por lotes se ejecuta como un script de shell, puede usar el comando logger para hacer esto. Si el trabajo por lotes se ejecuta en un lenguaje de secuencias de comandos, de todos modos debería haber una instalación de registro.

wolfgangsz
fuente
3
Esto es lo que hago ahora, pero el proceso amortigua la escritura en el archivo y eso es justo lo que quiero evitar.
James Dean
Vea mi edición para una propuesta actualizada.
wolfgangsz
1
Esto no funciona por razones obvias. ¿Quién demonios da This answer is usefulrespuestas que no funcionan y que posiblemente no pueden funcionar?
Cnst
1

Puedes usar el teecomando, ¡solo magia!

someCommand | tee logFile.logserá tanto la pantalla en la consola y escribir en el archivo de registro.

Benj
fuente
No funciona teeno detendrá el almacenamiento en búfer.
Cnst
1
@cnst Efectivamente, teeno evitará un poco de almacenamiento en búfer, pero solo le permitirá ver cuál es el resultado. Esto es lo que @JamesDean quería (ya que no entendí su pregunta), pero creo que el buffering no es realmente el problema aquí. Si tiene más detalles, hágamelo saber.
Benj
Quería ver la salida, y no está obteniendo ninguna salida (de una manera no amortiguada), y sin embargo, ¿sugiere utilizar teepara obtener una mejor vista de la salida que no se obtiene?
Cnst
1
Cómo respondí a la pregunta de @JamesDean: "Redirijo a la salida a un archivo '> out.txt'" significa que no hay salida de consola, espere a que se complete el proceso mientras se redirige toda la salida. Cuando estás usando >no ves nada en la consola. Supongo que @JamesDean está usando la palabra "almacenamiento en búfer" para describir eso. Publicaré un comentario sobre su pregunta para que diga más sobre lo que quiere.
Benj