2010-07-28 11:51:37 +0000 2010-07-28 11:51:37 +0000
133
133

C'è un modo per vedere i progressi del tar per ogni file?

Ho un paio di file grandi che vorrei comprimere. Posso farlo per esempio con

tar cvfj big-files.tar.bz2 folder-with-big-files

Il problema è che non posso vedere alcun progresso, quindi non ho idea di quanto tempo ci vorrà o qualcosa del genere. Usando v posso almeno vedere quando ogni file è completato, ma quando i file sono pochi e grandi questo non è il massimo dell'aiuto.

C'è un modo per far sì che tar mostri un progresso più dettagliato? Come una percentuale di completamento o una barra di progresso o un tempo stimato rimanente o qualcosa del genere. O per ogni singolo file o per tutti o per entrambi.

Risposte (13)

109
109
109
2013-10-25 08:15:15 +0000

Preferisco gli oneliner come questo:

tar cf - /folder-with-big-files -P | pv -s $(du -sb /folder-with-big-files | awk '{print $1}') | gzip > big-files.tar.gz

Avrà un output come questo:

4.69GB 0:04:50 [16.3MB/s] [==========================>] 78% ETA 0:01:21

Per OSX (dalla risposta di Kenji)

tar cf - /folder-with-big-files -P | pv -s $(($(du -sk /folder-with-big-files | awk '{print $1}') * 1024)) | gzip > big-files.tar.gz
77
77
77
2010-07-28 12:01:07 +0000

Potete usare pv per ottenere questo. Per riportare correttamente il progresso, pv ha bisogno di sapere quanti byte gli state lanciando. Quindi, il primo passo è calcolare la dimensione (in kbyte). Puoi anche abbandonare completamente la barra di progresso e lasciare che pv ti dica solo quanti byte ha visto; riporterebbe un ‘fatto così tanto e così velocemente’.

% SIZE=`du -sk folder-with-big-files | cut -f 1`

E poi:

% tar cvf - folder-with-big-files | pv -p -s ${SIZE}k | \ 
     bzip2 -c > big-files.tar.bz2
23
23
23
2012-08-28 08:26:14 +0000

migliore barra di avanzamento..

apt-get install pv dialog

(pv -n file.tgz | tar xzf - -C target_directory ) \
2>&1 | dialog --gauge "Extracting file..." 6 50

17
17
17
2011-08-04 20:53:06 +0000

Controlla le opzioni --checkpoint e --checkpoint-action nella pagina informativa di tar (come per la mia distribuzione, la descrizione di queste opzioni non è contenuta nella pagina man → RTFI).

Vedi https://www.gnu.org/software/tar/manual/html_section/tar_26.html

Con queste (e forse la funzionalità per scrivere il proprio comando di checkpoint), puoi calcolare una percentuale…

11
11
11
2017-07-16 00:22:25 +0000

Ispirato dalla risposta di helper

Un altro modo è usare le opzioni native tar FROMSIZE=`du -sk ${FROMPATH} | cut -f 1`; CHECKPOINT=`echo ${FROMSIZE}/50 | bc`; echo "Estimated: [==================================================]"; echo -n "Progess: ["; tar -c --record-size=1K --checkpoint="${CHECKPOINT}" --checkpoint-action="ttyout=>" -f - "${FROMPATH}" | bzip2 > "${TOFILE}"; echo "]"

il risultato è come

