Ниже приведен быстрый и грязный скрипт sh
предназначенный для работы в качестве фильтра (между tar
и split
в вашем случае). Он был построен в Ubuntu и, возможно, потребует некоторых настроек для других систем (например, я не уверен, является ли column -t | cut -d " " -f 7
правильным способом для анализа df
независимо от ОС). Требуется /proc
.
Сохраните его как ensuredf
куда указывает ваша $PATH
, сделайте исполняемый файл (chmod -x ensuredf
) и используйте его так:
… | ensuredf path requirement | …
где
path
- это каталог, который вы хотите отслеживать;
requirement
- желаемое свободное пространство (df -B
должен это понимать);
Пример:
… | ensuredf /mnt/foo/data/ 2G | …
Идея состоит в том, чтобы позволить фоновой cat
передавать данные из stdin
(сценария) в stdout
но немедленно приостанавливать их. Затем вызовите df
для заданного path
, проанализируйте его вывод и проверьте, есть ли больше места, чем requirement
. Если это так, cat
возобновляется, в противном случае она приостанавливается. Это цикл с жестко заданным интервалом в 1 секунду, пока существует запись /proc
для этой cat
.
Другие заметки:
- некоторые файловые системы (особенно BTRFS) производят вывод
df
не так точно, как хотелось бы;
- если ваш
tar
очень быстрый, а требуемое пространство очень мало, интервал в 1 секунду может быть слишком длинным;
- но даже если интервал был нулевым, когда свободное пространство станет меньше
requirement
будет некоторая задержка, прежде чем cat
будет поставлена на паузу;
- если по какой-то причине сценарий переднего плана задерживается и фоновая
cat
работает хорошо, диск все равно может заполниться.
Это означает, что вы должны установить свои requirement
с надлежащим запасом прочности. Используйте этот код в качестве примера и приспособьтесь к вашим потребностям. Мне удалось написать более безопасный сценарий, который продолжает вызывать передний план dd
для передачи фрагмента данных, если и только если достаточно дискового пространства, но эти несколько процессов dd
были намного медленнее, чем один 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