Spowolnij kopiowanie dysku / dysku


28

Czy istnieje metoda spowolnienia procesu kopiowania w systemie Linux?

Mam duży plik, powiedzmy 10 GB, i chciałbym go skopiować do innego katalogu, ale nie chcę go kopiować z pełną prędkością. Powiedzmy, że chciałbym go skopiować z prędkością 1 Mb / s, a nie szybciej. Chciałbym użyć standardowej cpkomendy Linux .

czy to możliwe? (Jeśli tak, jak?)

Edycja : dodam więc więcej kontekstu do tego, co próbuję osiągnąć.

Mam problem z systemem ArchLinux podczas kopiowania dużych plików przez USB (na pendrive, dysk USB itp.). Po zapełnieniu pamięci podręcznej bufora USB mój system przestaje odpowiadać (nawet mysz się zatrzymuje; porusza się sporadycznie). Operacja kopiowania jest nadal w toku, ale zajmuje 100% zasobów skrzynki. Po zakończeniu operacji kopiowania wszystko wraca do normy - wszystko znów doskonale reaguje.

Może to błąd sprzętowy, nie wiem, ale wiem, że mam dwa komputery z tym problemem (oba są na ArchLinux, jeden to komputer stacjonarny, drugi to laptop).

Najłatwiejszym i najszybszym „rozwiązaniem” tego problemu (zgadzam się, że to nie jest „prawdziwe” rozwiązanie, tylko brzydki „hack”) byłoby zapobieganie zapełnianiu się bufora przez kopiowanie pliku ze średnią prędkością zapisu na dysku USB, dla mi to by wystarczyło.


7
Jeśli chcesz ograniczyć szybkość kopiowania z dysku na dysk, starając się być „miły” dla innych procesów związanych z operacjami we / wy w systemie, prawdopodobnie lepiej jest wykorzystać zdolność jądra do dostrojenia harmonogramu operacji we / wy zamiast. W szczególności ionicemożna go użyć, aby zapewnić, że proces kopiowania z dysku na dysk ma zaplanowane operacje we / wy o niższym priorytecie niż zwykłe procesy.
Steven poniedziałek

3
To klasyczne pytanie problemowe XY . Zamiast tego powinieneś zapytać, dlaczego pulpit przestaje reagować, gdy kopiujesz pliki na urządzenie USB.
Michael Hampton

4
Linux faktycznie ma absurdalnie duże bufory we / wy. Rozmiary pamięci RAM wzrosły szybciej niż prędkości pamięci masowej. Może mógłbyś wykonać kopię za pomocą dd (1) i zsynchronizować, aby faktycznie była okresowo synchronizowana zamiast buforowana? Przeglądarka potoków (pv) ma opcję ograniczania prędkości. Coś jak cat file | pv -L 3k > outfile. Jednak żadne z nich nie jest tym samym, co użycie cp (1).
ptman

@MichaelHampton, na forum ArchLinux jest kilka nierozwiązanych tematów na ten temat, więc pomyślałem, że spróbuję sobie z tym poradzić w inny sposób, aby to zadziałało.
antonone

@antonone Ale Unix.SE nie jest forami ArchLinux. Ktoś tutaj może mieć rozwiązanie.
Izkata

Odpowiedzi:


23

Możesz dławić rurę za pomocą pv -qL(lub cstream -tzapewnia podobną funkcjonalność)

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

-q usuwa raportowanie postępów stderr.

-LGranica jest w bajtach.

Więcej informacji na temat --rate-limit/-Lflagi z 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.

Ta odpowiedź pierwotnie wskazywała, throttleale ten projekt nie jest już dostępny, więc wymknął się z niektórych systemów pakietów.


Jeśli cpnie można go spowolnić, to domyślnie jedyną opcją jest użycie niestandardowego polecenia.
antonone

1
Brzmi zbyt skomplikowanie w porównaniu zrsync
LinuxSecurityFreak