Estimated: [==================================================]
Progess: [>>>>>>>>>>>>>>>>>>>>>>>

un esempio completo qui

8
8
8
2018-06-15 05:03:41 +0000

Utilizzando solo tar

tar ha l'opzione (dalla v1.12) di stampare informazioni di stato sui segnali che usano --totals=$SIGNO, ad es:

tar --totals=USR1 -czf output.tar input.file
Total bytes written: 6005319680 (5.6GiB, 23MiB/s)

Le informazioni Total bytes written: [...] vengono stampate su ogni segnale USR1, ad esempio:

pkill -SIGUSR1 tar

Fonte:

3
3
3
2012-04-21 20:44:39 +0000

Ho appena notato il commento su MacOS, e mentre penso che la soluzione di @akira (e pv) sia molto più ordinata ho pensato di inseguire un'intuizione e un veloce playaround nella mia scatola MacOS con tar e inviandogli un segnale SIGINFO. Stranamente, ha funzionato :) se siete su un sistema simile a BSD, questo dovrebbe funzionare, ma su una macchina Linux, potreste aver bisogno di inviare un SIGUSR1, e/o tar potrebbe non funzionare allo stesso modo.

Il lato negativo è che vi fornirà solo un output (su stdout) che vi mostrerà a che punto è il file corrente, poiché immagino che non abbia idea di quanto sia grande il flusso di dati che sta ricevendo.

Quindi sì, un approccio alternativo sarebbe quello di avviare tar e inviargli periodicamente dei SIGINFO ogni volta che volete sapere a che punto è arrivato. Come si fa?

L'approccio manuale ad-hoc

Se vuoi essere in grado di controllare lo stato su una base ad-hoc, puoi premere control-T (come ha detto Brian Swift) nella relativa finestra che invierà il segnale SIGINFO. Un problema con questo è che lo invierà a tutta la vostra catena, credo, quindi se state facendo:

% tar cvf - folder-with-big-files | bzip2 -c > big-files.tar.bz2

Vedrete anche bzip2 segnalare il suo stato insieme a tar:

a folder-with-big-files/big-file.imgload 0.79 cmd: bzip2 13325 running 
      14 0.27u 1.02s 

      adding folder-with-big-files/big-file.imgload (17760256 / 32311520)

Questo funziona bene se volete solo controllare se quel tar che state eseguendo è bloccato, o semplicemente lento. Probabilmente non hai bisogno di preoccuparti troppo dei problemi di formattazione in questo caso, dato che è solo un controllo veloce.

Il tipo di approccio automatico

Se sai che ci vorrà un po’ di tempo, ma vuoi qualcosa come un indicatore di progresso, un'alternativa potrebbe essere quella di lanciare il tuo processo tar e in un altro terminale lavorare sul suo PID e poi lanciarlo in uno script che invia ripetutamente un segnale. Per esempio, se avete il seguente scriptlet (e lo invocate come script.sh PID-to-signal interval-to-signal-at):

#!/bin/sh

PID=$1
INTERVAL=$2
SIGNAL=29 # excuse the voodoo, bash gets the translation of SIGINFO, 
               # sh won't..

kill -0 $PID # invoke a quick check to see if the PID is present AND that
               # you can access it..

echo "this process is $$, sending signal $SIGNAL to $PID every $INTERVAL s"
while [$? -eq 0]; do
     sleep $INTERVAL;
     kill -$SIGNAL $PID; # The kill signalling must be the last statement
                            # or else the $? conditional test won't work
done
echo "PID $PID no longer accessible, tar finished?"

Se lo invocate in questo modo, poiché state puntando solo a tar otterrete un output più simile a questo

a folder-with-big-files/tinyfile.1
a folder-with-big-files/tinyfile.2
a folder-with-big-files/tinyfile.3
a folder-with-big-files/bigfile.1
adding folder-with-big-files/bigfile.1 (124612 / 94377241)
adding folder-with-big-files/bigfile.1 (723612 / 94377241)
...

che, ammetto, è piuttosto carino.

Ultimo ma non meno importante - il mio scripting è un po’ arrugginito, quindi se qualcuno vuole andare a pulire/correggere/migliorare il codice, vada per la sua vita :)

2
2
2
2012-04-18 01:00:19 +0000

Ispirato dalla risposta di Noah Spurrier

function tar {
  local bf so
  so=${*: -1}
  case $(file "$so" | awk '{print$2}') in
  XZ) bf=$(xz -lv "$so" |
    perl -MPOSIX -ane '$.==11 && print ceil $F[5]/50688') ;;
  gzip) bf=$(gzip -l "$so" |
    perl -MPOSIX -ane '$.==2 && print ceil $F[1]/50688') ;;
  directory) bf=$(find "$so" -type f | xargs du -B512 --apparent-size |
    perl -MPOSIX -ane '$bk += $F[0]+1; END {print ceil $bk/100}') ;;
  esac
  command tar "$@" --blocking-factor=$bf \
    --checkpoint-action='ttyout=%u%\r' --checkpoint=1
}

