Зробіть копію диска / диска повільніше


28

Чи існує метод уповільнення процесу копіювання в Linux?

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

Чи можливо це? (Якщо так, то як?)

Редагувати : отже, я додам більше контексту до того, що намагаюся досягти.

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

Можливо, це помилка апаратури, я не знаю, але я знаю, що у мене є дві машини з цією проблемою (обидва знаходяться в ArchLinux, одна - коробка для робочого столу, друга - ноутбук).

Найпростішим та найшвидшим "рішенням" цього (я згоден, що це не "справжнє" рішення, а просто некрасивий "хак") було б запобігти заповненню цього буфера, копіюючи файл із середньою швидкістю запису на USB-накопичувач, для мені цього було б достатньо.


7
Якщо ви прагнете обмежити швидкість копіювання з диска на диск, намагаючись бути "приємним" для інших процесів, пов'язаних з входом / виводом в системі, вам, ймовірно, краще скористатися можливістю ядра налаштовувати планування вводу / виводу. замість цього. Зокрема, це ioniceможе бути використано для того, щоб процес копіювання з диска на диск був запланований вводу / виводу з нижчим пріоритетом, ніж звичайні процеси.
Стівен у понеділок

3
Це класичне проблемне питання XY . Натомість слід запитати про те, чому ваш робочий стіл не відповідає, коли ви копіюєте файли на USB-пристрій.
Майкл Хемптон

4
Сьогодні Linux насправді має смішно великі буфери вводу / виводу. Розміри оперативної пам’яті зростали швидше, ніж масові швидкості зберігання. Може бути, ви могли виконати копію, використовуючи dd (1) та синхронізувати, щоб вона насправді періодично синхронізувалась, а не була завантажена? А у трубного переглядача (pv) є можливість обмеження швидкості. Щось подібне cat file | pv -L 3k > outfile. Але це не те саме, що використовувати cp (1).
ptman

@MichaelHampton, на форумі ArchLinux є кілька невирішених тем з цього питання, тож я подумав, що я спробую впоратися з цим по-іншому, просто щоб змусити його працювати.
антонон

@antonone Але Unix.SE не є форумами ArchLinux. Хтось тут може мати рішення.
Ізката

Відповіді:


23

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

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

-q видаляє суворішу звітність про хід.

-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

обмеження пропускної здатності вводу / виводу; Кбайт в секунду

Отже, команда actuall, яка також показує прогрес, виглядала б так:

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

Це звучить як приємна ідея для копіювання старих дисків, які я не хочу бити.
jeremyjjbrown

Не працює для читання з /dev/zeroабо/dev/random
cdosborn

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

Сторінка: навіть якщо на сторінці "man" можна сказати, що ви можете використовувати літери для одиниць, наприклад 20m, вона підтримується не на всіх платформах, тому краще дотримуватися позначення KBytes.
Hubert Grzeskowiak

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

13

Я б припустив, що ви намагаєтеся не порушувати іншу діяльність. Останні версії Linux включають, ioniceщо дозволяє контролювати планування вводу-виводу.

Окрім дозволу на різні пріоритети, є додаткова можливість обмежити IO часом, коли диск в режимі очікування. Команда man ioniceвідобразить документацію.

Спробуйте скопіювати файл за допомогою команди типу:

ionice -c 3 cp largefile /new/directory

Якщо два каталоги знаходяться на одному пристрої, можливо, ви знайдете, що файл зв'язує те, що ви хочете. Якщо ви копіюєте для резервного копіювання, не використовуйте цю опцію. lnнадзвичайно швидко, оскільки сам файл не копіюється. Спробуйте:

ln largefile /new/directory

Або якщо ви просто хочете отримати доступ до нього з каталогу на іншому пристрої, спробуйте:

ln -s largefile /new/directory

чи ionice добре працює в Linux? я читаю це просто "емуляція" роботи, і немає реальної різниці? +1 для посилань
Нік

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

з файлом 400MB, який я копіював з одного HD на SSD, початкові 10-х він працював ідеально, потім раптом я побачив, що я навантажую IO, і мені довелося чекати, як 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,5 Мбіт).

Але я думаю, що це не так вже й практично для одного файлу. У вашому випадку ви можете просто перейти до 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]: Кредит, де це належить: щойно помітив, що Птман побив мене до цього приблизно п’ять годин у коментарях.

Однозначно, ви можете налаштувати $ 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.