¿Cuál es la mejor manera de realizar una copia paralela en Unix?

18

Rutinariamente tengo que copiar el contenido de una carpeta en un sistema de archivos de red a mi computadora local. Hay muchos archivos (1000) en la carpeta remota que son relativamente pequeños, pero debido a la sobrecarga de la red, una copia regular cp remote_folder/* ~/local_folder/lleva mucho tiempo (10 minutos).

Creo que es porque los archivos se copian secuencialmente; cada archivo espera hasta que finalice el anterior antes de que comience la copia.

¿Cuál es la forma más sencilla de aumentar la velocidad de esta copia? (Supongo que es realizar la copia en paralelo).

Comprimir los archivos antes de copiarlos no necesariamente acelerará las cosas porque pueden guardarse en diferentes discos en diferentes servidores.

dsg
fuente
Comprimir los archivos antes de copiarlos acelerará las cosas de forma masiva porque ya no será necesario "obtuviste ese archivo", "sí, lo hice", "aquí está el próximo", "está bien", ... Son esos "cambios" que lo retrasan.
David Schwartz
Probablemente sea la velocidad del disco, en lugar de la velocidad de la red, ese es su factor limitante, y si ese es el caso, hacer esto por archivo en paralelo hará que la operación sea más lenta , no más rápida, porque obligará al disco a buscar constantemente hacia adelante y hacia atrás entre archivos
Joel Coehoorn
Si bien la compresión puede no ser una buena idea (ejecutar algo de compresión en más de 1000 archivos puede demorar un poco), el alquitrán podría ser viable.
Rob
@JoelCoehoorn aún, hay casos en los que este no es el caso: por ejemplo, varios husillos + archivos pequeños (o simplemente lecturas aleatorias). En este escenario, "cp paralelo" ayudaría.
CAFxX
serverfault.com/questions/152331/parallel-file-copy
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Respuestas:

8

Mientras limite los comandos de copia que está ejecutando, probablemente podría usar un script como el publicado por Scrutinizer

SOURCEDIR="$1"
TARGETDIR="$2"
MAX_PARALLEL=4
nroffiles=$(ls "$SOURCEDIR" | wc -w)
setsize=$(( nroffiles/MAX_PARALLEL + 1 ))
ls -1 "$SOURCEDIR"/* | xargs -n "$setsize" | while read workset; do
  cp -p "$workset" "$TARGETDIR" &
done
wait
OldWolf
fuente
1
Nota de advertencia: este script se rompe con nombres de archivos que contienen espacios o caracteres globales.
slhck
@OldWolf - ¿Puedes explicar cómo funciona este script? Por ejemplo, ¿qué parte hace la paralelización?
dsg
3
@dsg: &al final del cpcomando permite que el whilebucle continúe e inicie el siguiente comando cp sin esperar. El xargscomando pasa los nombres de archivo en grupos de 4 (MAX_PARALLEL) al whilebucle.
RedGrittyBrick
No me ha funcionado. No estoy seguro de que sea posible acelerar cp. Obviamente, puede acelerar el cálculo a través del subprocesamiento múltiple . Pero no creo que lo mismo sea válido para la copia de datos del disco duro.
Adobe
9

Si tiene instalado GNU Parallel http://www.gnu.org/software/parallel/ , puede hacer esto:

parallel -j10 cp {} destdir/ ::: *

Puede instalar GNU Parallel simplemente por:

$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
   fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 3374ec53bacb199b245af2dda86df6c9
12345678 3374ec53 bacb199b 245af2dd a86df6c9
$ md5sum install.sh | grep 029a9ac06e8b5bc6052eac57b2c3c9ca
029a9ac0 6e8b5bc6 052eac57 b2c3c9ca
$ sha512sum install.sh | grep f517006d9897747bed8a4694b1acba1b
40f53af6 9e20dae5 713ba06c f517006d 9897747b ed8a4694 b1acba1b 1464beb4
60055629 3f2356f3 3e9c4e3c 76e3f3af a9db4b32 bd33322b 975696fc e6b23cfb
$ bash install.sh

Mire los videos de introducción de GNU Parallel para obtener más información: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Ole Tange
fuente
3

Una forma sería usar rsync, que solo copiará los cambios: los archivos nuevos y las partes cambiadas de otros archivos.

http://linux.die.net/man/1/rsync

La ejecución de cualquier forma de operación de copia paralela probablemente inundará su red y la operación de copia simplemente se detendrá o sufrirá cuellos de botella en el disco de origen o de destino.

Linker3000
fuente
2

Honestamente, la mejor herramienta es gsutil de Google. Maneja copias paralelas con recursividad de directorio. La mayoría de los otros métodos que he visto no pueden manejar la recursividad del directorio. No mencionan específicamente el sistema de archivos local a las copias del sistema de archivos local en sus documentos, pero funciona de maravilla.

Es otro binario para instalar, pero probablemente uno que ya pueda ejecutar teniendo en cuenta toda la adopción del servicio en la nube hoy en día.

diq
fuente
2

Rsync paralelo usando find:

export SOURCE_DIR=/a/path/to/nowhere
export DEST_DIR=/another/path/to/nowhere

# sync folder structure first
rsync -a -f'+ */' -f'- *' $SOURCE_DIR $DEST_DIR

# cwd
cd $SOURCE_DIR

# use find to help filter files etc. into list and pipe into gnu parallel to run 4 rsync jobs simultaneously
find . -type f | SHELL=/bin/sh parallel --linebuffer --jobs=4 'rsync -av {} $DEST_DIR/{//}/'

en una LAN corporativa, rsync solo hace aproximadamente 800Mbps; Con 6-8 trabajos puedo obtener más de 2.5 Gbps (a expensas de la alta carga). Limitado por los discos.

yee379
fuente
0

Hay muchas cosas que uno debe tener en cuenta dependiendo de la topología que tenga. Pero antes de comenzar a pensar en soluciones complejas, simplemente puede tratar de dividir la tarea en dos trabajos y verificar si el tiempo necesario se reducirá significativamente:

La próxima vez intente:

  cp remote_folder/[a-l]* ~/local_folder/ &
  cp remote_folder/[!a-l]* ~/local_folder/ &
  wait
  wait

(es posible que desee reemplazar [al] * por algo más que coincida con aproximadamente la mitad de los archivos, tal vez [0-4] *, dependiendo del contenido de la carpeta)

Si el tiempo mejora drásticamente, puede ser más importante verificar si es necesario copiar todos los archivos (¿cuál es la proporción de archivos modificados a todos los archivos?)

ktf
fuente