A maioria abaixo é um script rápido e sujo sh
desenvolvido para funcionar como um filtro (entre tar
e split
no seu caso). Ele foi criado no Ubuntu e pode precisar de alguns ajustes para outros sistemas (por exemplo, não sei se column -t | cut -d " " -f 7
é o caminho certo para analisar df
independentemente do sistema operacional). Requer /proc
.
Salve como ensuredf
para onde $PATH
aponta, torne executável ( chmod -x ensuredf
) e use assim:
… | ensuredf path requirement | …
onde
-
path
é o diretório que você deseja monitorar; -
requirement
é o espaço livre desejado (df -B
deve entender isso);
Exemplo:
… | ensuredf /mnt/foo/data/ 2G | …
A ideia é permitir que o plano de fundo cat
passe dados de stdin
(do script) para stdout
, mas pause imediatamente. Em seguida, invoque df
para um determinado path
, analise sua saída e verifique se há mais espaço que requirement
. Em caso afirmativo, cat
é retomado, caso contrário, ele é pausado. Isso faz um loop com um intervalo codificado de 1 segundo, contanto que /proc
entrada para esse cat
exista.
Outras notas:
- alguns sistemas de arquivos (especialmente BTRFS) tornam a saída
df
não tão exata quanto você gostaria; - se o seu
tar
for muito rápido e o espaço necessário for muito baixo, o intervalo de 1 segundo poderá ser muito longo; - mas, mesmo que o intervalo seja zero, quando o espaço livre ficar abaixo do
requirement
, haverá algum atraso antes que ocat
seja pausado; - se por algum motivo o script de primeiro plano for atrasado e o plano de fundo
cat
funcionar bem, o disco poderá ficar cheio de qualquer maneira.
Isso significa que você deve definir seu requirement
com a margem de segurança adequada. Use este código como um exemplo e ajuste suas necessidades. Consegui escrever um script mais seguro que invoca o primeiro plano dd
para passar um pedaço de dados se e somente se houver espaço em disco suficiente, mas esses vários processos dd
eram muito mais lentos que um único cat
.
#!/bin/sh
[ $# -eq 2 ] || { printf '%s\n' "usage: $0 path requirement" >&2 ; exit 1;}
pth="$1"
rqrmnt="$2"
intrvl=1
</proc/$$/fd/0 cat >/proc/$$/fd/1 &
kill -s STOP $!
while [ -d /proc/$! ] ; do
if [ $(df -P -B "$rqrmnt" "$pth" | tail -n 1 | column -t | cut -d " " -f 7) -ge 2 ]
then kill -s CONT $!
else kill -s STOP $!
fi
sleep "$intrvl"
done