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

Existe alguma forma de ver o progresso do alcatrão por ficheiro?

Tenho alguns ficheiros grandes que gostaria de comprimir. Posso fazê-lo, por exemplo, com

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

O problema é que não consigo ver qualquer progresso, por isso não faço ideia de quanto tempo vai demorar ou algo do género. Usando v consigo pelo menos ver quando cada ficheiro está completo, mas quando os ficheiros são poucos e grandes, isto não é o mais útil.

Existe alguma forma de conseguir alcatrão para mostrar um progresso mais detalhado? Como uma percentagem feita ou uma barra de progresso ou tempo restante estimado ou algo assim. Ou para cada ficheiro ou para todos eles ou para ambos.

Respostas (13)

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

Eu prefiro oneliners como este:

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

Terá uma produção como esta:

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

Para OSX (da resposta de 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

Pode usar pv para o conseguir. Para relatar correctamente o progresso, pv precisa de saber quanto bytes lhe está a atirar. Portanto, o primeiro passo é calcular o tamanho (em kbyte). Também pode deixar cair completamente a barra de progresso e deixar apenas pv dizer-lhe quantos bytes viu; reportaria um “feito assim tanto e tão rápido”.

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

E depois:

% 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

melhor barra de progresso…

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

Ver as opções --checkpoint e --checkpoint-action na página de informação sobre alcatrão (quanto à minha distribuição, a descrição destas opções não está contida na página de homem → RTFI).

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

Com estas (e talvez a funcionalidade de escrever o seu próprio comando de ponto de controlo), pode calcular uma percentagem…

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

Inspirado pela resposta do ajudante

Outra maneira é usar as opções nativas 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 "]"

o resultado é como

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

um exemplo completo aqui

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

Utilizando apenas alcatrão

tar tem a opção (desde v1.12) de imprimir informação sobre o estado dos sinais usando --totals=$SIGNO, por exemplo:

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

A informação Total bytes written: [...] é impressa em cada sinal USR1, e.g:

pkill -SIGUSR1 tar

Fonte:

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

Acabei de reparar no comentário sobre MacOS, e enquanto penso que a solução de @akira (e pv) é much neater, pensei em perseguir um palpite e uma brincadeira rápida na minha caixa MacOS com alcatrão e enviar-lhe um sinal SIGINFO. Curiosamente, funcionou :) se estiver num sistema tipo BSD, este deve funcionar, mas numa caixa Linux, pode precisar de enviar um SIGUSR1, e/ou tar pode não funcionar da mesma maneira.

O lado negativo é que apenas lhe fornecerá uma saída (em stdout) que lhe mostrará até que ponto o ficheiro actual está, uma vez que suponho que não faz ideia do tamanho do fluxo de dados que está a receber.

Por isso, sim, uma abordagem alternativa seria disparar alcatrão e enviar-lhe SIGINFOS periodicamente sempre que quiser saber até onde chegou. Como fazer isto?

A abordagem ad-hoc, manual

Se quiser poder verificar o estado numa base ad-hoc, pode carregar em control-T (como Brian Swift mencionou) na janela relevante que enviará o sinal SIGINFO através. Um problema com isso é que o enviará para toda a sua cadeia, creio eu, portanto, se o fizer:

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

Verá também o bzip2 reportar o seu estado juntamente com o alcatrão:

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)

Isto funciona bem se quiser apenas verificar se o tar que está a correr está emperrado, ou apenas lento. Provavelmente não precisa de se preocupar muito com questões de formatação neste caso, uma vez que é apenas uma verificação rápida…

O tipo de abordagem automatizada

Se sabe que vai demorar algum tempo, mas quer algo como um indicador de progresso, uma alternativa seria disparar o seu processo de alcatrão e noutro trabalho terminal é o PID e depois atirá-lo para um script que apenas envia repetidamente um sinal. Por exemplo, se tiver o seguinte scriptlet (e invocá-lo como digamos 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 o invocar desta forma, uma vez que tem como alvo apenas tar obterá um resultado mais parecido com este

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)
...

o que admito, é um pouco bonito.

Por último mas não menos importante - a minha escrita está um pouco enferrujada, por isso se alguém quiser entrar e limpar/fixar/imprimir o código, vá pela sua vida :)

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

Inspirado pela resposta de 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 souber o número do ficheiro em vez do tamanho total de todos eles:

uma alternativa (menos precisa mas adequada) é usar a opção -l e enviar no tubo unix os nomes dos ficheiros em vez do conteúdo dos dados.

Vamos ter 12345 ficheiros em mydir, o comando é:

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

pode saber esse valor antecipadamente (devido ao seu caso de utilização) ou usar algum comando como find+wc para o descobrir:

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

Em macOS* , primeiro certifique-se de que tem todos os comandos disponíveis, e instale os que faltam (por exemplo pv) usando brew .

Se quiser apenas tar sem compressão , vá com:

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

Se quiser comprimir , vá com:

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

Se quiser comprimir , vá com

0x1&

Nota: Pode demorar algum tempo até que a barra de progresso apareça. Experimente primeiro uma pasta mais pequena para se certificar de que funciona, depois mude para pasta-com-arquivos grandes.

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

Método baseado em 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

Aqui estão alguns números de uma cópia de segurança (dados métricos) em Debian/buster AMD64:

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

Cancelei este trabalho porque não havia espaço em disco suficiente disponível.

Experimentar com zstd como compressor para tar com monitorização do 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

No meu uso diário, não preciso de saber o progresso exacto ao nível percentual da operação, apenas se estiver a funcionar e (por vezes) quanto está perto de ser concluída.

Resolvo esta necessidade minimamente, mostrando o número de ficheiros processados na sua própria linha; em Bash:

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

Como uso isto muitas vezes, defini uma função alias em . bashrc:

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

Depois simplesmente:

tar zcvf files.tgz directory | pvl

Posso calcular o número de ficheiros com antecedência se necessário com find directory | wc -l (Ou melhor, utilizando a mesma função mostrada [find directory | pvl] para esmagar a minha impaciência!)

Outro exemplo, definir direitos para um website virtual (depois disso, um chown -R é rápido porque os nomes dos ficheiros estão na cache do sistema de ficheiros):

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

É verdade que este processamento lateral poderia retardar a operação principal, mas penso que imprimir um carácter de retorno e alguns dígitos não pode ser demasiado caro (além disso, esperar que o próximo sinal de igualdade apareça ou que o dígito de percentagem mude parece lento em comparação com a velocidade subjectiva de mudança de dígitos!)