el parámetro de time de espera de lectura (-t) no funciona?

No estoy seguro de cómo explicar el problema en general, así que usaré este ejemplo:

#!/bin/bash cleanup() { rm "$myfifo" rm "$mylock" kill '$(jobs -p)' } writer() { for i in $(seq 0 100); do echo "$(date -R) writing \"$i\"." echo "$i" > "$myfifo" done } reader() { while true; do flock 3 read -st 1 line status=$? if [ $status -eq 0 ]; then echo "$(date -R) reading \"$line\" in thread $1." else echo "$(date -R) status $status in thread $1. break fi flock -u 3 sleep 10 done 3<"$mylock" <"$myfifo" } trap cleanup EXIT myfifo="$(mktemp)" mylock="$(mktemp)" rm "$myfifo" mkfifo "$myfifo" writer & for i in $(seq 1 10); do reader $i & sleep 1 done wait 

Ahora esperaría que los hilos de lectura para cada uno tomen una línea (o unas pocas líneas) pero el primer process de lectura tomará todas las líneas (en un order aleatorio que no entiendo pero está bien), colóquelo en un buffer en algún lado y todos los demás processs de lectura no obtendrán ninguna línea.

Además, el parámetro de time de espera suministrado al command de lectura no parece funcionar porque los lectores 2-10 no salen.

  1. ¿Por qué?
  2. ¿Cómo puedo solucionar esto para que las líneas se distribuyan (algo) uniformemente entre los lectores?

Dejar read time de espera

read time de espera de read realmente funciona. El problema aquí es que abre un FIFO en bloques de modo de lectura hasta que el FIFO se abre en modo de escritura. Y en este caso, esto no se read que está bloqueado, esto es bash , cuando se networkingirige su FIFO a stdin.

Una vez que algún otro process abra el FIFO para escritura, bash abrirá exitosamente el FIFO para leer y ejecutará el command de read (que se ejecutará como se espera).

Si está utilizando Linux, la página man para fifo nos dice que "abrir un FIFO para lectura y escritura tendrá éxito tanto en modo de locking como de no locking". Por lo tanto, el siguiente command caducará incluso cuando ningún otro process abra el FIFO para escritura:

 read -st 1 data <> "$fifo" 

Cuidado con la condición de carrera

Una vez que el process de shell abre el FIFO para su lectura, el / los escritor / es se desbloquearán y, en el momento en que bash networkingireccione el FIFO al stdin y las llamadas read , el escritor podrá abrir el FIFO y escribir en él varias veces . Como solo lee una línea a la vez, se perderá cualquier línea que quede por leer mientras se cierra el FIFO en ambos extremos. Una mejor solución sería mantener el FIFO abierto networkingirigiéndolo a stdin durante todo el whiledone loop, como hiciste para fd 3. Algo como:

 while ...; do ... read -st 1 data ... done 3<"$lock" < "$fifo" 

O incluso en un nivel superior, si tiene varios lectores en paralelo. Lo que importa es mantener el FIFO abierto. Lo mismo para el lado del escritor.

Por ejemplo, con el código que publicaste con tu actualización, el nivel superior sería:

 # Writer writer > "$myfifo" & # Reader for i in $(seq 1 10); do reader $i & sleep 1 done < "$myfifo" 

Por supuesto, elimine las networkingirecciones a / from $myfifo cualquier otro lugar de su código y elimine el echo "$(date -R) writing \"$i\"." en su escritor, o networkingirigirlo a stderr, de lo contrario iría al FIFO.