Mam następujący kod jako część skryptu powłoki:
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
Monitoruje to cp
wykonując następującą operację:
cp -a "$ISOMOUNTPOINT"/* "$DEVICEMOUNTPOINT"
I to działa w większości dobrze, dopóki
90.5% copied...
94.2% copied...
97.8% copied...
101.6% copied...
102.7% copied...
Dlaczego przekracza to 100% wielkości źródła? Kopia pochodzi z zamontowanego w pętli ISO na partycji sformatowanej w systemie NTFS na dysku flash USB. Zgaduję, że to prawdopodobnie kwestia systemu plików?
Czego brakuje w moim przykładzie, aby dopasować rozmiary, aby po cp
zakończeniu został w 100% skopiowany, a nie 103%?
Dzięki.
Re: Bounty
Przyznam nagrodę pierwszej osobie, która opracuje rozwiązanie podobne do powyższego kodu, które spełnia następujące kryteria:
- Skrypt musi być w stanie wykryć kopiowanie w stosunku 1: 1
- Skrypt nie może wyświetlać wartości przekraczającej 100% skopiowanej, jednak ...
- Skrypt nie może po prostu ograniczać wyświetlania w 100% skopiowanym, gdy go przekroczy.
Jeśli rozmiar danych jest rzeczywiście różnią się od źródła do miejsca przeznaczenia, dla jakiegoś powodu, to chciałbym skrypt, który zauważa to i nadal wyświetla rzeczywisty stosunek kopiowane.
źródło
Odpowiedzi:
Oto twój kod uproszczony i bardziej czytelny:
Twój ostatni
awk
wiersz można zastąpić tymi dwoma:Następnie możesz to zrobić tuż przed tym
printf
stwierdzeniem:i dodaj
wait $CPPID
tuż po zakończeniuwhile
pętli. To zatrzyma postęp drukowania po osiągnięciu 100%.Zobacz Zarządzanie procesami dotyczące niezawodności PID (są one poddawane recyklingowi).
Problem, który widzisz, prawdopodobnie wynika z użycia „używanej” wartości docelowego systemu plików, a nie z różnicy między wartością bieżącą a wartością początkową.
Spróbuj dodać taką linię przed
while
pętlą:i zmień linię wewnątrz pętli na:
Oczywiście można tego wszystkiego uniknąć, jeśli użyjesz go
rsync --progress
zamiastcp
.Edytować:
Spróbuj również w
while
pętli, jak pokazano powyżej, aby zobaczyć, jakie są liczby używane w obliczeniach. To może dać wskazówkę, co się dzieje:źródło
bc
jest tylko kolejną opcją do wykonywania matematyki zmiennoprzecinkowej, która może skutkować krótszymi poleceniami. Uznałem za pewnik, że jest wszechobecny. AWK jest w tym celu w porządku./bin/df $DEVICEMOUNTPOINTQ
i co robią/bin/df $ISOMOUNTPOINTQ
? Czy to jedna linia nagłówka, po której następuje coś takiego/dev/xxx 1111 2222 3333 44% /mountpoint
? Jeśli dodaszecho "[$DEVICEMOUNTPOINTQ] [$ISOMOUNTPOINTQ]"
przed komendą AWK, co wyprowadza? Nawiasem mówiąc, mam literówkę w tym fragmencie. Na końcu jest dodatkowy podwójny cytat. Spróbuj to usunąć.Po pierwsze, będzie to w dużej mierze zależało od rodzaju plików w katalogu źródłowym. Sądzę, że prawdopodobnym winowajcą są rzadkie pliki. Plik rzadki to taki, w którym stat.st_size! = (Stat.st_blksize * stat.st_blocks); to znaczy całkowity rozmiar pliku jest większy niż liczba bloków danych powiązanych z i-węzłem pliku. Wszelkie nieprzydzielone bloki są odczytywane jako blok zer przez wywołania systemowe. Więc jeśli użyjesz cp (1) na pliku rzadkim, plik docelowy będzie zawierał więcej bloków (zawierających tylko zera) niż plik źródłowy. Polecenia du (1) i df (1) sprawdzają liczbę bloków, a nie rozmiar pliku (ów). Pliki podstawowe są często tworzone jako pliki rzadkie, ponieważ mogą wymagać mapowania pamięci. Ten typ pliku jest przydatny do tworzenia obrazów dysków, na przykład do tworzenia wirtualnego dysku hosta o rozmiarze 15 GB. Byłoby bardzo marnotrawstwem przydzielanie wszystkich bloków w czasie tworzenia; rozmiar (st_size) może wynosić 15 GB, ale rzeczywista liczba bloków może zaczynać się od 0.
To tylko jeden typ pliku, który może wybuchnąć po skopiowaniu. Nie wiedząc, co masz w systemie plików, trudno powiedzieć, co jeszcze może to zrobić.
źródło
Możesz użyć rsync w trybie tylko lokalnym, w którym zarówno źródło, jak i miejsce docelowe nie mają w nazwie znaku „:”, dzięki czemu zachowuje się jak ulepszone polecenie kopiowania. Z parametrem progress wyświetla coś podobnego do tego ( źródło ):
Ponieważ nie daje to całkowitego procentu, innym rozwiązaniem może być użycie tego skryptu ( źródła ):
W akcji:
Możesz także przejrzeć pliki przenoszenia z paskiem postępu, które szczegółowo opisują, jak dodać do cp i mv przełącznik -g, aby pokazać postęp.
źródło