script útil para reduzir a contagem de hardlinks?

script útil para reduzir a contagem de hardlinks?

Estou fazendo a transição de um conjunto de arquivos grande de um sistema de arquivos com alto _PC_LINK_MAX(número máximo de hardlinks por inode) para um inferior.

Em particular, estou brincando com o Amazon EFS, que tem no máximo 175, conforme ditoaqui.

Então, eu gostaria que a entrada fosse um conjunto de arquivos com contagens de links de até 250 reorganizados, para que os inodes fossem divididos, de modo que o máximo fosse 100 links cada.

Existe uma invocação inteligente de, digamos, hardlink que possa fazer isso? Ou talvez uma opção rsync -aHou talvez cp -aque possa ajudar?

...caso contrário, alguma pirataria é necessária...

Responder1

A situação é complicada. Imagine que o máximo de links é 5 e você tem 12 arquivos a01com a12todos os links físicos. Você precisa dividir a01..a05and a06..a10and a11..a12, onde a06e a07etc ainda estão vinculados, mas não a01.

Aqui está um script bash rsyncque é executado em um exemplo de diretório de origem ( src=/usr/libexec/git-core/) no meu sistema que possui 110 links físicos. Simula um número máximo de 50 links( max) no diretório de destino realdestpela função sim. Em um caso real, você simplesmente ignoraria omuitos linkserros e não usar esta função.

Após o rsync normal inicial (com erros), a lista de arquivos ausentes é criada usando rsync -ni, extraindo os nomes dos arquivos na função calctodopara /tmp/todo.

Há então um loop onde coletamos rsyncos arquivos ausentes, novamente ignorandomuitos linkserros (que você teria se tivesse mais de 2*175links no diretório original). Os arquivos criados com sucesso são vinculados entre si. A nova lista de arquivos ausentes é calculada. Isso é repetido até que não haja mais arquivos.

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

Você pode precisar revisar isso se tiver nomes de arquivos com " => ", novas linhas e assim por diante.


Observe que você pode encontrar o número máximo de links suportados por um sistema de arquivos clicando em

getconf LINK_MAX /some/directory

informação relacionada