¿Secuencia de comandos útil para reducir el número de enlaces duros?

¿Secuencia de comandos útil para reducir el número de enlaces duros?

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 -aHo tal vez cp -aque 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 a01todos a12vinculados entre sí. Debe separar a01..a05y a06..a10y a11..a12, donde a06y a07etc todavía están vinculados entre sí, pero no para a01.

Aquí hay un script bash rsyncque 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 realdestmediante 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 calctodoen /tmp/todo.

Luego hay un bucle donde buscamos rsynclos archivos que faltan, ignorando nuevamentedemasiados enlaceserrores (que tendría si tuviera más de 2*175enlaces 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

información relacionada