wygląda na bardziej skomplikowane, ale bardziej użyteczne dla mnie. Trzeba przetestować mechanizm blokowania plików i spowolnić kopiowanie do niektórych bajtów / s, co wydaje się niemożliwe w przypadku rsync. Spróbuję i 'cat' plik przez rurkę przepustnicy
cljk

przykro mi to mówić, ale projekt jest martwy bugs.debian.org/cgi-bin/bugreport.cgi?bug=426891
cljk

1
@cljk zaktualizowano do pv. dzięki.
Matt

23

Zamiast tego cp -a /foo /barmożesz także używać rsynci ograniczać przepustowość w miarę potrzeb.

Z rsyncpodręcznika:

--bwlimit=KBPS

ograniczenie przepustowości we / wy; KBytes na sekundę

Tak więc polecenie aktuall, również pokazujące postęp, wyglądałoby następująco:

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

To brzmi jak niezły pomysł na kopiowanie starych dysków, których nie chcę pobić.
jeremyjjbrown

Nie działa w przypadku czytania z /dev/zerolub/dev/random
cdosborn

rsync -a --bwlimit=1500 /source /destinationdoskonale kopiuje gigantyczne foldery z prędkością 1,5 MB / s (co stanowi dobry kompromis między unikaniem spowolnienia serwera i nie zabieraniem zbyt wiele czasu)
lucaferrario

Sidenote: nawet jeśli strona podręcznika może powiedzieć, że możesz używać liter dla jednostek, np. 20mNie jest obsługiwana na wszystkich platformach, więc lepiej trzymaj się notacji KBytes.
Hubert Grzeskowiak

uratował mi dzień! cgroup cgexec -g ... cp /in /outcały czas nie działał (z terminalu pracował czasami, ze skryptu nigdy) i nie mam pojęcia, dlaczego ...
Aquarius Power

13

Zakładam, że próbujesz nie zakłócać innej działalności. Najnowsze wersje systemu Linux obejmująionice które pozwalają kontrolować harmonogram IO.

Oprócz zezwalania na różne priorytety, istnieje dodatkowa opcja ograniczenia IO do czasów, gdy dysk jest w przeciwnym razie bezczynny. Komendaman ionice wyświetli dokumentację.

Spróbuj skopiować plik za pomocą polecenia takiego jak:

ionice -c 3 cp largefile /new/directory

Jeśli dwa katalogi znajdują się na tym samym urządzeniu, może się okazać, że połączenie pliku spowoduje wykonanie żądanej czynności. Jeśli kopiujesz w celu wykonania kopii zapasowej, nie używaj tej opcji. lnjest bardzo szybki, ponieważ sam plik nie jest kopiowany. Próbować:

ln largefile /new/directory

Lub jeśli chcesz uzyskać do niego dostęp z katalogu na innym urządzeniu, spróbuj:

ln -s largefile /new/directory

czy ionice działa dobrze w systemie Linux? czytam to po prostu „emuluję” pracę i nie ma prawdziwej różnicy? +1 dla linków
Nick

1
@Nick Kiedy go użyłem, zachowywał się zgodnie z oczekiwaniami. Proces, do którego zastosowałem jonice, znacznie zwolnił, a inne procesy, które wymagały wejścia / wyjścia, były w stanie wykonać zgodnie z oczekiwaniami. Przy umiarkowanym obciążeniu I / O z innych procesów byłem w stanie skutecznie zawiesić wysoki proces I / O, stosując maksymalną „pewność” zgodnie z oczekiwaniami. Gdy nie było konkurencyjnych We / Wy, proces jonizacji przeprowadzany był normalnie.
BillThor,

z plikiem 400 MB, który kopiowałem z jednego dysku HD na dysk SSD, początkowe 10s działało idealnie, a potem nagle zobaczyłem, że mam duże obciążenie IO i musiałem czekać na około 1 minutę zamrożonej maszyny: /. Mam ten sam problem z cgroup piszę przepustnicę tam, gdzie czasami działa, a inne w ogóle nie działają.
Aquarius Power

