Я использую его du
для постоянного мониторинга объема данных, записываемых на USB-накопители, которые я копирую.
Я сравниваю использование диска на исходном и целевом дисках и отображаю пользователю ход копирования.
Проблема в том, что du
сообщается о наличии 100% данных на целевом диске, хотя я вижу, что в системном кэше все еще находится много данных, светодиод диска мигает, а диски не готовы к извлечению.
Я запускаю rsync
, sync
и umount
в последовательности, чтобы убедиться, что данные действительно там, прежде чем позволить пользователю удалить целевой диск. sync
Однако я не могу отслеживать ход выполнения. Поэтому пользователь увидит 100% задолго до того, как диски действительно будут синхронизированы.
Мне бы хотелось иметь возможность отслеживать «реальный» ход копирования, поскольку это действительно важно — нет смысла наблюдать за rsync
полным копированием файла размером 1 ГБ за 25 секунд, в то время как мне придется ждать еще 5 минут, пока sync
он запишется на диск (я преувеличиваю, но вы поняли).
Вот как я отслеживаю rsync
прогресс в цикле для каждого диска:
PROGRESS="$(echo "$(du -s "/MEDIA/TARGET" 2>/dev/null | cut -f 1) / $(du -s "/MEDIA/SOURCE" 2>/dev/null | cut -f 1) " | bc -l)"
$PROGRESS
представляет собой число с плавающей точкой от 0 до 1, указывающее соотношение между использованием исходного диска и использованием целевого диска.
Как изменить это так, чтобы учитывались только данные, которые уже синхронизированы с диском, а не просто ожидающие в системном кэше?
Редактировать:
Я обнаружил, что dd
может выполнять запись, минуя системный кэш. Я провел тест, и действительно, копирование файла таким образом заставляет du
сообщать фактические значения, и мои индикаторы прогресса наконец-то будут точными:
dd if=/media/SOURCE/file of=/media/TARGET/file bs=4M oflag=direct
Это использует кэш чтения, но отключает кэш записи, что упрощает отслеживание процесса без выполнения избыточных чтений. Проблема в том, что для использования dd
вместо rsync
мне нужно вручную пересоздать структуру каталогов. Мне не нужно заботиться об атрибутах файлов или датах изменения.
Думаю, я мог бы использовать комбинацию find
, mkdir
и dd
сначала пересоздать дерево каталогов, а затем скопировать файлы по одному. Интересно, есть ли какие-нибудь недостатки у этого подхода?
решение1
Похоже, лучший способ справиться с этим — использоватьпрямой вывод файла. Таким образом, du
показания будут гораздо точнее.
К сожалению, это возможно только dd
в том случае, поэтому нам нужно обойти две проблемы:
dd
не знает, что делать с каталогамиdd
можно копировать только один файл за раз
Сначала давайте определим входные и выходные каталоги:
SOURCE="/media/source-dir"
TARGET="/media/target-dir"
Теперь перейдем cd
в исходный каталог, чтобы find
сообщить относительные каталоги, которыми мы можем легко управлять:
cd "$SOURCE"
Дублируйте дерево каталогов из $SOURCE
в$TARGET
find . -type d -exec mkdir -p "$TARGET{}" \;
Дублировать файлы из $SOURCE
в $TARGET
без кэширования записи (но с использованием кэширования чтения!)
find . -type f -exec dd if={} of="$TARGET{}" bs=8M oflag=direct \;
Это не сохранит время изменения файла, владельца и другие атрибуты, но меня это устраивает.