У меня есть следующий код как часть сценария оболочки:
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
Это контролирует cp
выполнение следующей операции:
cp -a "$ISOMOUNTPOINT"/* "$DEVICEMOUNTPOINT"
И это хорошо работает по большей части, до
90.5% copied...
94.2% copied...
97.8% copied...
101.6% copied...
102.7% copied...
Почему это превышает 100% размера источника? Копия от смонтированного циклом ISO до отформатированного NTFS раздела на карте флэш-памяти с интерфейсом USB. Я предполагаю, что это - вероятно, вещь файловой системы?
Что является моим примером, отсутствующим для составления соответствия размеров, так, чтобы когда cp
завершается это - скопированных 100%, не 103%?
Спасибо.
Ре: щедрость
Я буду присуждать щедрость первому человеку, который произведет решение, подобное вышеупомянутому коду, который соответствует следующим критериям:
Если бы размер данных действительно отличается от источника до места назначения по некоторым причинам, то я хотел бы сценарий, который замечает это и все еще отображает фактическое скопированное отношение.
Здесь Ваш упрощенный код и сделал более читаемым:
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
Ваше последнее awk
строка могла быть заменена этими двумя:
percent=$(echo "$usbsize / $isosize * 100" | bc -l)
printf "%.1f%% copied...\n" $percent
Затем Вы могли сделать это незадолго до этого printf
оператор:
if (( $(echo "$percent > 100" | bc) == 1 ))
then
break
fi
и добавьте wait $CPPID
сразу после конца while
цикл. Это прекратит печатать прогресс, после того как 100% достигнуты.
Посмотрите, что управление процессами расценивает надежность PIDs (они переработаны).
Проблема, которую Вы видите, происходит, вероятно, из-за использования "используемого" значения целевой файловой системы, а не различия в текущем значении от значения запуска.
Попытайтесь добавить строку как это перед while
цикл:
startsize=$(/bin/df $DEVICEMOUNTPOINTQ | awk 'NR == 2 {print $3}')
и измените строку в цикле к:
usbsize=$(/bin/df $DEVICEMOUNTPOINTQ | awk -v "start=$startsize" 'NR == 2 {print $3 - start}')
Конечно, это могло бы все быть преодолимо, если бы Вы использовали rsync --progress
вместо cp
.
Править:
Кроме того, попробуйте это в while
цикл как показано выше для наблюдения, каковы числа, используемые в вычислении. Это могло бы дать представление относительно того, что продолжается:
awk -v "usbsize=$usbsize" -v "isosize=$isosize" 'BEGIN { printf "%d of %d, %.1f%% copied...\n", usbsize, isosize, 100 * usbsize / isosize }'
Мое первое через - то, что это в основном зависело бы от типа файлов в исходном каталоге. Я думал бы, что вероятный преступник является редкими файлами. Редкий файл является тем где где статистика st_size! = (статистика st_blksize * статистика st_blocks); то есть, полный размер файла больше, чем количество блоков данных, связанных с inode файла. Любые освобожденные блоки читаются как блок нулей системными вызовами. Таким образом, при использовании CP (1) на редком файле целевой файл будет содержать больше блоков (содержащий только нули), чем исходный файл. du (1) и df (1) команды смотрят на количество блоков, не размер файла (файлов). Базовые файлы часто создаются как редкие файлы, так как они, возможно, должны отобразить память. Этот тип файла полезен для создания образов дисков, например, создавая диск виртуального хоста, который имеет размер 15 ГБ. Было бы очень расточительно выделить все блоки во время создания; размер (st_size) мог составить 15 ГБ, но фактическое количество блоков могло запуститься в 0.
Это - всего один тип файла, который мог взорваться при копировании. Не зная, что Вы имеете в своей файловой системе, трудно сказать, что еще могло бы делать это.
Можно использовать rsync в локально-единственном режиме, где у и источника и места назначения нет a ':' на имя, так, чтобы это вело себя как улучшенная команда копии. С параметром прогресса это отображает что-то подобное этому (источник):
$ 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
Поскольку это не дает общий процент, другое решение могло бы состоять в том, чтобы использовать этот сценарий (источник):
#!/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
}
В действии:
% cp_p /mnt/raid/pub/iso/debian/debian-2.2r4potato-i386-netinst.iso /dev/null
76% [===========================================> ]
Можно также взглянуть на файлы перемещения с индикатором выполнения, который детализирует, как добавить к CP и mv, который-g переключают для показа прогресса.