Hacer disco / copia de disco más lento

28

¿Hay algún método para ralentizar el proceso de copia en Linux?

Tengo un archivo grande, digamos 10GB, y me gustaría copiarlo a otro directorio, pero no quiero copiarlo a toda velocidad. Digamos que me gustaría copiarlo con la velocidad de 1mb / s, no más rápido. Me gustaría usar un cpcomando estándar de Linux .

es posible? (Si es así, ¿cómo?)

Editar : entonces, agregaré más contexto a lo que estoy tratando de lograr.

Tengo un problema en el sistema ArchLinux al copiar archivos grandes a través de USB (a un pendrive, disco usb, etc.). Después de llenar el caché del búfer usb, mi sistema deja de responder (incluso el mouse se detiene; solo se mueve esporádicamente). La operación de copia aún está en curso, pero requiere el 100% de los recursos del cuadro. Cuando finaliza la operación de copia, todo vuelve a la normalidad: todo vuelve a responder perfectamente.

Tal vez sea un error de hardware, no lo sé, pero sí sé que tengo dos máquinas con este problema (ambas están en ArchLinux, una es una caja de escritorio, la segunda es una computadora portátil).

La "solución" más fácil y rápida para esto (estoy de acuerdo que no es la solución 'real', solo un 'truco' feo) sería evitar que este búfer se llene copiando el archivo con una velocidad de escritura promedio de la unidad USB, para Yo eso sería suficiente.

antonone
fuente
77
Si busca limitar la velocidad de copia de disco a disco en un esfuerzo por ser "agradable" con otros procesos vinculados de E / S en el sistema, probablemente sea mejor aprovechar la capacidad del núcleo para ajustar la programación de E / S en lugar. Específicamente, ionicese puede utilizar para garantizar que su proceso de copia de disco a disco sea una E / S programada con una prioridad menor que los procesos normales.
Steven Monday
3
Esta es una pregunta clásica de problema XY . En su lugar, debe preguntar por qué su escritorio deja de responder cuando copia archivos a un dispositivo USB.
Michael Hampton
44
Linux en realidad tiene búferes de E / S ridículamente grandes en estos días. Los tamaños de RAM han crecido más rápido que las velocidades de almacenamiento masivo. ¿Tal vez podría realizar la copia usando dd (1) y sincronizar para que realmente se sincronice periódicamente en lugar de almacenarse en el búfer? Y pipe viewer (pv) tiene una opción de limitación de velocidad. Algo así como cat file | pv -L 3k > outfile. Sin embargo, tampoco son lo mismo que usar cp (1).
ptman
@MichaelHampton, hay varios temas no resueltos sobre este tema en el foro de ArchLinux, así que pensé que trataría de enfrentarlo de una manera diferente, solo para que funcione.
Antone
@antonone Pero Unix.SE no es el foro de ArchLinux. Alguien aquí podría tener una solución.
Izkata

Respuestas:

23

Puede estrangular una tubería con pv -qL(o cstream -tproporciona una funcionalidad similar)

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

-q elimina los informes de progreso de stderr.

El -Llímite está en bytes.

Más sobre la --rate-limit/-Lbandera de 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.

Esta respuesta originalmente apuntaba throttlepero ese proyecto ya no está disponible, por lo que se ha escapado de algunos sistemas de paquetes.

Mate
fuente
Si cpno se puede ralentizar, supongo que usar un comando personalizado es la única opción.
Antonone
1
Suena demasiado complicado en comparación con elrsync
LinuxSecurityFreak
Parece más complicado pero más usable para mí. Necesita probar un mecanismo de bloqueo de archivos y necesita ralentizar la copia a algunos bytes / s, lo que parece imposible con rsync. Voy a intentarlo y 'cat' un archivo a través del tubo del acelerador
cljk
es triste decirlo pero el proyecto está muerto bugs.debian.org/cgi-bin/bugreport.cgi?bug=426891
cljk
1
@cljk actualizado a pv. Gracias.
Matt
23

En lugar de cp -a /foo /barusted, también puede usar rsyncy limitar el ancho de banda según lo necesite.

Del rsyncmanual de:

--bwlimit=KBPS

limitar el ancho de banda de E / S; KBytes por segundo

Entonces, el comando actuall, que también muestra el progreso, se vería así:

