Rendre le disque / la copie de disque plus lent


28

Existe-t-il une méthode pour ralentir le processus de copie sous Linux?

J'ai un gros fichier, disons 10 Go, et j'aimerais le copier dans un autre répertoire, mais je ne veux pas le copier à pleine vitesse. Disons que j'aimerais le copier à la vitesse de 1 Mo / s, pas plus vite. Je voudrais utiliser une cpcommande Linux standard .

Est-ce possible? (Si oui, comment?)

Edit : donc, je vais ajouter plus de contexte à ce que j'essaie de réaliser.

J'ai un problème sur le système ArchLinux lors de la copie de gros fichiers via USB (sur une clé USB, un disque USB, etc.). Après avoir rempli le cache du tampon USB, mon système cesse de répondre (même la souris s'arrête; elle ne se déplace que sporadiquement). L'opération de copie est toujours en cours, mais elle prend 100% des ressources de la boîte. Lorsque l'opération de copie est terminée, tout revient à la normale - tout est à nouveau parfaitement réactif.

C'est peut-être une erreur matérielle, je ne sais pas, mais je sais que j'ai deux machines avec ce problème (les deux sont sur ArchLinux, l'une est une boîte de bureau, la seconde est un ordinateur portable).

La "solution" la plus simple et la plus rapide à cela (je conviens que ce n'est pas la "vraie" solution, juste un "hack" moche) serait d'empêcher ce tampon de se remplir en copiant le fichier avec une vitesse d'écriture moyenne du lecteur USB, par exemple. moi ce serait suffisant.


7
Si vous cherchez à limiter la vitesse de copie disque à disque dans un effort pour être "agréable" avec les autres processus liés aux E / S dans le système, vous feriez probablement mieux de profiter de la capacité du noyau à régler la planification des E / S. au lieu. Plus précisément, il ionicepeut être utilisé pour garantir que votre processus de copie de disque à disque est une E / S planifiée avec une priorité inférieure à celle des processus ordinaires.
Steven lundi

3
Il s'agit d'une question de problème XY classique . Vous devriez plutôt demander pourquoi votre bureau ne répond plus lorsque vous copiez des fichiers sur un périphérique USB.
Michael Hampton

4
Linux a actuellement des tampons d'E / S ridiculement grands de nos jours. Les tailles de RAM ont augmenté plus rapidement que les vitesses de stockage de masse. Peut-être pourriez-vous effectuer la copie à l'aide de dd (1) et de la synchronisation afin qu'elle soit effectivement synchronisée périodiquement au lieu d'être mise en mémoire tampon? Et le visualiseur de tuyaux (pv) a une option de limitation de débit. Quelque chose comme cat file | pv -L 3k > outfile. Cependant, cela ne revient pas non plus à utiliser cp (1).
ptman

@MichaelHampton, il y a plusieurs sujets non résolus sur ce problème sur le forum d'ArchLinux, alors j'ai pensé que j'essaierais de le gérer d'une manière différente, juste pour le faire fonctionner.
antonone

@antonone Mais Unix.SE n'est pas les forums d'ArchLinux. Quelqu'un ici pourrait avoir une solution.
Izkata

Réponses:


23

Vous pouvez étrangler un tuyau avec pv -qL(ou cstream -toffre des fonctionnalités similaires)

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

-q supprime les rapports de progression de stderr.

La -Llimite est en octets.

En savoir plus sur le --rate-limit/-Ldrapeau de la 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.

Cette réponse a été indiquée à l'origine, throttlemais ce projet n'est plus disponible et a donc été supprimé de certains systèmes de packages.


Si cpcela ne peut pas être ralenti, l'utilisation d'une commande personnalisée est la seule option, je suppose.
antonone


semble plus compliqué mais plus utilisable pour moi. Besoin de tester un mécanisme de verrouillage de fichier et de ralentir la copie vers certains octets / s, ce qui ne semble pas possible avec rsync.
Je vais

triste à dire mais le projet est mort bugs.debian.org/cgi-bin/bugreport.cgi?bug=426891
cljk

1
@cljk mis à jour vers pv. Merci.
Matt

23

Au lieu de cela, cp -a /foo /barvous pouvez également utiliser rsyncet limiter la bande passante selon vos besoins.

D'après le rsyncmanuel de:

--bwlimit=KBPS

limiter la bande passante d'E / S; Koctets par seconde

Ainsi, la commande actuall, montrant également la progression, ressemblerait à ceci:

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

Cela ressemble à une bonne idée pour copier de vieux disques que je ne veux pas battre.
jeremyjjbrown

Ne fonctionne pas pour la lecture de /dev/zeroou/dev/random
cdosborn

rsync -a --bwlimit=1500 /source /destinationfonctionne parfaitement pour copier des dossiers géants à une vitesse de 1,5 Mo / s (ce qui est un bon compromis entre éviter tout ralentissement du serveur et ne pas prendre trop de temps)
lucaferrario

Sidenote: même si la page de manuel peut dire que vous pouvez utiliser des lettres pour les unités, par exemple 20m, elle n'est pas prise en charge sur toutes les plates-formes, il vaut donc mieux s'en tenir à la notation KBytes.
Hubert Grzeskowiak

sauvé ma journée! cgroup cgexec -g ... cp /in /outne fonctionnait pas tout le temps (depuis le terminal a parfois fonctionné, jamais depuis le script) et je ne sais pas pourquoi ...
Aquarius Power

13

Je suppose que vous essayez de ne pas perturber d'autres activités. Les versions récentes de Linux incluent ionicece qui vous permet de contrôler la planification des E / S.

En plus d'autoriser diverses priorités, il existe une option supplémentaire pour limiter les E / S aux moments où le disque est autrement inactif. La commande man ioniceaffichera la documentation.

Essayez de copier le fichier à l'aide d'une commande comme:

ionice -c 3 cp largefile /new/directory

Si les deux répertoires sont sur le même appareil, vous pouvez trouver que la liaison du fichier fait ce que vous voulez. Si vous copiez à des fins de sauvegarde, n'utilisez pas cette option. lnest extrêmement rapide car le fichier lui-même n'est pas copié. Essayer:

ln largefile /new/directory

Ou si vous souhaitez simplement y accéder à partir d'un répertoire sur un autre appareil, essayez:

ln -s largefile /new/directory

est ionice fonctionne bien sous linux? je le lis juste "imite" le travail et il n'y a pas vraiment de différence? +1 pour les liens
Nick

1
@ Nick Quand je l'ai utilisé, il s'est comporté comme prévu. Le processus auquel j'ai appliqué l'ionice a considérablement ralenti, et les autres processus nécessitant des E / S ont pu fonctionner comme prévu. Avec une charge d'E / S modérée provenant d'autres processus, j'ai pu suspendre efficacement un processus d'E / S élevé en appliquant une «gentillesse» maximale comme prévu. Une fois qu'il n'y avait pas d'E / S concurrentes, le processus ionisé s'est déroulé normalement.
BillThor

avec le fichier de 400 Mo que je copiais d'un disque dur vers un SSD, les 10 premières ont fonctionné parfaitement, puis soudain j'ai vu une charge IO élevée et j'ai dû attendre comme une minute gelée par la machine: /. J'ai le même problème avec cgroup write io throttle où cela fonctionne parfois et d'autres il ne fonctionnera pas du tout.
Aquarius Power

7

Si la ionicesolution ne suffit pas (quoi qu'il en soit) et que vous souhaitez vraiment limiter les E / S à une valeur absolue, il existe plusieurs possibilités:

  1. le moyen le plus probablement: ssh. Il a une limite de bande passante intégrée. Vous utiliseriez par exemple tar(au lieu de cp) ou scp(si cela suffit, je ne sais pas comment il gère les liens symboliques et les liens durs) ou rsync. Ces commandes peuvent diriger leurs données ssh. Dans le cas où tarvous écrivez /dev/stdout(ou -) et canalisez cela dans le sshclient qui en exécute un autre tardu côté "distant".

  2. élégant mais pas dans le noyau vanilla (AFAIK): la cible du mappeur de périphériques ioband. Bien sûr, cela ne fonctionne que si vous pouvez démonter le volume source ou le volume cible.

  3. un plaisir auto-écrit: grep "^write_bytes: " /proc/$PID/iovous donne la quantité de données qu'un processus a écrites. Vous pouvez écrire un script qui démarre cpen arrière-plan, dort par exemple 1 / 10e de seconde, arrête le cpprocessus d' arrière-plan ( kill -STOP $PID), vérifie le montant qui a été écrit (et lu? Environ la même valeur dans ce cas), calcule la durée cpdoit faire une pause afin de ramener le taux de transfert moyen à la valeur souhaitée, s'endort pendant ce temps, se réveille cp( kill -CONT $PID), etc.


Oui, normalement j'utilise simplement lftp pour me connecter à localhost via scp, et limiter le bandwich à partir de là.
antonone

5

Votre problème n'est probablement pas avec votre ordinateur, en soi, c'est probablement bien. Mais cette couche de transition flash USB possède son propre processeur qui doit cartographier toutes vos écritures pour compenser ce qui pourrait être autant qu'une puce flash défectueuse à 90%, qui sait? Vous l'inondez puis vous inonder vos tampons, puis vous inonder tout le bus, puis vous êtes coincé, l'homme - après tout, c'est là que se trouvent toutes vos affaires. Cela peut sembler contre-intuitif, mais ce dont vous avez vraiment besoin est de bloquer les E / S - vous devez laisser le FTL donner le rythme, puis suivre le rythme.

(Sur le piratage des microcontrôleurs FTL: http://www.bunniestudios.com/blog/?p=3554 )

Toutes les réponses ci-dessus devraient fonctionner, donc c'est plus un "moi aussi!" qu'autre chose: j'y suis totalement allé, mec. J'ai résolu mes propres problèmes avec l' argument --bwlimit de rsync (2,5 Mo semblaient être le point idéal pour une seule exécution sans erreur - rien de plus et je me retrouverais avec des erreurs de protection en écriture). rsync était particulièrement adapté à mon objectif car je travaillais avec des systèmes de fichiers entiers - donc il y avait beaucoup de fichiers - et simplement exécuter rsync une deuxième fois résoudrait tous les problèmes de la première exécution (ce qui était nécessaire lorsque je devenais impatient et essayais rampe au-delà de 2,5 Mo).

Pourtant, je suppose que ce n'est pas aussi pratique pour un seul fichier. Dans votre cas, vous pouvez simplement rediriger vers dd défini sur raw-write - vous pouvez gérer n'importe quelle entrée de cette façon, mais un seul fichier cible à la fois (bien que ce fichier unique puisse être un périphérique de bloc entier, bien sûr).

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

Vous pouvez trouver que netcat est un peu plus rapide que ssh pour le transport de données si vous lui donnez une chance. Quoi qu'il en soit, les autres idées ont déjà été prises, alors pourquoi pas?

[EDIT]: J'ai remarqué les mentions de lftp, scp et ssh dans l'autre post et j'ai pensé que nous parlions d'une copie à distance. Les locaux sont beaucoup plus faciles:

% 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]: Le crédit est dû: je viens de remarquer que ptman m'a battu pendant environ cinq heures dans les commentaires.

Vous pouvez certainement régler $ bs pour les performances ici avec un multiplicateur - mais certains systèmes de fichiers peuvent exiger qu'il soit un multiple de la taille de secteur du fs cible, alors gardez cela à l'esprit.


Sur ma machine, le drapeau n'est --getiooptpas--getoptio
Michael Mior

2

Le problème est que la copie remplit votre mémoire de blocs "en vol", évincant les données "utiles". Un bogue connu (et très difficile à corriger) dans la gestion par le noyau Linux des E / S vers les périphériques lents (USB dans ce cas).

Vous pouvez peut-être essayer de répartir la copie, par exemple par un script comme celui-ci (croquis de validation de principe , totalement non testé!):

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

réglage seeket skippar countchaque tour. Besoin de régler countpour qu'il ne remplisse pas (trop) de mémoire et 5pour lui permettre de s'écouler.


2

Abaissez la limite de pages sales. La limite par défaut est folle.

Créez /etc/sysctl.d/99-sysctl.conf avec:

vm.dirty_background_ratio = 3
vm.dirty_ratio = 10

Exécutez ensuite sysctl -p ou redémarrez.

Ce qui se passe, c'est que les données sont lues plus rapidement qu'elles ne peuvent être écrites sur le disque de destination. Lorsque Linux copie des fichiers, il les lit dans la RAM, puis marque les pages comme sales pour l'écriture vers la destination. Les pages sales ne peuvent pas être échangées. Donc, si le disque source est plus rapide que le disque de destination et que vous copiez plus de données que vous n'avez de RAM libre, l'opération de copie consommera toute la RAM disponible (ou au moins quelle que soit la limite de pages sales, qui pourrait être supérieure à la RAM disponible) et provoquer la famine car les pages sales ne peuvent pas être échangées et les pages propres sont utilisées et marquées comme sales lorsqu'elles sont libérées.

Notez que cela ne résoudra pas complètement le problème ... ce dont Linux a vraiment besoin, c'est d'un moyen d'arbitrer la création de pages sales afin qu'un gros transfert en cours ne consomme pas toute la RAM disponible / toutes les pages sales autorisées.


0

Ce problème n'a rien à voir avec des erreurs ou des défauts de matériel ou de logiciel, c'est juste que votre noyau essaie d'être gentil avec vous et de renvoyer votre invite et de la copier en arrière-plan (il utilise un cache dans le noyau: plus de RAM, plus de cache, mais vous pouvez le limiter en écrivant quelque part dans / proc - pas recommandé cependant). Les lecteurs flash sont trop lents et pendant que le noyau écrit dessus, d'autres opérations d'E / S ne peuvent pas être effectuées assez rapidement. ionicementionné plusieurs fois dans d'autres réponses est ok. Mais avez-vous essayé de simplement monter le lecteur avec -o syncpour éviter la mise en mémoire tampon du système d'exploitation? C'est probablement la solution la plus simple qui existe.


Après avoir activé la synchronisation -o, mon Internet est plus rapide que la vitesse d'écriture sur ce lecteur USB. Ce que je ne comprends pas, c'est pourquoi le noyau ne suit pas la vitesse à laquelle les pages de cache sont vidées et planifie les futures vidanges en fonction de cela. C'est comme si elle allait toujours à pleine vitesse, même si ce mauvais lecteur ne peut pas suivre la vitesse. Mais c'est un sujet pour une autre question, je suppose.
antonone
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.