Das kopierte Verzeichnis scheint am Ziel größer zu werden

Das kopierte Verzeichnis scheint am Ziel größer zu werden

Ich habe den folgenden Code als Teil eines Shell-Skripts:

while [ $(ps -ef | awk '{print $2}' | grep -F "$CPPID") ]; do
    sleep 10
    awk -v "usbsize=$(/bin/df | grep -F $DEVICEMOUNTPOINTQ | awk '{print $3}')" -v "isosize=$(/bin/df | grep -F $ISOMOUNTPOINTQ | awk '{print $3}')" 'BEGIN { printf "%.1f", 100 * usbsize / isosize }' && echo "% copied..."
done

Dabei wird die Überwachung cpmit folgendem Vorgang durchgeführt:

cp -a "$ISOMOUNTPOINT"/* "$DEVICEMOUNTPOINT"

Und das funktioniert größtenteils gut, bis

90.5% copied...
94.2% copied...
97.8% copied...
101.6% copied...
102.7% copied...

Warum überschreitet dies 100 % der Größe der Quelle? Die Kopie erfolgt von einem Loop-gemounteten ISO auf eine NTFS-formatierte Partition auf einem USB-Flash-Laufwerk. Ich vermute, das ist wahrscheinlich eine Dateisystem-Sache?

Was fehlt in meinem Beispiel, damit die Größen übereinstimmen, sodass nach cpAbschluss eine Kopie von 100 % und nicht von 103 % vorliegt?

Danke.


Betreff: Kopfgeld

Ich werde die Prämie an die erste Person vergeben, die eine dem obigen Code ähnliche Lösung erstellt, die die folgenden Kriterien erfüllt:

  • Das Skript muss in der Lage sein, das Kopieren im Verhältnis 1:1 zu erkennen.
  • Das Skript darf keinen Wert anzeigen, der 100 % der kopierten Daten überschreitet.Jedoch...
  • Das Skript darf die Anzeige nicht einfach auf 100 % begrenzen, wenn es diese überschreitet.

Wenn die Datengrößetutaus irgendeinem Grund tatsächlich von Quelle zu Ziel unterschiedlich sind, dann hätte ich gerne ein Skript, das dies erkennt und trotzdem das tatsächlich kopierte Verhältnis anzeigt.

Antwort1

Hier ist Ihr Code vereinfacht und lesbarer:

while ps -p $CPPID > /dev/null
do
    sleep 10
    usbsize=$(/bin/df $DEVICEMOUNTPOINTQ | awk 'NR == 2 {print $3}')
    isosize=$(/bin/df $ISOMOUNTPOINTQ | awk 'NR == 2 {print $3}')
    awk -v "usbsize=$usbsize" -v "isosize=$isosize" 'BEGIN { printf "%.1f%% copied...\n", 100 * usbsize / isosize }'
done

Ihre letzte awkZeile könnte durch diese beiden ersetzt werden:

    percent=$(echo "$usbsize / $isosize * 100" | bc -l)
    printf "%.1f%% copied...\n" $percent

Dann könnten Sie direkt vor dieser Anweisung Folgendes tun printf:

if (( $(echo "$percent > 100" | bc) == 1 ))
then
    break
fi

wait $CPPIDund direkt nach dem Ende der Schleife hinzufügen while. Dadurch wird der Druckvorgang gestoppt, sobald 100 % erreicht sind.

SehenProzessmanagementbezüglich der Zuverlässigkeit von PIDs (sie werden recycelt).

Das Problem, das Sie sehen, ist wahrscheinlich darauf zurückzuführen, dass Sie den "used"-Wert des Zieldateisystems verwenden und nicht denUnterschiedim aktuellen Wert vom Startwert.

Versuchen Sie, vor der Schleife eine Zeile wie diese hinzuzufügen while:

startsize=$(/bin/df $DEVICEMOUNTPOINTQ | awk 'NR == 2 {print $3}')

und ändern Sie die Zeile innerhalb der Schleife wie folgt:

usbsize=$(/bin/df $DEVICEMOUNTPOINTQ | awk -v "start=$startsize" 'NR == 2 {print $3 - start}')

Dies alles ließe sich natürlich möglicherweise vermeiden, wenn Sie rsync --progressanstelle von verwenden würden cp.

Bearbeiten:

Versuchen Sie dies auch in der whileSchleife, wie oben gezeigt, um zu sehen, welche Zahlen in der Berechnung verwendet werden. Das könnte einen Hinweis darauf geben, was vor sich geht:

    awk -v "usbsize=$usbsize" -v "isosize=$isosize" 'BEGIN { printf "%d of %d, %.1f%% copied...\n", usbsize, isosize, 100 * usbsize / isosize }'

Antwort2

Mein erster Gedanke ist, dass es größtenteils von der Art der Dateien im Quellverzeichnis abhängt. Ich denke, dass die wahrscheinlichen Übeltäter Sparse-Dateien sind. Eine Sparse-Datei ist eine Datei, bei der stat.st_size != (stat.st_blksize * stat.st_blocks) ist; das heißt, die Gesamtgröße der Datei ist größer als die Anzahl der Datenblöcke, die mit dem Inode der Datei verknüpft sind. Alle nicht zugewiesenen Blöcke werden von den Systemaufrufen als Blöcke aus Nullen gelesen. Wenn Sie also cp(1) auf einer Sparse-Datei anwenden, enthält die Zieldatei mehr Blöcke (die nur Nullen enthalten) als die Quelldatei. Die Befehle du(1) und df(1) betrachten die Anzahl der Blöcke, nicht die Größe der Datei(en). Core-Dateien werden oft als Sparse-Dateien erstellt, da sie möglicherweise Speicher zuordnen müssen. Dieser Dateityp ist nützlich zum Erstellen von Disk-Images, beispielsweise zum Erstellen eines Laufwerks für einen virtuellen Host mit einer Größe von 15 GB. Es wäre sehr verschwenderisch, alle Blöcke zum Zeitpunkt der Erstellung zuzuweisen; Die Größe (st_size) könnte 15 GB betragen, aber die tatsächliche Anzahl der Blöcke könnte bei 0 beginnen.

Dies ist nur ein Dateityp, der beim Kopieren explodieren kann. Ohne zu wissen, was Sie in Ihrem Dateisystem haben, ist es schwer zu sagen, was sonst noch die Ursache sein könnte.

Antwort3

Sie können rsync im Nur-Lokal-Modus verwenden, wobei weder die Quelle noch das Ziel einen ':' im Namen haben, sodass es sich wie ein verbesserter Kopierbefehl verhält. Mit dem Parameter progress wird etwas Ähnliches wie das hier angezeigt (Quelle) :

$ rsync -r -v --progress -e ssh root@remote-server:~/pictures /home/user/
receiving file list ...
366 files to consider
pictures/IMG_1142.jpg
 4400662 100%   32.21kB/s    0:02:13 (xfer#31, to-check=334/366)
pictures/IMG_1172.jpg
 2457600  71%   32.49kB/s    0:00:29

Da dies nicht den Gesamtprozentsatz ergibt, könnte eine andere Lösung darin bestehen, dieses Skript zu verwenden (Quelle) :

#!/bin/sh
cp_p()
{
strace -q -ewrite cp -- "${1}" "${2}" 2>&1 \
  | awk '{
    count += $NF
        if (count % 10 == 0) {
           percent = count / total_size * 100
           printf "%3d%% [", percent
           for (i=0;i<=percent;i++)
              printf "="
           printf ">"
           for (i=percent;i<100;i++)
              printf " "
           printf "]\r"
        }
     }
     END { print "" }' total_size=$(stat -c '%s' "${1}") count=0
}

In Aktion:

% cp_p /mnt/raid/pub/iso/debian/debian-2.2r4potato-i386-netinst.iso /dev/null
76% [===========================================>                    ]

Sie können auch einen Blick aufDateien mit Fortschrittsbalken verschiebendort wird detailliert beschrieben, wie man zu cp und mv den Schalter -g hinzufügt, um den Fortschritt anzuzeigen.

verwandte Informationen