rsync -av --bwlimit=100 --progress /foo /bar
LinuxSecurityFreak
fuente
Esto suena como una buena idea para copiar discos viejos que no quiero superar.
jeremyjjbrown
No funciona para leer de /dev/zeroo/dev/random
cdosborn
rsync -a --bwlimit=1500 /source /destinationfunciona perfectamente para copiar carpetas gigantes a una velocidad de 1,5 MB / s (lo cual es un buen intercambio entre evitar que el servidor se ralentice y no tomar demasiado tiempo)
lucaferrario
Nota al margen: incluso si la página del manual puede decir que puede usar letras para unidades, por ejemplo 20m, no es compatible con todas las plataformas, por lo que es mejor atenerse a la notación KBytes.
Hubert Grzeskowiak
me salvó el día! cgroup cgexec -g ... cp /in /outno funcionaba todo el tiempo (desde la terminal funcionaba algunas veces, desde el script nunca) y no tengo idea de por qué ...
Aquarius Power
13

Supongo que está tratando de no interrumpir otra actividad. Las versiones recientes de Linux incluyen ionicelo que le permite controlar la programación de IO.

Además de permitir varias prioridades, hay una opción adicional para limitar la E / S a los momentos en que el disco está inactivo. El comando man ionicemostrará la documentación.

Intente copiar el archivo usando un comando como:

ionice -c 3 cp largefile /new/directory

Si los dos directorios están en el mismo dispositivo, puede encontrar que vincular el archivo hace lo que desea. Si está copiando con fines de copia de seguridad, no use esta opción. lnes extremadamente rápido ya que el archivo en sí no se copia. Tratar:

ln largefile /new/directory

O si solo desea acceder desde un directorio en un dispositivo diferente, intente:

ln -s largefile /new/directory
BillThor
fuente
¿Ionice funciona bien en Linux? Lo leo simplemente "emular" el trabajo y no hay una diferencia real? +1 para enlaces
Nick
1
@Nick Cuando lo he usado, se ha comportado como se esperaba. El proceso al que apliqué ionice se ralentizó significativamente, y los otros procesos que necesitaban E / S pudieron funcionar como se esperaba. Con una carga de E / S moderada de otros procesos, pude suspender efectivamente un proceso de alta E / S aplicando la máxima 'amabilidad' como se esperaba. Una vez que no hubo E / S competidoras, el proceso ionizado se realizó de manera normal.
BillThor
con el archivo de 400 MB que estaba copiando de una HD a una SSD, los 10 primeros funcionaron perfectamente, de repente vi que tenía una carga de E / S alta y tuve que esperar como una máquina de 1 minuto congelada: /. Tengo el mismo problema con cgroup write io throttle donde funciona a veces y otras no funcionará en absoluto.
Acuario Power
7

Si la ionicesolución no es suficiente (por ejemplo) y realmente desea limitar la E / S a un valor absoluto, existen varias posibilidades:

  1. el probablemente más fácil: ssh. Tiene un límite de ancho de banda incorporado. Usaría, por ejemplo, tar(en lugar de cp) o scp(si eso es lo suficientemente bueno; no sé cómo maneja los enlaces simbólicos y los enlaces duros) o rsync. Estos comandos pueden canalizar sus datos ssh. En caso de tarque escriba a /dev/stdout(o -) y canalice eso en el sshcliente que ejecuta otro taren el lado "remoto".

  2. elegante, pero no en el núcleo de vainilla (que yo sepa): El objetivo del mapeador de dispositivos ioband. Esto, por supuesto, solo funciona si puede desmontar el volumen de origen o de destino.

  3. algo de diversión auto escrita: grep "^write_bytes: " /proc/$PID/iole brinda la cantidad de datos que ha escrito un proceso. Podría escribir un script que comience cpen segundo plano, duerma, por ejemplo, 1/10 de segundo, detenga el cpproceso en segundo plano ( kill -STOP $PID), verifique la cantidad que se ha escrito (y lea? Sobre el mismo valor en este caso), calcule cuánto tiempo cpdebe detenerse para reducir la tasa de transferencia promedio al valor deseado, duerme durante ese tiempo, se despierta cp( kill -CONT $PID), etc.

Hauke ​​Laging
fuente
Sí, normalmente solo estoy usando lftp para conectarme a localhost a través de scp, y limitar el bandwich desde allí.
Antone
5

Su problema probablemente no sea con su computadora, per se, probablemente esté bien. Pero esa capa de transición de flash USB tiene un procesador propio que tiene que mapear todas sus escrituras para compensar lo que podría ser un chip flash defectuoso en un 90%, ¿quién sabe? Lo inundará, luego inundará sus amortiguadores, luego inundará todo el autobús, luego estará atrapado, hombre, después de todo, ahí es donde están todas sus cosas. Puede sonar contra-intuitivo, pero lo que realmente necesita es bloquear E / S: debe dejar que el FTL marque el ritmo y luego seguir el ritmo.

