Estoy realizando la transición de un conjunto de archivos grande de un sistema de archivos con un nivel alto _PC_LINK_MAX
(número máximo de enlaces físicos por inodo) a uno inferior.
En particular, estoy jugando con Amazon EFS, que tiene un máximo de 175, como se indicaaquí.
Entonces, me gustaría que la entrada sea un conjunto de archivos con un número de enlaces de hasta 250 reajustados, de modo que los inodos se dividan, de modo que el máximo sea 100 enlaces cada uno.
¿Existe una invocación inteligente de, digamos, hardlink
que pueda hacer esto? ¿O tal vez una opción rsync -aH
o tal vez cp -a
que pueda ayudar?
...de lo contrario, es necesario algo de piratería...
Respuesta1
La situación es complicada. Imagine que el máximo de enlaces es 5 y tiene 12 archivos
a01
todos a12
vinculados entre sí. Debe separar a01..a05
y a06..a10
y a11..a12
, donde a06
y a07
etc todavía están vinculados entre sí, pero no para a01
.
Aquí hay un script bash rsync
que se ejecuta en un directorio fuente de ejemplo ( src=/usr/libexec/git-core/
) en mi sistema que tiene 110 enlaces físicos. Simula un número máximo de 50 enlaces ( max
) en el directorio de destino realdest
mediante la función sim
. En un caso real simplemente ignorarías eldemasiados enlaceserrores y no utilizar esta función.
Después del rsync normal inicial (con errores), la lista de archivos faltantes se crea usando rsync -ni
, extrayendo los nombres de archivos en función calctodo
en /tmp/todo
.
Luego hay un bucle donde buscamos rsync
los archivos que faltan, ignorando nuevamentedemasiados enlaceserrores (que tendría si tuviera más de 2*175
enlaces en el directorio original). Los archivos creados correctamente están vinculados entre sí. Se calcula la nueva lista de archivos faltantes. Esto se repite hasta que no queden más archivos.
src=/usr/libexec/git-core/
realdest=/tmp/realdest
#rm -fr "$realdest"
max=50
sim(){
find ${1?} -links +$max |
sed "1,${max}d" |
xargs --no-run-if-empty rm
}
calctodo(){
sed -n '/^hf/{ s/[^ ]* //; s/ =>.*//; p }' >/tmp/todo
}
rsync -aHR "$src" "$realdest"; sim "$realdest"
rsync -niaHR "$src" "$realdest" | calctodo
while [ -s /tmp/todo ]
do mv /tmp/todo /tmp/todo.old
rsync -aHR --files-from=/tmp/todo.old / "$realdest"; sim "$realdest"
rsync -niaHR --files-from=/tmp/todo.old / "$realdest" | calctodo
done
Es posible que necesites revisar esto si tienes nombres de archivos con " => ", nuevas líneas, etc.
Tenga en cuenta que puede encontrar el número máximo de enlaces admitidos por un sistema de archivos haciendo clic en
getconf LINK_MAX /some/directory