¿Tubería nombrada tamponada sin bloqueo?

20

Estoy buscando algo que sospecho que no existe: una tubería con nombre sin búfer bloqueada (fifo) para usar desde la línea de comandos. ¿Hay tal cosa?

Este es el caso de uso: supongamos que tengo un proceso que se ejecutará mucho tiempo en segundo plano y arrojará una gran cantidad de resultados stdout. Realmente no me importa el resultado y no quiero almacenarlo (tal vez no tengo suficiente espacio para hacerlo), pero me gustaría "ingresar" periódicamente y seguir lo que está haciendo, luego abandonarlo nuevamente y deja que haga su trabajo. Por lo tanto, me gustaría redirigir su salida a esta tubería con nombre teóricamente protegida y sin bloqueo y luego aprovecharla periódicamente.

Entonces, básicamente, quiero comenzar así ( 10Msiendo el tamaño del búfer):

mkmagicfifo magicfifo 10M
spewingprocess > magicfifo &

... y visita periódicamente lo que sucede ...

tail -f magicfifo

... sin magicfifo almacenar toda la salida (por lo tanto, no es un archivo normal), y sin que bloquee el proceso de vomitar cuando se llena y no se toca (por lo tanto, no es una tubería con nombre normal).

No creo que las soluciones involucren tailo prunelo hagan (bueno, puedo pensar en una solución alternativa que involucre tail), porque tailaún requeriría que almacene todos los datos en algún lugar (si quiero entrar y dejar de mirarlo), y prunetiene que reescribir el archivo, presumiblemente (admito que no lo he probado / probado) rompiendo la redirección del proceso que genera toda la salida.

Espero poder escribir alguna utilidad para hacer esto, pero * nix tiene muchos aspectos geniales de archivos y tuberías y tal, simplemente no puedo evitar pensar que esto existe y simplemente no lo sé.

Entonces: ¿Existe tal cosa, y si es así, qué es?

TJ Crowder
fuente
1
Lo que está describiendo es un "buffer de anillo" o "buffer circular". No conozco ninguna herramienta de línea de comandos para mantener tal cosa, aunque sería trivial de crear.
Shawn J. Goff
2
Eche un vistazo a las soluciones descritas en "Fifo de Linux sin bloqueo (registro bajo demanda)", stackoverflow.com/questions/7360473/… .
1
Parece que esto se ha resuelto en StackOverflow: stackoverflow.com/questions/7360473/…
James Blackburn
@JamesBlackburn: ¡Gracias! Muy interesante.
TJ Crowder

Respuestas:

16

Creo que lo que estás buscando es GNU screen. Mantiene un búfer para mantener la última pantalla llena o dos de salida de uno o más programas y le permite desconectarse y volver más tarde.

psusi
fuente
+1 para sugerir pantalla. Por cierto, puede configurarlo para contener muchas "líneas de historial".
Sr. Shunz
1
Gracias. ¿Puedes dar un ejemplo de cómo aplicarías eso a los comandos que mostré en mi pregunta? La página del manual dice que es un administrador de ventanas (creo que significan en un sentido terminal, no gráfico, pero aún así). ¿Y todavía podría entrar (a través de ssh) y abandonarlo según sea necesario? (Por ejemplo, operaciones en servidores remotos.)
TJ Crowder
Sí, puedes usar la pantalla GNU de esta manera. Crearía una nueva sesión (potencialmente nombrada), ejecutaría su comando dentro de esa sesión y luego se desconectaría.
TML
2
También hay tmuxy dtach, cualquier cosa en la misma clase de aplicación de multiplexor de terminal / administrador de sesión debería ser capaz de lograr lo mismo.
jw013
5

Puede usarlo pv, proporciona tanta memoria intermedia como desee en una tubería. Puedes usarlo así:

sprewingprocess | pv -B 1g > ordinaryfifo &

Eso le daría hasta 1 GB de almacenamiento intermedio entre spewingprocessy los quince. La mayoría de las distribuciones de Linux se ofrecen pven un paquete llamado, lo creas o no pv,.

David Schwartz
fuente
Gracias, pero ¿no bloquearía eso una vez que el búfer estuviera lleno si no estuviera leyendo el objetivo llamado tubería?
TJ Crowder
1
Sí, pero ¿qué opción tienes? En un universo finito, no puedes tener un búfer literalmente ilimitado.
David Schwartz
La otra opción es como describí en mi pregunta: no almacenar toda la salida. Cuando el búfer está lleno, se tira lo más antiguo.
TJ Crowder
Hmm, probé esto y desafortunadamente no funciona del todo. Si el proceso de lectura del fifo deja de leer por un tiempo, pv bloquea el intento de escribir en el fifo, y debido a que no es multiproceso, eso también bloquea la lectura de datos en el búfer de pv. Por lo tanto, el búfer de pv solo continuará llenándose mientras el proceso de lectura del fifo sigue leyendo. pv puede leer y almacenar algunos datos en el búfer, pero no evita que el escritor se bloquee por completo.
Daniel S. Sterling
1

Yo tuve el mismo problema. Esta es mi primera solución. Primero escriba la salida en un archivo que truncamos después de cada línea para que no crezca indefinidamente:

spewingprocess | while read line; do echo $line > buffer.txt ; done

Luego, lea el archivo usando tail (donde 2> /dev/nullelimina el mensaje de error "file truncated"):

tail -f ./buffer.txt 2> /dev/null

De esta manera, el búfer no crece y podemos multiplexar, por ejemplo, ejecutar tantas colas como queramos. Sin embargo, el problema con este enfoque es que podemos perder datos cuando truncamos más rápido de lo que la cola puede leer, como muestra esta prueba:

for ((i=0; ; i++)) ; do echo "$i" ; done | while read line; do  echo $line > buffer.txt ; done
tail -f ./buffer.txt 2> /dev/null > log.txt

Después de correr durante un tiempo, la primera y la última línea son:

$ head -n 1 log.txt
0
$ tail -n 1 log.txt
78783

Pero el archivo tiene menos líneas, por lo que se pierden algunas:

$ wc log.txt
67087  67087 392819 log.txt

Aún así, esta parece una buena solución si no le importa tanto la pérdida de datos o si su proceso de generación de chispas no es lo suficientemente rápido como para que ocurra la pérdida de datos.

bterwijn
fuente