Fonte

1
1
1
2017-09-15 12:38:27 +0000

Se si conosce il numero di file invece della dimensione totale di tutti i file:

un'alternativa (meno accurata ma adatta) è usare l'opzione -l e inviare nella pipe unix i nomi dei file invece del contenuto dei dati.

Abbiamo 12345 file in mydir, il comando è:

[myhost@myuser mydir]$ tar cfvz ~/mytarfile.tgz .|pv -s 12345 -l > /dev/null

puoi conoscere tale valore in anticipo (per il tuo caso d'uso) o usare qualche comando come find+wc per scoprirlo:

[myhost@myuser mydir]$ find | wc -l
12345
1
1
1
2019-09-02 20:05:09 +0000

Su macOS , prima assicuratevi di avere tutti i comandi disponibili, e installate quelli mancanti (per esempio pv) usando brew .

Se volete solo tar senza compressione , andate con:

tar -c folder-with-big-files | pv -s $[$(du -sk folder-with-big-files | awk '{print $1}') * 1024] > folder-with-big-files.tar

Se vuoi comprimere , vai con:

tar cf - folder-with-big-files -P | pv -s $[$(du -sk folder-with-big-files | awk '{print $1}') * 1024] | gzip > folder-with-big-files.tar.gz

Nota: Potrebbe volerci un po’ prima che la barra di progresso appaia. Prova prima su una cartella più piccola per assicurarti che funzioni, poi passa alla cartella con grandi file.

1
1
1
2018-04-27 06:44:10 +0000

Metodo basato su tqdm :

tar -v -xf tarfile.tar -C TARGET_DIR | tqdm --total $(tar -tvf tarfile.tar | wc -l) > /dev/null
0
0
0
2019-09-13 15:39:11 +0000

Ecco alcuni numeri di un backup prometheus (dati metrici) su Debian/buster AMD64:

root# cd /path/to/prometheus/
root# tar -cf - ./metrics | ( pv -p --timer --rate --bytes > prometheus-metrics.tar )

Cancellato questo lavoro perché non c'era abbastanza spazio su disco disponibile.

Sto sperimentando zstd come compressore per tar con il monitoraggio del progresso usando pv:

root# apt-get update
root# apt-get install zstd pv

root# tar -c --zstd -f - ./metrics | ( pv -p --timer --rate --bytes > prometheus-metrics.tar.zst )
10.2GiB 0:11:50 [14.7MiB/s]

root# du -s -h prometheus
62G prometheus

root# du -s -h prometheus-metrics.tar.zst
11G prometheus-metrics.tar.zst
0
0
0
2020-02-25 22:54:21 +0000

Nel mio uso quotidiano non ho bisogno di sapere l'esatto progresso a livello percentuale dell'operazione, solo se sta funzionando e (a volte) quanto è vicino al completamento.

Risolvo minimamente questa necessità mostrando il numero di file processati nella propria riga; in Bash:

let n=0; tar zcvf files.tgz directory | while read LINE; do printf "\r%d" $((n++)) ; done ; echo

Poiché lo uso molto, ho definito un alias di funzione in . bashrc:

function pvl { declare -i n=0; while read L ; do printf "\r%d" $((++n)) ; done ; echo ; }

Poi semplicemente:

tar zcvf files.tgz directory | pvl

Posso calcolare il numero di file in anticipo se necessario con find directory | wc -l (O meglio usando la stessa funzione indicata [find directory | pvl] per schiacciare la mia impazienza!)

Un altro esempio, impostando i diritti per un sito virtuale (dopo di che, un chown -R è veloce perché i nomi dei file sono nella cache del filesystem):

find /site -print -type d -exec chmod 2750 "{}" \; -o -type f -exec chmod 640 "{}" | pvl

È vero che questa elaborazione laterale potrebbe rallentare l'operazione principale, ma penso che stampare un carattere di ritorno e qualche cifra non possa essere troppo costoso (inoltre, aspettare che appaia il prossimo segno uguale o che cambi la cifra percentuale sembra lento rispetto alla velocità soggettiva di cambiare le cifre!)