Я хотел бы получить резервную копию некоторых файлов с сервера. Основная идея заключается в создании архива с использованием tar , сохранении его на диск и загрузке. Проблема заключается в отсутствии свободного дискового пространства (или оперативной памяти для tmpfs), что вынуждает меня разбить архив и загрузить его порциями.

Есть ли простой способ (например, путем добавления другой команды между конвейером от tar до split) сделать паузу split , когда диск слишком заполнен для следующего фрагмента, и продолжить, когда диск снова будет свободен? (По умолчанию split просто выходит с сообщением об ошибке, если запись не удалась из-за переполнения диска.)

Альтернативы, которых я хотел бы избежать:

  • Передача tar через SSH для сохранения его непосредственно в месте назначения - соединение может разорваться, если загрузка выполняется слишком долго, а загружающий клиент работает под управлением Windows.
  • Использование dsplit (или что-то подобное для создания нескольких архивов tar) - я ожидаю, что это не позволит мне объединить архивы после их загрузки.

1 ответ1

1

Ниже приведен быстрый и грязный скрипт 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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .