Gibt es eine Möglichkeit, den Fortschritt von Teer pro Datei zu sehen?

122

Ich habe ein paar große Dateien, die ich komprimieren möchte. Ich kann das zum Beispiel mit machen

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

Das Problem ist, dass ich keinen Fortschritt sehe, also habe ich keine Ahnung, wie lange es dauern wird oder so. Mit vkann ich zumindest sehen, wann jede Datei fertig ist, aber wenn die Dateien klein und groß sind, ist dies nicht besonders hilfreich.

Gibt es eine Möglichkeit, wie ich Teer dazu bringen kann, detailliertere Fortschritte zu zeigen? Wie ein erledigter Prozentsatz oder ein Fortschrittsbalken oder eine geschätzte verbleibende Zeit oder so. Entweder für jede einzelne Datei oder für alle oder für beide.

Svish
quelle

Antworten:

100

Ich bevorzuge Oneliner wie folgt:

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

Die Ausgabe wird folgendermaßen aussehen:

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

Für OSX (aus Kenjis Antwort)

tar cf - /folder-with-big-files -P | pv -s $(($(du -sk /folder-with-big-files | awk '{print $1}') * 1024)) | gzip > big-files.tar.gz
Prüfsumme
quelle
2
Unter OSX verwendet du kein Argument -b, um auf Folgendes zurückzugreifen: $ ((du -sk / folder-with | awk '{print $ 1}') * 1024))
Dienstag,
4
Schön, ein Einzeiler. Kannst du es erklären? Oder funktioniert es einfach auf magische Weise?
Kissaki
2
Ok, ich habe espv $FILE.tgz | tar xzf - -C $DEST_DIR
Krzysztof Szewczyk
1
Für OS X musste ich die eckige Klammer für die arithmetische Erweiterung verwenden, was folgendes tar cf - /folder-with-big-files -P | pv -s $[$(du -sk /folder-with-big-files | awk '{print $1}') * 1024] | gzip > big-files.tar.gzergab : Ohne diese Änderung bekam ich-bash: syntax error near unexpected token ')'
Dean Becker
1
Beachten Sie, dass der Fortschritt erst nach Abschluss des Befehls du angezeigt wird, was je nach Größe, Komplexität und Fragmentierung des Verzeichnisses einige Zeit in Anspruch nehmen kann.
Rooster242
75

Sie können pv verwenden , um dies zu erreichen. Um den Fortschritt korrekt zu melden, pvmuss bekannt sein, wie viele Bytes Sie darauf werfen. Der erste Schritt ist also die Berechnung der Größe (in KB). Sie können den Fortschrittsbalken auch vollständig löschen und sich nur pvmitteilen lassen , wie viele Bytes er gesehen hat. es würde ein "so viel und so schnell getan" melden.

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

Und dann:

% tar cvf - folder-with-big-files | pv -p -s ${SIZE}k | \ 
     bzip2 -c > big-files.tar.bz2
Akira
quelle
Cool. pvScheint nicht mit Mac OS X zu kommen, aber ich werde es ausprobieren, sobald ich einen Computer mit MacPorts habe. Könnten Sie erklären, was Sie dort tun? Nicht ganz sicher, was die erste Zeile genau macht.
Svish
4
Erste Zeile: Informationen darüber abrufen, wie viele Bytes verarbeitet werden. zweite zeile: benutze die größe aus der ersten zeile, damit pv 'progress' rendern kann. Da Sie Daten weiterleiten, weiß pv nicht, wie viele weitere Bytes kommen werden.
Akira
Ein Zusatz: SIZE=$(($SIZE * 1000 / 1024))- Ich weiß nicht, ob dies eine Eigenheit auf meiner speziellen Plattform ist oder nicht, daher füge ich es nicht der Antwort hinzu: duGibt eine Größe zurück, bei der 1 KB = 1024 Byte, während pv1 KB = 1000 erwartet wird Bytes. (Ich bin auf Ubuntu 10.04)
Izkata
2
@lzkata konnte man immer fragen Sie duIhre bevorzugte Blockgröße zu verwenden, zB du -s --block-size=1000, oder nur mit einfachem Bytes zu arbeiten, zum Beispiel fällt die k‚s aus den duund pvAnrufen. Trotzdem würde ich davon ausgehen, dass beide verwendet werden, 1024sofern nicht anders angegeben, z. B. das --siEinschalten du.
Legolas
1
oder lass einfach das K-Zeug fallen und verwende nur einfache Bytes ( du -sbund pv -sohne Modifikator). das sollte die ganze Verwirrung beenden.
Akira
22

bessere Fortschrittsanzeige ..

apt-get install pv dialog

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

Bildbeschreibung hier eingeben

Herr Schwarz
quelle
2
Dies funktioniert für die Extraktion, aber Sie müssen noch einen der komplizierteren Befehle für die Erstellung ausführen (das war die ursprüngliche Frage). Es könnte immer noch mit denen kombiniert werden; es ist nur komplizierter.
Daniel H
17

Schauen Sie sich die Optionen --checkpointund --checkpoint-actionauf der Tar-Infoseite an (wie bei meiner Distribution ist die Beschreibung für diese Optionen nicht in der Manpage → RTFI enthalten).

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

Mit diesen (und möglicherweise der Funktionalität zum Schreiben eines eigenen Prüfpunktbefehls) können Sie einen Prozentsatz berechnen ...

Helfer
quelle
3
Dies sollte die richtige Antwort sein. Andere erklären nur zusätzliche Tools (die nicht standardmäßig installiert sind), um etwas Ähnliches zu erreichen.
Carmine Giangregorio
@Sardathrion Vielleicht, weil es GNU- tarspezifisch ist.
Phk
11

Inspiriert von der Antwort des Helfers

Eine andere Möglichkeit ist die Verwendung der nativen tarOptionen

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 "]"

Das Ergebnis ist wie

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

ein komplettes Beispiel hier

campisano
quelle
4

Verwenden Sie nur Teer

tarhat die Option (seit v1.12), Statusinformationen auf Signalen auszudrucken --totals=$SIGNO, z. B .:

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

Die Total bytes written: [...]Informationen werden auf jedes USR1-Signal gedruckt, z.

pkill -SIGUSR1 tar

Quelle:

Murmeln
quelle
3

Ich habe gerade den Kommentar zu MacOS bemerkt und obwohl ich denke, dass die Lösung von @akira (und pv) viel besser ist , dachte ich, ich würde eine Vermutung und eine schnelle Umgehung in meiner MacOS-Box mit Teer verfolgen und ein SIGINFO-Signal senden. Komischerweise hat es funktioniert :) Wenn Sie auf einem BSD-ähnlichen System arbeiten, sollte dies funktionieren, aber auf einer Linux-Box müssen Sie möglicherweise ein SIGUSR1 senden und / oder tarfunktionieren möglicherweise nicht auf die gleiche Weise.

Der Nachteil ist, dass Sie nur eine Ausgabe (auf stdout) erhalten, die zeigt, wie weit die aktuelle Datei reicht, da ich vermute, dass sie keine Ahnung davon hat, wie groß der Datenstrom ist, den sie erhält.

Also ja, ein alternativer Ansatz wäre, Teer zu zünden und ihm regelmäßig SIGINFOs zu senden, wann immer Sie wissen möchten, wie weit es gekommen ist. Wie macht man das?

Der ad-hoc, manuelle Ansatz

Wenn Sie in der Lage sein möchten, den Status ad-hoc zu überprüfen, können Sie control-T(wie von Brian Swift erwähnt) das entsprechende Fenster anklicken, das das SIGINFO-Signal weiterleitet. Ein Problem dabei ist, dass es meiner Meinung nach an Ihre gesamte Kette gesendet wird. Wenn Sie also Folgendes tun:

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

Sie werden auch sehen, dass bzip2 seinen Status zusammen mit tar meldet:

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)

Dies funktioniert sehr gut, wenn Sie nur überprüfen möchten, ob das Programm nicht funktioniert taroder nur langsam. In diesem Fall müssen Sie sich wahrscheinlich nicht zu viele Gedanken über Formatierungsprobleme machen, da es sich nur um eine schnelle Überprüfung handelt.

Die Art des automatisierten Ansatzes

Wenn Sie wissen, dass es eine Weile dauern wird, Sie aber eine Art Fortschrittsanzeige benötigen, besteht eine Alternative darin, Ihren Teerprozess auszulösen und in einem anderen Terminal die PID zu ermitteln und sie dann in ein Skript zu werfen, das nur wiederholt ein Signal sendet . Wenn Sie beispielsweise das folgende Scriptlet haben (und es als say aufrufen 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?"

Wenn Sie es auf diese Weise aufrufen, erhalten Sie tareine Ausgabe wie diese , da Sie nur das Targeting durchführen

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

was ich zugebe, ist irgendwie hübsch.

Last but not least - mein Scripting ist ein bisschen verrostet. Wenn also jemand den Code bereinigen, reparieren oder verbessern möchte, dann ist alles in Ordnung :)

Tanantish
quelle
2
Wenn Sie in tarder Befehlszeile ausgeführt werden, wird durch Eingabe control-Tein SIGINFO gesendet. Wenn dies in einem Drehbuch wäre, würde es mitkill -INFO pid
Brian Swift
Völlig vergessen control-T, habe ich mich eindeutig daran gewöhnt, zu viele Konsolenfenster zu meinem eigenen Besten zu
spammen
1
warum kann ich -SIGINFO nicht sehen, wenn ich es tuekill -l
Felipe Alvarez
2

Inspiriert von Noah Spurriers Antwort

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
}

Quelle

Steven Penny
quelle
17
Ein wenig Kontext und Erklärung vielleicht?
Kissaki
1

Wenn Sie die Dateinummer anstelle der Gesamtgröße aller Dateien kennen:

Eine Alternative (weniger genau, aber geeignet) ist die Verwendung der Option -l und das Senden der Dateinamen anstelle des Dateninhalts in der Unix-Pipe.

Wir haben 12345 Dateien in mydir , der Befehl lautet:

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

Sie können diesen Wert (aufgrund Ihres Anwendungsfalls) im Voraus kennen oder einen Befehl wie find + wc verwenden , um ihn zu ermitteln:

[myhost@myuser mydir]$ find | wc -l
12345
bzimage
quelle
Warum also nicht diesen Befehl in einen Unterbefehl setzen? =)
Kirby
tar cfvz ~/mytarfile.tgz . | pv -s $(find . | wc -l) -l > /dev/null. Funktioniert es bei dir
Kirby
1

Methode basierend auf tqdm :

tar -v -xf tarfile.tar -C TARGET_DIR | tqdm --total $(tar -tvf tarfile.tar | wc -l) > /dev/null
J_Zar
quelle
1

Stellen Sie unter macOS zunächst sicher, dass alle Befehle verfügbar sind, und installieren Sie die fehlenden (z . B. pv) mithilfe von brew .

Wenn Sie nur tar ohne Komprimierung arbeiten möchten , gehen Sie mit:

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

Wenn Sie komprimieren möchten , gehen Sie mit:

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

Hinweis: Es kann eine Weile dauern, bis der Fortschrittsbalken angezeigt wird. Probieren Sie zuerst einen kleineren Ordner aus, um sicherzustellen, dass er funktioniert, und wechseln Sie dann in einen Ordner mit großen Dateien.

Bugs Bunny
quelle
0

Hier sind einige Zahlen einer Prometheus-Sicherung (Metrics Data) auf Debian / Buster AMD64:

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

Diesen Job abgebrochen, da nicht genügend Speicherplatz verfügbar war.

Experimentieren mit zstdals Kompressor zur tarÜberwachung des Fortschritts mit 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
Dileks
quelle