Pipa con nome buffer non bloccante?


20

Sto cercando qualcosa che sospetto non esista: una pipe di nome buffer (non bloccata) non bloccabile da utilizzare dalla riga di comando. C'è una cosa del genere?

Ecco il caso d'uso: supponiamo che io abbia un processo che durerà a lungo in background e spargerà molto output stdout. Non mi interessa davvero l'output e non voglio memorizzarlo (forse non ho abbastanza spazio per), ma mi piacerebbe "entrare" periodicamente e seguire ciò che sta facendo, quindi abbandonare di nuovo e lasciarlo fare il suo lavoro. Quindi mi piacerebbe reindirizzare il suo output a questa teorica pipe bufferizzata, non bloccante, e poi attingere periodicamente.

Quindi in pratica voglio iniziare in questo modo ( 10Messendo la dimensione del buffer):

mkmagicfifo magicfifo 10M
spewingprocess > magicfifo &

... e periodicamente entrare per vedere cosa sta succedendo ...

tail -f magicfifo

... senza magicfifo archiviare tutto l'output (quindi, non un file normale), e senza che blocchi il processo di sputa quando si riempie e non viene toccato (quindi, non è un normale pipe chiamato).

Non penso che le soluzioni coinvolgano tailo prunelo faranno (beh, posso pensare a una soluzione alternativa che coinvolga tail), perché tailrichiederei comunque di archiviare tutti i dati da qualche parte (se voglio entrare e uscire dal guardarli), e prunedeve riscrivere il file, presumibilmente (ammetto di non aver provato / provato questo) interrompendo il reindirizzamento del processo generando tutto l'output.

Mi aspetto di poter scrivere qualche utilità per farlo, ma * nix ha così tanti aspetti interessanti di file e pipe e simili, non posso fare a meno di pensare che questo esista e semplicemente non lo so.

Quindi: esiste una cosa del genere, e in caso affermativo che cos'è?


1
Quello che stai descrivendo è un "buffer ad anello" o "buffer circolare". Non sono a conoscenza di strumenti della riga di comando per mantenere una cosa del genere, anche se sarebbe banale da creare.
Shawn J. Goff,

2
Dai un'occhiata alle soluzioni descritte in "Linux non bloccante fifo (registrazione su richiesta)", stackoverflow.com/questions/7360473/… .

1
Sembra che questo sia stato risolto su StackOverflow: stackoverflow.com/questions/7360473/…
James Blackburn,

@JamesBlackburn: grazie! Molto interessante.
TJ Crowder,

Risposte:


16

Penso che quello che stai cercando sia GNU screen. Mantiene un buffer per mantenere l'ultimo schermo pieno o due di output da uno o più programmi e consente di disconnettersi e tornare più tardi.


+1 per suggerire schermo. A proposito, è possibile configurarlo per contenere molte "righe della cronologia".
Shunz,

1
Grazie. Puoi fare un esempio di come lo applicheresti ai comandi che ho mostrato nella mia domanda? La pagina man dice che è un gestore di finestre (penso che significhino in senso terminale, non in senso grafico, ma comunque). E sarei ancora in grado di entrare (tramite ssh) e abbandonare se necessario? (Ad esempio, operazioni su server remoti.)
TJ Crowder,

Sì, puoi usare lo schermo GNU in questo modo. Dovresti creare una nuova sessione (potenzialmente denominata), eseguire il comando all'interno di quella sessione e quindi disconnetterti.
TML,

2
C'è anche tmuxe dtach- qualsiasi cosa nella stessa classe di applicazione terminal multiplexer / session manager dovrebbe essere in grado di ottenere la stessa cosa.
jw013,

5

È possibile utilizzare pv, fornisce tutto il buffering che si desidera in una pipeline. Puoi usarlo in questo modo:

sprewingprocess | pv -B 1g > ordinaryfifo &

Ciò ti darebbe fino a 1 GB di buffering tra spewingprocesse il fifo. La maggior parte delle distribuzioni Linux offrono pvin un pacchetto chiamato, che ci crediate o no pv,.


Grazie, ma non si bloccherebbe una volta che il buffer era pieno se non stavo leggendo il target chiamato pipe?
TJ Crowder,

1
Sì, ma che scelta hai? In un universo finito, non puoi avere un buffering letteralmente illimitato.
David Schwartz,

L'altra scelta è come ho descritto nella mia domanda: non memorizzare tutto l'output. Quando il buffer è pieno, le cose più vecchie vengono eliminate.
TJ Crowder,

Hmm, l'ho provato e sfortunatamente non funziona del tutto. Se il processo di lettura del fifo interrompe la lettura per un po ', pv blocca il tentativo di scrivere nel fifo e, poiché non è multithread, blocca anche la lettura dei dati nel buffer di pv. Quindi il buffer di pv continuerà a riempirsi solo mentre il processo di lettura del fifo continua a leggere. pv potrebbe essere in grado di leggere e bufferizzare alcuni dati, ma ciò non impedisce al writer di bloccarsi completamente.
Daniel S. Sterling,

1

Ho avuto lo stesso problema. Questa è la mia prima soluzione. Prima scrivi l'output in un file che tronciamo dopo ogni riga in modo che non cresca indefinitamente:

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

Quindi leggi dal file usando tail (dove 2> /dev/nullelimina il messaggio di errore "file troncato"):

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

In questo modo il buffer non cresce e possiamo multiplexare, ad esempio eseguire tutte le code che vogliamo. Tuttavia, il problema con questo approccio è che possiamo perdere dati quando tronciamo più velocemente di quanto coda possa leggere come mostra questo test:

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

Dopo aver eseguito per qualche tempo la prima e l'ultima riga sono:

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

Ma il file ha meno righe, quindi alcune vanno perse:

$ wc log.txt
67087  67087 392819 log.txt

Tuttavia, questa sembra una buona soluzione se non ti preoccupi così tanto della perdita di dati o quando il tuo processo di sputa non è abbastanza veloce per la perdita di dati.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.