Zip слишком хорош (Mac OS X)
Я использую zip для регулярного резервного копирования локального каталога на удаленную машину. Они не верят в такие вещи, как rsync, поэтому это лучшее, что я могу сделать (?). Вот сценарий, который я использую
echo $(date)>>~/backuplog.txt;
if [[ -e /Volumes/backup/ ]];
then
cd /Volumes/Non-RAID_Storage/;
for file in projects/*;
do nice -n 10 zip -vru9 /Volumes/backup/nonRaidStorage.backup.zip "$file" 2>&1 | grep -v "zip info: local extra (21 bytes)">>~/backuplog.txt;
done;
else
echo "backup volume not mounted">>~/backuplog.txt;
fi
Все это прекрасно работает, за исключением того, что zip никогда не использует много ресурсов ЦП, поэтому, похоже, это занимает больше времени, чем следует. Кажется, он никогда не поднимается выше 5%. Я пытался сделать это хорошо -20, но это не имело никакого значения. Это просто скорость сети или диска, затрудняющая процесс, или я делаю что-то не так?
3 ответа
Вы, вероятно, найдете это zip
тратит большую часть своего времени на ожидание ввода / вывода (чтение файлов и запись сжатых версий), поэтому он не использует столько процессора, сколько вы ожидаете. Придавать процессу дополнительный приоритет через nice
не влияет на это, так как задача не может использовать больше процессорного времени, если она не передает данные со скоростью, которая потребует этого.
Под Linux вы можете увидеть эту ситуацию как высокий% времени как время ожидания ввода-вывода в выводе из top
и подобные утилиты, то же самое может быть верно для OSX.
Причины времени ожидания ввода-вывода могут включать:
- обработка множества маленьких файлов (много движений головы, чтение файлов и связанных структур каталогов)
- фрагментация файла
- конкурировать с другими действиями на соответствующих дисках (пользователи, копирующие / перемещающие / получающие доступ к файлам, запланированные AV-сканирования, ...), пока выполняется резервное копирование
- чтение файлов по сети (современный ЦП может архивировать данные гораздо быстрее, чем когда-либо может передать их канал со скоростью 100 Мбит / с, а задержка в сети усугубит эффект многих маленьких файлов) или передача сжатых данных по сети (если только Ваши данные сжимаются необычно, применяется то же условие "zip быстрее, чем ваша сеть на современных процессорах", так как они будут считывать данные с локальных дисков и обрабатывать данные быстрее, чем могут затем передать результат по сети).
- конкуренция в сети (если сервер, с которым вы разговариваете, имеет 100-мегабитную ссылку, а другие используют его, это может быть проблемой, в меньшей степени, если у него, конечно, более быстрая ссылка)
- медленные диски или медленные интерфейсы (если какой-либо из этих дисков подключен через USB2, он будет иметь тенденцию передавать не более 25 Мбайт / с, иногда медленнее, в зависимости от используемого адаптера USB и конкуренции с шиной USB с другими быстрыми устройствами, где современный внутренний диск будет вдвое больше, если не больше для массовых переводов)
Если вы хотите использовать "запасные" циклы ЦП и не можете сделать это за счет сокращения задержек ввода-вывода, вы можете вместо этого попробовать использовать 7zip - это использует гораздо больше процессорного времени на блок данных, но обеспечивает лучшее сжатие, чем zip by во многих случаях тоже довольно много, уменьшая размер ваших резервных копий. Будет ли это быстрее (потому что 7zip приводит к отправке меньшего количества данных по сети) или медленнее (потому что дополнительная вычислительная сложность означает, что ваш ЦП может стать узким местом, а не дисками / файловыми системами / сетью), зависит от точной спецификации вашей машины.
Редактировать:
Еще одна вещь: некоторые инструменты сообщают, что процесс использует каждое ядро, а некоторые - процессор (а некоторые в любом случае в зависимости от настроек), а zip обычно является многопоточным процессом. Таким образом, если у вас четырехъядерный процессор, то 5%, скорее всего, будут "5% от ЦП", или примерно 20% от одного ядра (хотя это может быть отскок между ядрами, если он однопоточный, он не будет работать более чем на одном в любой момент).
"nice -n 10" делает данную программу еще более "хорошей", используя более низкий приоритет. Возможно, вы имели в виду "nice -n -10" или "nice --10", что делает программу менее "приятной" и, таким образом, использует больше ресурсов процессора.
Вот мой сценарий в том виде, в котором он есть, если кому-то интересно. Очевидно, здесь есть несколько жестко закодированных путей, поэтому вы не можете просто запустить их в том виде, в каком они есть. Он ведет журнал своих операций и использует рычание, чтобы уведомлять вас о любых ошибках. Если у вас нет рычания / вы не хотите его устанавливать, просто закомментируйте / удалите все строки с пометкой growlnotify.
Одним из других изменений, которые я сделал, было копирование удаленного zip-архива на локальный диск перед добавлением файлов. Происходило то, что zip копировал архив в локальный временный файл, вносил изменения и затем перемещал временный файл обратно на удаленный диск для каждого файла / папки в каталоге верхнего уровня. Так что теперь он только один раз поднимает тяжелую сеть. Я вроде думаю, что я должен смотреть на смолу для такого рода вещей..
localBaseDirectory=/Volumes/Non-RAID_Storage/;
backedUpDirectory=projects;
backupVolume=/Volumes/video-prod/Backup;
backupFile=$backupVolume/Non-RAID_Storage_backup.zip;
zipTempfile=/Volumes/B_media
localBackupTempFile=/Volumes/A_Media/backuptemp.zip;
log=~/backuplog.txt;
temp=/var/tmp/backupError.txt;
##############################################
/usr/local/bin/growlnotify -m "backing up $backedUpDirectory on $localBaseDirectory" 2>&1 >/Dev/Null #need this redirect because growl chucks errors when run by cron;
echo $(date) > $log
if [[ -e $backupVolume ]];
then
if [[ -e $backupFile ]];
then cp $backupFile $localBackupTempFile;
mv $backupFile "$backupFile-old";
echo "copied old backup to $backupFile-old">>$log;
fi;
cd $localBaseDirectory 2>$temp;
if [[ -s $temp ]];
#notify if there was an error cding to this directory. -s is true if the file exists and is not zero sized
then cat $temp | /usr/local/bin/growlnotify -s;
cat $temp >> $log;
fi;
for file in $backedUpDirectory/*;
do
/usr/local/bin/growlnotify -m "backing up $file" 2>&1 >/Dev/Null;
#zip using verbose, recursive, update (ie don't overwrite files unless they're older), highest level compression
#zip creates a lot of garbage errors when being verbose eo send errors to a temp file, and stdout to the log file
nice -n 10 zip -vru9 -b $zipTempfile $localBackupTempFile "$file" 2>$temp |grep "adding:">>$log;
#add just the important errors to the log
cat $temp 2>/dev/null|grep "error:">>$log;
done;
echo "done adding to local zip file - moving to $backupFile">>$log;
#move the local version to the remote backup file
mv $localBackupTempFile $backupFile 2>>$log;
echo "$(date) - backed up Non-RAID_storage">>$log
/usr/local/bin/growlnotify -m "backed up $backedUpDirectory on $localBaseDirectory" 2>&1 >/Dev/Null;
else
/usr/local/bin/growlnotify -s -m "Backup volume not mounted" 2>&1 >/Dev/Null;
echo "backup volume not mounted" >> $log;
fi;