7

Jeśli ionicerozwiązanie nie jest wystarczające (dlaczego) i naprawdę chcesz ograniczyć We / Wy do wartości bezwzględnej, istnieje kilka możliwości:

  1. prawdopodobnie najłatwiejszy: ssh. Ma wbudowany limit przepustowości. Użyłbyś np. tar(Zamiast cp) lub scp(jeśli to wystarczy; nie wiem, jak obsługuje dowiązania symboliczne i dowiązania twarde) lub rsync. Te polecenia mogą przesyłać dane przez potok ssh. W przypadku tarpisania do /dev/stdout(lub -) i podłączania go do sshklienta, który wykonuje inny tarpo „zdalnej” stronie.

  2. elegancki, ale nie w jądrze wanilii (AFAIK): Cel urządzenia mapującego ioband. Działa to oczywiście tylko wtedy, gdy można zamontować wolumin źródłowy lub docelowy.

  3. trochę samodzielnej zabawy: grep "^write_bytes: " /proc/$PID/iodaje ilość danych zapisanych przez proces. Możesz napisać skrypt, który zaczyna się cpw tle, śpi na przykład przez 1/10 sekundy, zatrzymuje cpproces w tle ( kill -STOP $PID), sprawdza ilość, która została napisana (i czyta? O tej samej wartości w tym przypadku), oblicza, jak długo cpmusi się zatrzymać, aby obniżyć średnią szybkość transferu do zamierzonej wartości, śpi przez ten czas, budzi się cp( kill -CONT $PID) i tak dalej.


Tak, zwykle używam lftp, aby połączyć się z hostem lokalnym za pośrednictwem scp i stamtąd ograniczyć bandwich.
antonone

5

Twój problem prawdopodobnie nie dotyczy komputera, prawdopodobnie jest w porządku. Ale ta warstwa przejściowa pamięci flash USB ma własny procesor, który musi odwzorować wszystkie twoje zapisy, aby zrekompensować coś, co może być wadliwym układem flash w 90%, kto wie? Zalewacie go, potem zalewacie bufory, zalewacie cały autobus, potem utknęliście, stary - w końcu tam są wszystkie rzeczy. Może to zabrzmieć sprzecznie z intuicją, ale tak naprawdę potrzebujesz blokowania I / O - musisz pozwolić FTL ustawić tempo, a następnie po prostu nadążyć.

(O włamywaniu mikrokontrolerów FTL: http://www.bunniestudios.com/blog/?p=3554 )

Wszystkie powyższe odpowiedzi powinny działać, więc jest to bardziej „ja też!” niż cokolwiek innego: byłem tam całkowicie, stary. Rozwiązałem swoje własne problemy z rsync - bwlimit arg (2,5 Mb / s wydawało się najlepszym miejscem na pojedynczy, bezbłędny przebieg - cokolwiek więcej i skończyłyby mnie błędy ochrony przed zapisem). rsync był szczególnie przydatny do moich celów, ponieważ pracowałem z całymi systemami plików - więc było wiele plików - a po prostu uruchomienie rsync po raz drugi naprawiłoby wszystkie problemy pierwszego uruchomienia (co było konieczne, gdy stałem się niecierpliwy i spróbowałem do rampy przekraczającej 2,5 Mb / s).

Mimo to wydaje mi się, że nie jest to tak praktyczne dla pojedynczego pliku. W twoim przypadku możesz po prostu potokować do dd i ustawić surowe zapisywanie - możesz obsługiwać dowolne dane wejściowe w ten sposób, ale tylko jeden plik docelowy na raz (choć ten pojedynczy plik może oczywiście być całym urządzeniem blokowym).

## 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  

Może się okazać, że netcat jest trochę szybszy niż ssh do transportu danych, jeśli spróbujesz. Zresztą inne pomysły zostały już wykorzystane, więc dlaczego nie?

[EDYCJA]: Zauważyłem wzmianki o lftp, scp i ssh w drugim poście i pomyślałem, że mówimy o zdalnej kopii. Lokalne jest o wiele łatwiejsze:

% 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]: Kredyt tam, gdzie jest to należne: właśnie zauważyłem, że ptman pobił mnie do tego przez około pięć godzin w komentarzach.

