Tengo una aplicación que debe registrar cada transacción. Cada mensaje de registro se vacía porque necesitamos tener un registro de lo que ocurrió antes de un bloqueo. Mis colegas y yo teníamos curiosidad acerca de cómo lograr los efectos de rendimiento del almacenamiento en búfer al tiempo que garantizamos que el mensaje de registro había abandonado el proceso.
Lo que se nos ocurrió es:
- hacer un FIFO en el que la aplicación pueda escribir, y
- redirigir el contenido de ese FIFO a un archivo normal a través de
cat
.
Es decir, lo que normalmente era:
app --logfile logfile.txt
es ahora:
mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo
¿Hay alguna trampa en este enfoque? Funcionó cuando lo probamos, pero queremos asegurarnos de que los mensajes lleguen al archivo de redireccionamiento incluso si la aplicación original falla.
(No tenemos el código fuente de la aplicación, por lo que las soluciones de programación están fuera de la cuestión. Además, la aplicación no escribirá en ella stdout
, por lo que no se puede canalizar directamente a un comando diferente. Por syslog
lo tanto, no es una posibilidad .)
Actualización: he añadido una recompensa. La respuesta aceptada no involucrará logger
por la simple razón de que nologger
es lo que he preguntado. Como dice la pregunta original, solo estoy buscando trampas al usar un FIFO.
Respuestas:
Tenga en cuenta que generalmente es necesario un quince en la programación donde la cantidad escrita puede superar la cantidad leída.
Como tal, una quinceañera no funcionará sin problemas como anticipa, pero resolvería su problema principal al presentar otra.
Hay tres posibles advertencias.
Esto significará que su problema (emular E / S con búfer en una escritura sin búfer) se resolverá. Esto se debe a que el nuevo 'límite' en su FIFO se convertirá en efecto en la velocidad de cualquier utilidad que escriba lo que está en la tubería al disco (que presumiblemente será una E / S almacenada).
Sin embargo, el escritor se vuelve dependiente de su lector de registros para funcionar. Si el lector deja de leer repentinamente, el escritor bloqueará. Si el lector sale repentinamente (digamos que se queda sin espacio en disco en su destino), el escritor SIGPIPE y probablemente salga.
Otro punto a mencionar es que si el servidor entra en pánico y el núcleo deja de responder, puede perder hasta 64k de datos que estaban en ese búfer.
Otra forma de solucionar esto será escribir registros en tmpfs (/ dev / shm en linux) y ajustar la salida a una ubicación de disco fija. Hay límites menos restrictivos en la asignación de memoria para hacer esto (¡no 64K, típicamente 2G!) Pero podría no funcionar para usted si el escritor no tiene una forma dinámica de volver a abrir archivos de registro (tendría que limpiar periódicamente los registros de tmpfs). Si el servidor entra en pánico en este método, podría perder MUCHOS más datos.
fuente
/dev/shm
. También lo habíamos considerado, aunque se me había olvidado usarlotail -f
.¿Qué sucede cuando su
cat logfifo
proceso muere, alguien lo mata por accidente o alguien accidentalmente lo señala a la ubicación incorrecta?Mi experiencia es que
app
rápidamente se bloqueará y colgará. He intentado esto con Tomcat, Apache y algunas pequeñas aplicaciones de construcción casera, y me encontré con el mismo problema. Nunca investigué muy lejos, porque unalogger
simple redirección de E / S hizo lo que quería. Por lo general, no necesito la integridad del registro, que es lo que está tratando de perseguir. Y como dices, no quieres registrador.Existe cierta discusión sobre este problema en Linux sin bloqueo de Fifo (registro bajo demanda) .
fuente
Sus opciones están bastante limitadas por la aplicación, pero lo que ha probado funcionará.
Hacemos algo similar con barniz y varnishncsa para obtener registros en algún lugar útil para nosotros. Tenemos un quince y solo leímoslo con syslog-ng y lo enviamos a donde lo necesitamos. Manejamos alrededor de 50 GB y hasta ahora no hemos encontrado ningún problema con este enfoque.
fuente
El entorno es CentOS y la aplicación escribe en un archivo ...
En lugar de enviar a un archivo normal, enviaría la salida a syslog y me aseguraría de que los mensajes de syslog se envíen a un servidor central, así como a nivel local.
Debería poder usar un script de shell como este:
También puede tomar la entrada (a
logger
) desdecat
otail -f
hacia una tubería:El único problema es que no se diferencia en función de la importancia del mensaje de registro (todo es AVISO ), pero al menos se registra y también se envía fuera del host a un servidor central.
La configuración de syslog depende del servidor que esté utilizando. Hay
rsyslog
ysyslog-ng
(ambos muy capaces).EDITAR : Revisado después de obtener más información del póster.
fuente
stdout
. El sistema operativo es CentOS (había etiquetado la pregunta como Linux , pero supongo que es fácil pasarla por alto). Todos los mensajes son de igual importancia, por lo que no hay diferencia entre un aviso y un error en esta aplicación.Slow query detected
yDatabase halted
?Usted escribe:
¿Intentaste iniciar sesión en el "archivo"
/dev/stdout
? Eso podría permitirle hacer algo como:fuente
No tiene sentido escribir en un quince y luego hacer que otro proceso lo escriba en un archivo. Simplemente escriba directamente en el archivo normalmente y una vez que
write()
regrese, estará en manos del núcleo; aún lo escribirá en el disco si la aplicación falla.fuente
fsync()
esperar a que cada escritura llegue al disco y NO QUIERES que eso suceda (arriesgando la pérdida en caso de un bloqueo del sistema)?write()
ha regresado, la aplicación puede bloquearse todo lo que quiera: los datos llegarán al disco siempre que el núcleo no se bloquee.