tar su pipe ma mantieni -v l'output dettagliato separato da STDERR


12

Un normale comando tar

tar cvf foo.tar ./foo >foo.out 2>foo.err

ha tre flussi IO di uscita

  • archiviare i dati su foo.tar
  • elenco di nomi di file su STDOUT (reindirizzato in foo.out)
  • messaggi di errore a STDERR (reindirizzati in foo.err)

Posso quindi controllare foo.err per i messaggi di errore senza dover leggere l'elenco dei nomi dei file.

se voglio fare qualcosa con i dati di archivio (instradalo attraverso netcat o uno speciale programma di compressione) posso usare l' -f -opzione tar così

tar cvf - ./foo 2>foo.err | squish > foo.tar.S

Ma ora la mia lista di nomi di file è mescolata con i miei messaggi di errore perché l' -voutput di tar ovviamente non può andare su STDOUT (è lì che scorre i dati di archivio), quindi Tar lo scrive abilmente su STDERR.

Usando la shell Korn, c'è un modo per costruire un comando che reindirizza il flusso di archivio a un altro comando ma cattura comunque l' -voutput separatamente da qualsiasi messaggio di errore.


Hai familiarità con tee? Questo sembra un caso d'uso piuttosto valido per questo.
HalosGhost

Risposte:


9

Se il tuo sistema supporta /dev/fd/n:

tar cvf /dev/fd/3 ./foo 3>&1 > foo.out 2>foo.err | squish > foo.tar.S

Che con le implementazioni AT&T di ksh(o basho zsh) potresti scrivere usando la sostituzione di processo :

tar cvf >(squish > foo.tar.S) ./foo > foo.out 2>foo.err

Sta facendo esattamente la stessa cosa, tranne che questa volta, la shell decide quale descrittore di file utilizzare invece 3(in genere sopra 9). Un'altra differenza è che questa volta ottieni lo stato di uscita tarinvece di squish. Sui sistemi che non supportano /dev/fd/n, alcune shell possono ricorrere a pipe con nome per quella funzione.

Se il tuo sistema non supporta /dev/fd/no la tua shell non può usare le pipe con nome per la sua sostituzione di processo, è lì che dovresti occuparti delle pipe con nome a mano .


6

Devi usare una pipe con nome per questo.

Innanzitutto creane uno nella cartella:

mkfifo foo.pipe

Quindi utilizzare quel comando:

tar cvf foo.pipe ./foo >foo.out 2>foo.err & cat foo.pipe >foo.tar

Avviso: la cat-part, ora può anche essere gzipo qualunque altra cosa, che può leggere da una pipe:

tar cvf foo.pipe ./foo >foo.out 2>foo.err & gzip -c foo.pipe >foo.tar

Spiegazione:

L'output viene scritto al tubo nome ( foo.pipe), dove un altro proccess ( cat, gzip, netcat) legge da. Quindi non perdi i canali stdout / stderr per informazioni.


1
Potrebbe valere la pena notare le implicazioni dell'uso di una named pipe. 1) la cosa migliore è impostare un umask 077(o usare una directory temporanea privata) per impedire ad altri processi di leggere o scrivere su di esso (su molti sistemi, pipe denominate, come altri file creati in modo leggibile dal mondo per impostazione predefinita), 2) è necessario assicurarsi la pipe denominata viene utilizzata solo da ogni istanza dello script (di nuovo una directory temporanea privata una tantum aiuta) 3) Ciò significa che è necessario ripulire in seguito o se interrotto.
Stéphane Chazelas,

1
+1 - Mi piace questa risposta. Sfortunatamente per me, c'è qualche stranezza nelle pipe nominate sul mio (vecchio) sistema che le rende inaffidabili quando provo questo.
RedGrittyBrick,

1
@ StéphaneChazelas - Penso che a volte possa essere più facile ripulire prima, come:p="/tmp/pipe$$"; mkfifo "$p"; (read na; cmd[s]...) <>"$p" & (echo;rm "$p"; cmd[s]...) >"$p"
mikeserv

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.