Сделать диск / копирование диска медленнее


28

Есть ли способ замедлить процесс копирования в Linux?

У меня большой файл, скажем, 10 ГБ, и я хотел бы скопировать его в другой каталог, но я не хочу копировать его с полной скоростью. Допустим, я бы хотел скопировать его со скоростью 1 Мб / с, а не быстрее. Я хотел бы использовать стандартную cpкоманду Linux .

Это возможно? (Если да, то как?)

Изменить : так, я добавлю больше контекста к тому, что я пытаюсь достичь.

У меня проблема в системе ArchLinux при копировании больших файлов через USB (на USB-диск, USB-диск и т. Д.). После заполнения кеша usb-буфера моя система перестает отвечать (даже мышь останавливается; она движется только спорадически). Операция копирования все еще продолжается, но она занимает 100% ресурсов коробки. Когда операция копирования завершается, все возвращается к нормальной жизни - все снова становится идеально отзывчивым.

Может быть, это аппаратная ошибка, я не знаю, но я знаю, что у меня есть две машины с этой проблемой (обе на ArchLinux, одна для настольного компьютера, вторая для ноутбука).

Самым простым и быстрым «решением» этого (я согласен, что это не «реальное» решение, а просто уродливый «взлом») было бы предотвратить заполнение этого буфера путем копирования файла со средней скоростью записи на USB-накопителе, для мне этого будет достаточно.


7
Если вы стремитесь ограничить скорость копирования с диска на диск, чтобы быть «хорошими» для других процессов ввода-вывода в системе, вам, вероятно, лучше воспользоваться возможностью ядра для настройки планирования ввода-вывода. вместо. В частности, ioniceможет использоваться, чтобы гарантировать, что ваш процесс копирования с диска на диск имеет запланированный ввод-вывод с более низким приоритетом, чем обычные процессы.
Steven Monday

3
Это классический проблемный вопрос XY . Вместо этого вам следует спросить, почему ваш рабочий стол перестает отвечать при копировании файлов на USB-устройство.
Майкл Хэмптон

4
На самом деле в Linux сегодня есть смехотворно большие буферы ввода / вывода. Объемы оперативной памяти выросли быстрее, чем скорость массовой памяти. Может быть, вы могли бы выполнить копирование с помощью dd (1) и синхронизировать его так, чтобы оно периодически синхронизировалось, а не буферизовалось? И труба просмотра (PV) имеет опцию ограничения скорости. Нечто подобное cat file | pv -L 3k > outfile. Тем не менее, это не то же самое, что использование cp (1).
Птман

@MichaelHampton, на форуме ArchLinux есть несколько нерешенных тем по этому вопросу, поэтому я решил, что попытаюсь справиться с этим по-другому, просто чтобы заставить его работать.
Антонон

@antonone Но Unix.SE - это не форумы ArchLinux. У кого-то здесь может быть решение.
Изката

Ответы:


23

Вы можете задушить трубу с pv -qL(или cstream -tобеспечивает аналогичную функциональность)

tar -cf - . | pv -q -L 8192 | tar -C /your/usb -xvf -

-q удаляет отчеты о прогрессе stderr

-LПредел в байтах.

Подробнее о --rate-limit/-Lфлаге от man pv:

-L RATE, --rate-limit RATE

    Limit the transfer to a maximum of RATE bytes per second.
    A suffix of "k", "m", "g", or "t" can be added to denote
    kilobytes (*1024), megabytes, and so on.

На этот ответ изначально указывалось, throttleно этот проект больше недоступен, поэтому он выпал из некоторых систем пакетов.


Если cpне может быть замедлено, то использование пользовательской команды является единственным вариантом, я думаю.
Антонон

1
Звучит слишком сложно по сравнению сrsync
LinuxSecurityFreak

выглядит более сложным, но более удобным для меня. Необходимо протестировать механизм блокировки файлов и замедлить копирование до нескольких байт / с, что невозможно с rsync. Я попытаюсь «
напечатать

грустно говорить, но проект мертвый bugs.debian.org/cgi-bin/bugreport.cgi?bug=426891
cljk

1
@cljk обновлен до pv. Спасибо.
Мэтт

23

Вместо этого cp -a /foo /barвы также можете использовать rsyncи ограничивать пропускную способность по мере необходимости.

Из rsyncруководства пользователя:

--bwlimit=KBPS

ограничить пропускную способность ввода / вывода; Кбайт в секунду

Итак, команда actall, также показывающая прогресс, будет выглядеть так:

rsync -av --bwlimit=100 --progress /foo /bar

Это звучит как хорошая идея для копирования старых дисков, которые я не хочу бить.
jeremyjjbrown

Не работает для чтения с /dev/zeroили/dev/random
cdosborn

