Rendi la copia del disco / disco più lenta


28

Esiste un metodo per rallentare il processo di copia su Linux?

Ho un file di grandi dimensioni, diciamo 10 GB, e vorrei copiarlo in un'altra directory, ma non voglio copiarlo alla massima velocità. Diciamo che vorrei copiarlo con la velocità di 1 mb / s, non più veloce. Vorrei usare un cpcomando Linux standard .

È possibile? (Se sì, come?)

Modifica : quindi, aggiungerò più contesto a ciò che sto cercando di ottenere.

Ho un problema con il sistema ArchLinux durante la copia di file di grandi dimensioni tramite USB (su un pendrive, un disco USB, ecc.). Dopo aver riempito la cache del buffer USB, il mio sistema smette di rispondere (anche il mouse si ferma; si sposta solo sporadicamente). L'operazione di copia è ancora in corso, ma richiede il 100% delle risorse della scatola. Al termine dell'operazione di copia, tutto torna alla normalità, tutto risponde perfettamente.

Forse è un errore hardware, non lo so, ma so di avere due macchine con questo problema (entrambi sono su ArchLinux, uno è un desktop box, il secondo è un laptop).

La "soluzione" più semplice e veloce a questo (sono d'accordo che non è la soluzione "reale", solo un brutto "hack") sarebbe quella di impedire che questo buffer si riempia copiando il file con una velocità di scrittura media dell'unità USB, per questo sarebbe abbastanza.


7
Se stai cercando di limitare la velocità di copia da disco a disco nel tentativo di essere "gentile" con altri processi associati a I / O nel sistema, probabilmente stai meglio approfittando della capacità del kernel di ottimizzare la programmazione I / O anziché. In particolare, ionicepuò essere utilizzato per garantire che il processo di copia da disco a disco sia pianificato l'I / O con una priorità inferiore rispetto ai processi normali.
Steven lunedì

3
Questa è una classica domanda del problema XY . Dovresti invece chiederti perché il tuo desktop non risponde quando copi i file su un dispositivo USB.
Michael Hampton,

4
Oggigiorno Linux ha buffer I / O ridicolmente grandi. Le dimensioni della RAM sono cresciute più velocemente della velocità di archiviazione di massa. Forse potresti eseguire la copia usando dd (1) e la sincronizzazione in modo che venga effettivamente sincronizzata periodicamente anziché essere bufferizzata? E pipe viewer (pv) ha un'opzione di limitazione della velocità. Qualcosa del genere cat file | pv -L 3k > outfile. Né sono gli stessi dell'uso di cp (1), comunque.
ptman,

@MichaelHampton, ci sono diversi argomenti irrisolti su questo problema nel forum di ArchLinux, quindi ho pensato che avrei provato a affrontarlo in un modo diverso, solo per farlo funzionare.
antonone

@antonone Ma Unix.SE non è il forum di ArchLinux. Qualcuno qui potrebbe avere una soluzione.
Izkata

Risposte:


23

Puoi strozzare un tubo con pv -qL(o cstream -tfornisce funzionalità simili)

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

-q rimuove i rapporti sui progressi di stderr.

Il -Llimite è in byte.

Maggiori informazioni sulla --rate-limit/-Lbandiera dal 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.

Questa risposta originariamente indicava throttlema quel progetto non è più disponibile, quindi è scivolato fuori da alcuni sistemi di pacchetti.


Se cpnon è possibile rallentare, l'utilizzo di un comando personalizzato è l'unica opzione che immagino.
Antonio

1
Sembra troppo complicato rispetto arsync
LinuxSecurityFreak il

sembra più complicato ma più utilizzabile per me. È necessario testare un meccanismo di blocco dei file e rallentare la copia in alcuni byte / s che non sembra possibile con rsync. Ci provo e 'cat' un file attraverso il tubo dell'acceleratore
cljk

triste da dire ma il progetto è morto bugs.debian.org/cgi-bin/bugreport.cgi?bug=426891
cljk

1
@cljk aggiornato a pv. Grazie.
Matt

23

Invece di cp -a /foo /barte puoi anche usare rsynce limitare la larghezza di banda di cui hai bisogno.

Dal rsyncmanuale di:

--bwlimit=KBPS

limitare la larghezza di banda I / O; KByte al secondo

Quindi, il comando actuall, mostrando anche l'avanzamento, sarebbe simile al seguente:

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

Sembra una bella idea per copiare vecchie unità che non voglio battere.
jeremyjjbrown,

Non funziona per leggere da /dev/zero o/dev/random
cdosborn il

rsync -a --bwlimit=1500 /source /destinationfunziona perfettamente per copiare cartelle giganti a una velocità di 1,5 MB / s (che è un buon compromesso tra evitare qualsiasi rallentamento del server e non
impiegare

Sidenote: anche se la pagina man potrebbe dire che puoi usare lettere per unità, ad es 20m , non è supportata su tutte le piattaforme, quindi è meglio attenersi alla notazione KBytes.
Hubert Grzeskowiak,

mi ha salvato la giornata! cgroup cgexec -g ... cp /in /outnon funzionava sempre (dal terminale funzionava qualche volta, dalla sceneggiatura mai) e non ho idea del perché ...
Aquarius Power

13

Suppongo che stai cercando di non interrompere altre attività. Le versioni recenti di Linux includono ioniceciò che consente di controllare la pianificazione di IO.

Oltre a consentire varie priorità, esiste un'opzione aggiuntiva per limitare IO a momenti in cui il disco è inattivo. Il comando man ionicevisualizzerà la documentazione.

Prova a copiare il file usando un comando come:

ionice -c 3 cp largefile /new/directory

Se le due directory si trovano sullo stesso dispositivo, è possibile che il collegamento del file faccia ciò che si desidera. Se si esegue la copia a scopo di backup, non utilizzare questa opzione. lnè estremamente veloce in quanto il file stesso non viene copiato. Provare:

ln largefile /new/directory

Oppure se vuoi semplicemente accedervi da una directory su un altro dispositivo prova:

ln -s largefile /new/directory

ionice funziona bene in Linux? l'ho letto solo "emulare" il lavoro e non c'è vera differenza? +1 per i collegamenti
Nick,

1
@Nick Quando l'ho usato, si è comportato come previsto. Il processo a cui ho applicato la ionice è rallentato in modo significativo, mentre gli altri processi che necessitavano di I / O sono stati in grado di funzionare come previsto. Con un carico I / O moderato da altri processi, sono stato in grado di sospendere efficacemente un processo I / O elevato applicando la massima "gentilezza" come previsto. Una volta che non esistevano I / O concorrenti, il processo ionizzato veniva eseguito normalmente.
BillThor il

con il file da 400 MB stavo copiando da un HD a un SSD, i primi 10s funzionavano perfettamente, poi all'improvviso vidi un elevato carico di I / O e dovetti aspettare come 1 minuto di macchina congelata: /. Ho lo stesso problema con cgroup write io throttle dove a volte funziona e altri non funzionerà affatto.
Aquarius Power il

7

Se la ionicesoluzione non è sufficiente (perché) e vuoi davvero limitare l'I / O a un valore assoluto, ci sono diverse possibilità:

  1. la probabilmente più facile: ssh. Ha un limite di larghezza di banda integrato. Utilizzeresti ad esempio tar(invece di cp) o scp(se è abbastanza buono; non so come gestisca i collegamenti simbolici e quelli fissi) o rsync. Questi comandi possono reindirizzare i loro dati ssh. Nel caso in cui tartu scriva a /dev/stdout(o -) e lo installi nelssh client che ne esegue un altro tarsul lato "remoto".

  2. elegante ma non nel kernel vanilla (AFAIK): il target del mapper del dispositivo ioband. Questo, ovviamente, funziona solo se è possibile smontare il volume di origine o di destinazione.

  3. un po 'di divertimento auto-scritto: grep "^write_bytes: " /proc/$PID/ioti dà la quantità di dati che un processo ha scritto. Potresti scrivere uno script che inizia cpin background, dorme per esempio 1/10 di secondo, interrompe il cpprocesso in background ( kill -STOP $PID), controlla la quantità che è stata scritta (e leggi sullo stesso valore in questo caso), calcola per quanto tempo cpdeve mettere in pausa per portare la velocità di trasferimento media al valore desiderato, dormire per quel tempo, sveglia cp( kill -CONT $PID) e così via.


Sì, normalmente sto solo usando lftp per connettermi a localhost tramite scp, e limitare il bandwich da lì.
antonone

5

Il tuo problema probabilmente non è con il tuo computer, di per sé, probabilmente va bene. Ma quel livello di transizione flash USB ha un proprio processore che deve mappare tutte le tue scritture per compensare quello che potrebbe essere un chip flash difettoso al 90%, chi lo sa? Lo allaghi, poi allaghi i tuoi buffer, quindi allaghi l'intero bus, poi sei bloccato, amico - dopo tutto, è lì che si trova tutta la tua roba. Può sembrare controintuitivo, ma ciò di cui hai davvero bisogno è bloccare l'I / O: devi lasciare che FTL stabilisca il ritmo e poi tenere il passo.

(Per hackerare i microcontrollori FTL: http://www.bunniestudios.com/blog/?p=3554 )

Tutte le risposte sopra dovrebbero funzionare, quindi questo è più un "anch'io!" di ogni altra cosa: ci sono stato totalmente, amico. Ho risolto i miei problemi con rsync's --bwlimit arg di (2,5 Mb sembrava essere il punto debole per una singola corsa senza errori - niente di più e finirei con errori di protezione da scrittura). rsync era particolarmente adatto al mio scopo perché stavo lavorando con interi filesystem - quindi c'erano molti file - e semplicemente eseguire rsync una seconda volta avrebbe risolto tutti i problemi della prima esecuzione (che era necessario quando sarei diventato impaziente e avrei provato superare 2,5 mbs).

Tuttavia, suppongo che non sia altrettanto pratico per un singolo file. Nel tuo caso potresti semplicemente pipe per dd impostato su raw-write - puoi gestire qualsiasi input in quel modo, ma solo un file di destinazione alla volta (anche se quel singolo file potrebbe essere un intero dispositivo a blocchi, ovviamente).

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

Potresti trovare netcat un po 'più veloce di ssh per il trasporto dei dati se ci dai una possibilità. Ad ogni modo, le altre idee erano già state prese, quindi perché no?

[EDIT]: ho notato le menzioni di lftp, scp e ssh nell'altro post e ho pensato che stessimo parlando di una copia remota. Il locale è molto più semplice:

% 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]: Ringraziamenti dove è dovuto: ho appena notato che ptman mi ha battuto su questo per circa cinque ore nei commenti.

Sicuramente potresti mettere a punto $ bs per le prestazioni qui con un moltiplicatore, ma alcuni filesystem potrebbero richiedere che sia un multiplo della dimensione settoriale del fs di destinazione, quindi tienilo a mente.


Sulla mia macchina, la bandiera --getiooptnon è--getoptio
Michael Mior

2

Il problema è che la copia sta riempiendo la tua memoria di blocchi "in volo", che ammucchiano dati "utili". Un bug noto (e molto difficile da risolvere) nella gestione del kernel Linux dell'I / O per rallentare i dispositivi (USB in questo caso).

Forse puoi provare a distribuire la copia, ad esempio con uno script come il seguente (schizzo di prova, totalmente non testato!):

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

aggiustando seeke skipad countogni giro. È necessario sintonizzarsi in countmodo che non riempia (troppa) memoria e 5consentirne il drenaggio.


2

Abbassa il limite di pagine sporche. Il limite predefinito è folle.

Crea /etc/sysctl.d/99-sysctl.conf con:

vm.dirty_background_ratio = 3
vm.dirty_ratio = 10

Quindi eseguire sysctl -p o riavviare.

Quello che sta succedendo è che i dati vengono letti più velocemente di quanto possano essere scritti sul disco di destinazione. Quando Linux copia i file, ciò che fa è leggerli nella RAM, quindi contrassegnare le pagine come sporche per la scrittura nella destinazione. Le pagine sporche non possono essere scambiate. Quindi, se il disco di origine è più veloce del disco di destinazione e stai copiando più dati di quanti ne hai RAM libera, l'operazione di copia consumerà tutta la RAM disponibile (o almeno qualunque sia il limite di pagina sporca, che potrebbe essere superiore al RAM disponibile) e causa la fame poiché le pagine sporche non possono essere scambiate e le pagine pulite vengono utilizzate e contrassegnate come sporche quando vengono liberate.

Nota che il suo non risolverà completamente il problema ... ciò di cui Linux ha davvero bisogno è un modo per arbitrare la creazione di pagine sporche, quindi un grande trasferimento in corso non consuma tutta la RAM disponibile / tutte le pagine sporche consentite.


0

Questo problema non ha nulla a che fare con errori o guasti nell'hardware o nel software, è solo il tuo kernel che cerca di essere gentile con te e restituire il tuo prompt e copiarlo in background (usa una cache nel kernel: più RAM, più cache, ma puoi limitarlo scrivendo da qualche parte in / proc - non consigliato però). Le unità flash sono troppo lente e mentre il kernel scrive su di esso, altre operazioni di I / O non possono essere eseguite abbastanza velocemente. ionicemenzionato più volte in altre risposte è ok. Ma hai provato a montare l'unità con -o syncper evitare il buffering del sistema operativo? È probabilmente la soluzione più semplice là fuori.


Dopo aver abilitato -o sync, Internet è più veloce della velocità di scrittura su questa unità USB. Quello che non capisco è il motivo per cui il kernel non tiene traccia della velocità con cui le pagine della cache vengono scaricate e pianifica le operazioni di scaricamento future in base a ciò. È come se andasse sempre a tutta velocità, anche se questa scarsa unità non riesce a tenere il passo con la velocità. Ma questo è un argomento per un'altra domanda, immagino.
Antonio
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.