Zdecydowanie możesz dostroić $ bs do wydajności tutaj za pomocą mnożnika - ale niektóre systemy plików mogą wymagać, aby była wielokrotnością wielkości sektora docelowego fs, więc miej to na uwadze.


Na mojej maszynie --getiooptnie ma flagi--getoptio
Michael Mior

2

Problem polega na tym, że kopia wypełnia twoją pamięć blokami „w locie”, „wypychając” użyteczne dane. Znany (i bardzo trudny do naprawienia) błąd w obsłudze jądra Linuksa we / wy na wolnych urządzeniach (w tym przypadku USB).

Być może możesz spróbować spakować kopiowanie, np. Za pomocą skryptu takiego jak poniższy (szkic weryfikacji koncepcji, całkowicie niesprawdzony!):

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

dostosowanie seeki skipprzez countkażdą rundę. Trzeba dostroić, countaby nie zapełniło (zbyt dużo) pamięci i 5pozwolić jej się wyczerpać.


2

Zmniejsz limit brudnej strony. Domyślny limit jest szalony.

Utwórz plik /etc/sysctl.d/99-sysctl.conf za pomocą:

vm.dirty_background_ratio = 3
vm.dirty_ratio = 10

Następnie uruchom sysctl -p lub uruchom ponownie.

Dzieje się tak, że dane są odczytywane szybciej, niż można je zapisać na dysku docelowym. Kiedy linux kopiuje pliki, odczytuje je do pamięci RAM, a następnie oznacza strony jako brudne, aby zapisać je w miejscu docelowym. Brudnych stron nie można zamienić. Więc jeśli dysk źródłowy jest szybszy niż dysk docelowy i kopiujesz więcej danych niż masz wolną pamięć RAM, operacja kopiowania pochłonie całą dostępną pamięć RAM (lub przynajmniej limit limitu brudnych stron, który może być większy niż dostępnej pamięci RAM) i powodują głód, ponieważ brudne strony nie mogą zostać zamienione, a czyste strony są używane i oznaczane jako brudne po zwolnieniu.

Zauważ, że jego nie rozwiąże całkowicie problemu ... to, czego naprawdę potrzebuje Linux, to jakiś sposób na arbitrażowe tworzenie brudnych stron, więc duży transfer, który ma miejsce, nie pochłania całej dostępnej pamięci RAM / wszystkich dozwolonych brudnych stron.


0

Ten problem nie ma nic wspólnego z błędami lub błędami w sprzęcie lub oprogramowaniu, to tylko twoje jądro stara się być dla ciebie miłe i daje ci monit z powrotem i kopiuje w tle (używa pamięci podręcznej w jądrze: więcej pamięci RAM, więcej pamięci podręcznej, ale możesz to ograniczyć pisząc gdzieś w / proc - choć nie polecam tego). Dyski flash są zbyt wolne i podczas gdy jądro je zapisuje, innych operacji IO nie można wykonać wystarczająco szybko. ionicewspomniane kilka razy w innych odpowiedziach jest w porządku. Ale czy próbowałeś właśnie zamontować dysk, -o syncaby uniknąć buforowania systemu operacyjnego? To chyba najprostsze rozwiązanie.


Po włączeniu opcji -o synchronizacja mój Internet jest szybszy niż prędkość zapisu na tym dysku USB. Nie rozumiem, dlaczego jądro nie śledzi, jak szybko strony pamięci podręcznej są opróżniane i na tej podstawie planuje przyszłe opróżnianie. To tak, jakby zawsze biegła z pełną prędkością, nawet jeśli ten słaby dysk nie nadąża za prędkością. Ale to chyba temat na kolejne pytanie.
antonone
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.