rsync -a --bwlimit=1500 /source /destinationотлично работает для копирования гигантских папок со скоростью 1,5 МБ / с (что является хорошим компромиссом между предотвращением замедления работы любого сервера и не
отнимает

Sidenote: даже если на странице руководства может быть сказано, что вы можете использовать буквы для юнитов, например 20m, это поддерживается не на всех платформах, так что лучше придерживаться нотации KBytes.
Hubert Grzeskowiak

спас мой день! cgroup cgexec -g ... cp /in /outне работал все время (из терминала работал несколько раз, из сценария никогда), и я понятия не имею, почему ...
Aquarius Power

13

Я бы предположил, что вы пытаетесь не нарушать другую деятельность. Последние версии Linux включают в себя, ioniceчто позволяет вам контролировать планирование ввода-вывода.

Помимо разрешения различных приоритетов, существует дополнительная опция, ограничивающая ввод-вывод временем, когда диск в противном случае простаивает. Команда man ioniceотобразит документацию.

Попробуйте скопировать файл с помощью команды вроде:

ionice -c 3 cp largefile /new/directory

Если две директории находятся на одном устройстве, вы можете найти, что связывание файла делает то, что вы хотите. Если вы копируете для целей резервного копирования, не используйте эту опцию. lnочень быстро, так как сам файл не копируется. Пытаться:

ln largefile /new/directory

Или, если вы просто хотите получить к нему доступ из каталога на другом устройстве, попробуйте:

ln -s largefile /new/directory

хорошо работает ionice в Linux? я читаю это просто "подражать" работе и нет никакой разницы? +1 за ссылки
Ник

1
@ Ник Когда я его использовал, он вел себя как ожидалось. Процесс, к которому я применил ионизатор, значительно замедлился, а другие процессы, которые требовали ввода / вывода, могли работать так, как ожидалось. При умеренной нагрузке ввода-вывода от других процессов я смог эффективно приостановить процесс с высоким вводом-выводом, применив максимальную «правильность», как и ожидалось. Когда не было конкурирующего ввода-вывода, ионизированный процесс выполнялся как обычно.
BillThor

с 400-мегабайтным файлом, который я копировал с одного жесткого диска на твердотельный накопитель, первые 10 секунд он работал отлично, потом внезапно я обнаружил, что у меня высокая нагрузка ввода-вывода, и мне пришлось ждать, пока машина зависла на 1 минуту: /. У меня та же проблема с cgroup write io throttle, где это иногда работает, а с другими это вообще не будет работать.
Водолей Сила

7

Если ioniceрешения недостаточно (почему), и вы действительно хотите ограничить ввод-вывод до абсолютного значения, есть несколько возможностей:

  1. вероятно , проще: ssh. Он имеет встроенный лимит пропускной способности. Вы могли бы использовать, например tar(вместо cp) или scp(если это достаточно хорошо; я не знаю, как он обрабатывает символические ссылки и жесткие ссылки) или rsync. Эти команды могут передавать свои данные по конвейеру ssh. В случае, если tarвы пишете /dev/stdout(или -) и отправляете это sshклиенту, который выполняет другой tarна «удаленной» стороне.

  2. элегантный, но не в ванильном ядре (AFAIK): цель устройства отображения ioband. Это, конечно, работает, только если вы можете размонтировать исходный или целевой том.

  3. немного самописного веселья: grep "^write_bytes: " /proc/$PID/ioдает вам объем данных, записанных процессом. Вы можете написать скрипт, который запускается cpв фоновом режиме, спит, например, на 1/10-ю секунду, останавливает фоновый cpпроцесс ( kill -STOP $PID), проверяет сумму, которая была написана (и в этом случае считывает? О том же значении), рассчитывает, как долго cpнеобходимо сделать паузу, чтобы снизить среднюю скорость передачи до заданного значения, в течение этого времени он спит, просыпается cp( kill -CONT $PID) и т. д.


Да, обычно я просто использую lftp для подключения к localhost через scp и ограничиваю бандвич оттуда.
Антонон

5

Ваша проблема, вероятно, не с вашим компьютером, по сути, это, вероятно, хорошо. Но этот переходный слой флэш-памяти USB имеет собственный процессор, который должен отображать все ваши записи, чтобы компенсировать то, что может быть на 90% неисправным флэш-чипом, кто знает? Вы затопляете это, тогда вы затопляете свои буферы, тогда вы затопляете весь автобус, тогда вы застряли, чувак - в конце концов, именно там все ваши вещи. Это может показаться нелогичным, но на самом деле вам нужно заблокировать ввод-вывод - вам нужно позволить FTL задать темп, а затем просто идти в ногу.

(О взломе микроконтроллеров FTL: http://www.bunniestudios.com/blog/?p=3554 )

Все вышеперечисленные ответы должны работать, так что это больше "я тоже!" больше всего на свете: я был там полностью, чувак. Я решил свои собственные проблемы с помощью rsync --bwlimit arg (2.5 Мбит / с, казалось, было подходящим местом для одного безошибочного запуска - чего угодно, и я столкнулся бы с ошибками защиты от записи). rsync был особенно подходящим для моей цели, потому что я работал с целыми файловыми системами - так что было много файлов - и простой запуск rsync во второй раз решил бы все проблемы первого запуска (что было необходимо, когда я потерял терпение и попытался проскочить мимо 2.5mbs).

Тем не менее, я думаю, что это не так практично для одного файла. В вашем случае вы могли бы просто передать в dd значение raw-write - вы можете обрабатывать любой ввод таким образом, но только один целевой файл за раз (хотя, конечно, этот единственный файл может быть целым блочным устройством).

## OBTAIN OPTIMAL IO VALUE FOR TARGET HOST DEV ##
## IT'S IMPORTANT THAT YOUR "bs" VALUE IS A MULTIPLE ##
## OF YOUR TARGET DEV'S SECTOR SIZE (USUALLY 512b) ##
% bs=$(blockdev --getoptio /local/target/dev)

## START LISTENING; PIPE OUT ON INPUT ##
% nc -l -p $PORT | lz4 |\ 
## PIPE THROUGH DECOMPRESSOR TO DD ## 
>    dd bs=$bs of=/mnt/local/target.file \
## AND BE SURE DD'S FLAGS DECLARE RAW IO ##
>        conv=fsync oflag=direct,sync,nocache

## OUR RECEIVER'S WAITING; DIAL REMOTE TO BEGIN ##
% ssh user@remote.host <<-REMOTECMD
## JUST REVERSED; NO RAW IO FLAGS NEEDED HERE, THOUGH ## 
>    dd if=/remote/source.file bs=$bs |\
>    lz4 -9 | nc local.target.domain $PORT
> REMOTECMD  

Возможно, вы обнаружите, что netcat будет немного быстрее ssh для передачи данных, если вы попробуете. Во всяком случае, другие идеи уже были приняты, так почему бы и нет?

[EDIT]: я заметил упоминания о lftp, scp и ssh в другом посте и подумал, что мы говорим об удаленной копии. Местные намного проще:

% bs=$(blockdev --getoptio /local/target/dev)
% dd if=/src/fi.le bs=$bs iflag=fullblock of=/tgt/fi.le \
>    conv=fsync oflag=direct,sync,nocache

[EDIT2]: Отдайте должное: только что заметил, что в комментариях ptman избил меня примерно на пять часов.

Определенно, вы можете настроить $ bs для производительности здесь с помощью множителя - но некоторые файловые системы могут требовать, чтобы он был кратным размеру сектора целевой fs, так что имейте это в виду.


На моей машине флага --getiooptнет,--getoptio
Майкл Миор

2

Проблема в том, что копия заполняет вашу память блоками «в полете», вытесняя «полезные» данные. Известная (и очень трудно исправить) ошибка в обработке ядром Linux операций ввода-вывода для медленных устройств (в данном случае USB).

Возможно, вы можете попытаться выполнить копирование, например, с помощью сценария, подобного следующему (набросок для проверки концепции, полностью не проверенный!):

while true do
  dd if=infile of=outfile bs=4096 count=... seek=... skip=...
  sleep 5
done

регулировки seekи skipна countкаждом раунде. Нужно настроить, countчтобы он не заполнил (слишком много) памяти, и 5чтобы он истощал.


2

Понизьте лимит грязной страницы. Ограничение по умолчанию безумно.

Создайте /etc/sysctl.d/99-sysctl.conf с помощью:

vm.dirty_background_ratio = 3
vm.dirty_ratio = 10

Затем запустите sysctl -p или перезагрузите компьютер.

Происходит то, что данные читаются быстрее, чем они могут быть записаны на целевой диск. Когда linux копирует файлы, они считывают их в оперативную память, а затем помечают страницы как грязные для записи в место назначения. Грязные страницы не могут быть выгружены. Таким образом, если исходный диск быстрее, чем целевой диск, и вы копируете больше данных, чем у вас есть свободная память, операция копирования израсходует всю доступную память (или, по крайней мере, независимо от того, какое ограничение для «грязной» страницы) может быть больше, чем доступной оперативной памяти) и вызывают голодание, поскольку грязные страницы не могут быть выгружены, а чистые страницы используются и помечаются как грязные по мере освобождения.

Обратите внимание, что это не решит проблему полностью ... что в действительности нужно linux, так это какой-то способ арбитража при создании грязных страниц, так что при большой передаче происходит не все доступное ОЗУ / все разрешенные грязные страницы.


0

Эта проблема не имеет ничего общего с ошибками или сбоями в оборудовании или программном обеспечении, это просто ваше ядро, которое пытается быть доброжелательным к вам и возвращает вашу подсказку и копировать в фоновом режиме (она использует кэш в ядре: больше оперативной памяти, больше кэша но вы можете ограничить это, написав где-нибудь в / proc - не рекомендуется). Флэш-накопители работают слишком медленно, и пока ядро ​​пишет на них, другие операции ввода-вывода не могут быть выполнены достаточно быстро. ioniceупоминал несколько раз в других ответах это нормально. Но вы пытались просто смонтировать диск, -o syncчтобы избежать буферизации ОС? Это, наверное, самое простое решение.


После включения -o синхронизации мой интернет быстрее, чем скорость записи на этот USB-накопитель. Чего я не понимаю, так это того, почему ядро ​​не отслеживает, как быстро сбрасываются страницы кэша, и на основании этого составляет расписание будущих сбросов. Как будто он всегда работает на полной скорости, даже если этот плохой диск не справляется со скоростью. Но это тема для другого вопроса, я думаю.
антонон
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.