Tengo un pequeño script, que crontab llama a diario usando el siguiente comando:
/homedir/MyScript &> some_log.log
El problema con este método es que some_log.log solo se crea después de que MyScript finaliza. Me gustaría vaciar la salida del programa en el archivo mientras se está ejecutando para poder hacer cosas como
tail -f some_log.log
y realizar un seguimiento del progreso, etc.
sys.stdout.flush()
.Respuestas:
bash en sí mismo nunca escribirá ninguna salida en su archivo de registro. En cambio, los comandos que invoca como parte de la secuencia de comandos escribirán individualmente la salida y se eliminarán cuando lo deseen. Entonces, su pregunta es realmente cómo forzar que los comandos dentro del script bash se descarguen, y eso depende de lo que sean.
fuente
Encontré una solución a esto aquí . Usando el ejemplo de OP, básicamente ejecutas
y luego el búfer se vacía después de cada línea de salida. A menudo combino esto con
nohup
para ejecutar trabajos largos en una máquina remota.De esta manera, su proceso no se cancelará cuando cierre la sesión.
fuente
stdbuf
? Según este comentario , parece que no está disponible en algunas distribuciones. ¿Podrías aclarar?stdbuf
es parte de GNU coreutils, la documentación se puede encontrar en gnu.orgexport -f my_function
y luego,stdbuf -oL bash -c "my_function -args"
si necesita ejecutar una función en lugar de un scriptLa clave es -f. Cita del guión del hombre:
-f, --flush Flush output after each write. This is nice for telecooperation: one person does 'mkfifo foo; script -f foo', and another can supervise real-time what is being done using 'cat foo'.
Ejecutar en segundo plano:
fuente
busybox
! (mi caparazón se congela después, pero lo que sea)Puede utilizar
tee
para escribir en el archivo sin necesidad de vaciarlo.fuente
Esto no es una función de
bash
, ya que todo lo que hace el shell es abrir el archivo en cuestión y luego pasar el descriptor del archivo como salida estándar del script. Lo que debe hacer es asegurarse de que la salida se elimine de su secuencia de comandos con más frecuencia de la que tiene actualmente.En Perl, por ejemplo, esto podría lograrse configurando:
Consulte perlvar para obtener más información al respecto.
fuente
El almacenamiento en búfer de la salida depende de cómo
/homedir/MyScript
se implemente su programa . Si encuentra que la salida se está almacenando en búfer, debe forzarla en su implementación. Por ejemplo, use sys.stdout.flush () si es un programa de Python o use fflush (stdout) si es un programa de C.fuente
¿Ayudaría esto?
tail -f access.log | stdbuf -oL cut -d ' ' -f1 | uniq
Esto mostrará inmediatamente entradas únicas de access.log utilizando la utilidad stdbuf .
fuente
stdbuf
disponible en Ubuntu en este momento, no estoy seguro de dónde lo conseguí.stdbuf
es parte decoreutilus
(se encuentra conapt-file search /usr/bin/stdbuf
).El problema que se acaba de ver aquí es que tienes que esperar a que los programas que ejecutas desde tu script terminen su trabajo.
Si en su secuencia de comandos ejecuta el programa en segundo plano , puede intentar algo más.
En general, una llamada a
sync
antes de salir permite vaciar los búferes del sistema de archivos y puede ayudar un poco.Si en el script inicia algunos programas en segundo plano (
&
), puede esperar a que terminen antes de salir del script. Para tener una idea de cómo puede funcionar, puede ver a continuación.#!/bin/bash #... some stuffs ... program_1 & # here you start a program 1 in background PID_PROGRAM_1=${!} # here you remember its PID #... some other stuffs ... program_2 & # here you start a program 2 in background wait ${!} # You wait it finish not really useful here #... some other stuffs ... daemon_1 & # We will not wait it will finish program_3 & # here you start a program 1 in background PID_PROGRAM_3=${!} # here you remember its PID #... last other stuffs ... sync wait $PID_PROGRAM_1 wait $PID_PROGRAM_3 # program 2 is just ended # ...
Dado que
wait
funciona tanto con trabajos como conPID
números, una solución perezosa debería ser poner al final del scriptfor job in `jobs -p` do wait $job done
Más difícil es la situación si ejecuta algo que ejecuta otra cosa en segundo plano porque tiene que buscar y esperar (si es el caso) el final de todo el proceso hijo : por ejemplo, si ejecuta un demonio, probablemente no sea el caso esperar que termine :-).
Nota:
esperar $ {!} significa "esperar hasta que se complete el último proceso en segundo plano" donde
$!
está el PID del último proceso en segundo plano. Así que ponerwait ${!}
justo despuésprogram_2 &
es equivalente a ejecutar directamenteprogram_2
sin enviarlo en segundo plano con&
Con la ayuda de
wait
:Syntax wait [n ...] Key n A process ID or a job specification
fuente
Gracias
@user3258569
, ¡el script es quizás lo único que funcionabusybox
!Sin embargo, el caparazón se me estaba congelando después de eso. Buscando la causa, encontré estas grandes advertencias rojas "no usar en shells no interactivos" en la página del manual del script :
Cierto.
script -c "make_hay" -f /dev/null | grep "needle"
estaba congelando el caparazón para mí.Contrariamente a la advertencia, pensé que
echo "make_hay" | script
PASARÁ un EOF, así que intentéecho "make_hay; exit" | script -f /dev/null | grep 'needle'
¡Y funcionó!
Tenga en cuenta las advertencias en la página de manual. Puede que esto no funcione para usted.
fuente
La alternativa a stdbuf es
awk '{print} END {fflush()}'
que desearía que hubiera un bash incorporado para hacer esto. Normalmente no debería ser necesario, pero con versiones anteriores puede haber errores de sincronización de bash en los descriptores de archivos.fuente
No sé si funcionaría, pero ¿qué hay de llamar
sync
?fuente
sync
es una operación del sistema de archivos de bajo nivel y no está relacionada con la salida almacenada en búfer a nivel de la aplicación.sync
escribe cualquier búfer sucio del sistema de archivos en el almacenamiento físico, si es necesario. Esto es interno del sistema operativo; las aplicaciones que se ejecutan en la parte superior del sistema operativo siempre ven una vista coherente del sistema de archivos, ya sea que los bloques de disco se hayan escrito o no en el almacenamiento físico. Para la pregunta original, la aplicación (script) probablemente está almacenando la salida en un búfer interno de la aplicación, y el sistema operativo ni siquiera sabrá (todavía) que la salida está destinada a escribirse en stdout. Por lo tanto, una operación hipotética de tipo "sincronización" no podría "alcanzar" el script y extraer los datos.Tuve este problema con un proceso en segundo plano en Mac OS X usando el
StartupItems
. Así es como lo resuelvo:Si lo hago
sudo ps aux
puedo ver quemytool
se lanza.Descubrí que (debido al almacenamiento en búfer) cuando Mac OS X se apaga,
mytool
nunca transfiere la salida alsed
comando. Sin embargo, si ejecutosudo killall mytool
,mytool
transfiero la salida alsed
comando. Por lo tanto, agregué unstop
caso alStartupItems
que se ejecuta cuando Mac OS X se apaga:start) if [ -x /sw/sbin/mytool ]; then # run the daemon ConsoleMessage "Starting mytool" (mytool | sed .... >> myfile.txt) & fi ;; stop) ConsoleMessage "Killing mytool" killall mytool ;;
fuente
te guste o no, así es como funciona la redirección.
En su caso, la salida (lo que significa que su secuencia de comandos ha finalizado) de su secuencia de comandos se redirigió a ese archivo.
Lo que quiere hacer es agregar esas redirecciones en su secuencia de comandos.
fuente