(Sobre la piratería de microcontroladores FTL: http://www.bunniestudios.com/blog/?p=3554 )

Todas las respuestas anteriores deberían funcionar, así que este es más un "¡yo también!" que cualquier otra cosa: he estado totalmente allí, hombre. Resolví mis propios problemas con rsync's --bwlimit arg (2.5mbs parecía ser el punto ideal para una sola ejecución sin errores, cualquier cosa más y terminaría con errores de protección contra escritura). rsync fue especialmente adecuado para mi propósito porque estaba trabajando con sistemas de archivos completos, por lo que había muchos archivos, y simplemente ejecutar rsync por segunda vez solucionaría todos los problemas de la primera ejecución (que era necesario cuando me impacientaba e intentaba para pasar más de 2.5 mb).

Aún así, supongo que eso no es tan práctico para un solo archivo. En su caso, podría simplemente canalizar a dd configurado en escritura sin formato: puede manejar cualquier entrada de esa manera, pero solo un archivo de destino a la vez (aunque ese único archivo podría ser un dispositivo de bloque completo, por supuesto).

## 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 [email protected] <<-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  

Es posible que netcat sea un poco más rápido que ssh para el transporte de datos si lo intenta. De todos modos, las otras ideas ya fueron tomadas, entonces ¿por qué no?

[EDITAR]: Noté las menciones de lftp, scp y ssh en la otra publicación y pensé que estábamos hablando de una copia remota. El local es mucho más fácil:

% 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]: Crédito donde es debido: acabo de notar que ptman me ganó en esto por cinco horas en los comentarios.

Definitivamente, podría ajustar $ bs para el rendimiento aquí con un multiplicador, pero algunos sistemas de archivos pueden requerir que sea un múltiplo del tamaño del sector de fs objetivo, así que tenga esto en cuenta.

mikeserv
fuente
En mi máquina, la bandera --getiooptno lo es--getoptio
Michael Mior
2

El problema es que la copia está llenando su memoria con bloques "en vuelo", desplazando datos "útiles". Un error conocido (y muy difícil de solucionar) en el manejo del kernel de Linux de E / S para dispositivos lentos (USB en este caso).

Quizás pueda intentar dividir la copia, por ejemplo, mediante un guión como el siguiente (boceto de prueba de concepto, ¡ totalmente no probado!):

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

ajustando seeky skippor countcada ronda. Necesita sintonizar countpara que no llene (demasiado) la memoria y 5permita que se agote.

vonbrand
fuente
2

Baje el límite de página sucia. El límite predeterminado es una locura.

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

vm.dirty_background_ratio = 3
vm.dirty_ratio = 10

Luego ejecute sysctl -p o reinicie.

Lo que sucede es que los datos se leen más rápido de lo que se pueden escribir en el disco de destino. Cuando Linux copia archivos, lo que hace es leerlos en la RAM, luego marcar las páginas como sucias para escribir en el destino. Las páginas sucias no se pueden intercambiar. Por lo tanto, si el disco de origen es más rápido que el disco de destino y está copiando más datos de los que tiene RAM libre, la operación de copia consumirá toda la RAM disponible (o al menos cualquiera que sea el límite de página sucia, que podría ser mayor que el RAM disponible) y causar hambre, ya que las páginas sucias no se pueden cambiar y las páginas limpias se usan y se marcan como sucias a medida que se liberan.

Tenga en cuenta que el suyo no resolverá por completo el problema ... lo que Linux realmente necesita es alguna forma de arbitrar la creación de páginas sucias para que una transferencia grande no consuma toda la RAM disponible / todas las páginas sucias permitidas.

alex.forencich
fuente
0

Este problema no tiene nada que ver con errores o fallas en el hardware o el software, es solo su núcleo tratando de ser amable con usted y devolver su mensaje y copiar en segundo plano (utiliza una memoria caché en el núcleo: más RAM, más memoria caché, pero puede limitarlo escribiendo en algún lugar de / proc, aunque no se recomienda). Las unidades flash son demasiado lentas y mientras el núcleo escribe en él, otras operaciones de E / S no pueden realizarse lo suficientemente rápido. ionicemencionado varias veces en otras respuestas está bien. ¿Pero ha intentado simplemente montar la unidad -o syncpara evitar el almacenamiento en búfer del sistema operativo? Es probablemente la solución más simple que existe.

Orión
fuente
Después de habilitar -o sync, mi Internet es más rápido que la velocidad de escritura en esta unidad USB. Lo que no entiendo es por qué el kernel no realiza un seguimiento de la rapidez con la que se vacían las páginas de la memoria caché y planifica futuros enjuagues en función de eso. Es como si siempre fuera a toda velocidad, incluso si este disco deficiente no puede mantener el ritmo. Pero ese es un tema para otra pregunta, supongo.
Antonone