Скрипт резервного копирования файлов на Python + cron

Часто возникают задачи по резервному копирования файлов и директорий по расписанию. Эту задачу можно очень просто реализовать с помощью встроенного в Linux планировщика задач Cron.

Crontab

В Ubuntu Server в качестве планировщика задач используется cron — планировщик с интерфейсом командной строки. Он является важной частью системы и начинает функционировать сразу после установки, исполняя различные системные задачи. Наша цель — поставить его себе на службу, тем более это не так сложно как кажется.

Предусмотрено два типа расписаний cron: пользовательское и системное. Отличаются они тем, что первое создается пользователями и исполняется с учетом пользовательских прав, второе используется в административных или системных целях и может быть запущено от имени любого пользователя.

Чтобы создать или изменить пользовательское расписание наберите команду:

crontab -e

Формат строк расписания имеет вид:

Минута - время в минутах от 0 до 59
Час - от 0 до 23
День - день месяца от 1 до 31
Месяц - от 1 до 12 либо буквенные обозначения jan - dec
День недели - от 0 до 6 (0 - воскресенье) или sat - sun

l

  • Команда — строка в формате командного интерпретатора которая будет исполнена, допускается запись типа команда1 && команда2 для запуска нескольких команд подряд.

Значения минут, часов, дней можно указывать следующим образом:

  • Значение — число обозначающее дату или время, допускается подстановочный знак *  допускающий полный диапазон значений
  • Несколько значений — допускается указывать несколько значений через запятую, например 2,14,22
  • Диапазон значений — указывается через дефис, например 2-10
  • Шаг значений — указывается через дробь, в знаменатель которой ставится шаг, например */3 — каждое третье значение 0, 3, 6, 9 и т.д. В качестве числителя должен быть диапазон значений либо звездочка.

Рассмотрим следующий пример записи:

 0 8-19/2 * * 1 /home/ivanov/test

Она означает что каждый второй час с 8 до 19 (8, 10,12,14,16) по понедельникам запускать скрипт test в домашнем каталоге Иванова.

Кроме даты можно использовать ряд специальных строк:

    • @reboot — выполнять команду при перезагрузке
    • @yearly или @annually — выполнять 1 января, аналогично записи: «0 0 1 1 * «
    • @monthly — выполнять 1 числа каждого месяца, аналогично «0 0 1 * * «
    • @weekly — выполнять каждое воскресенье, равносильно «0 0 * * 0«
    • @daily или @midnight — ежедневно в полночь,»0 0 * * * «
    • @hourly — раз в час, «0 * * * * «

Завершив составление расписания сохраняем файл и выходим из редактора. Пользовательское расписание будет сохранено в /var/spool/cron/crontabs под именем текущего пользователя.

Для системных и административных задач предусмотрен файл /etc/crontab синтаксис записей в нем отличается наличием дополнительного значения — пользователя, от чьего имени будет запущено задание:

минута час день месяц день_недели пользователь команда

Пример такой записи:

0 19 * * 1-5 root /etc/backup

Согласно которой в 19:00 с понедельника по пятницу будет запускаться скрипт /etc/backup от имени пользователя root.

Скрипт резервного копирования

#shell_backup.py
"""
Скрипт создании резервной копии директории. 
"""
import shutil
import sys
import os
from datetime import datetime as DT


if len(sys.argv) > 1 :
    path_from = sys.argv[-1] # если указана директория в аргументах при вызове скрипта из командной строки
    path_to = path_from +'/../backups/'+path_from.split('/')[-1]+'_'+DT.today().strftime("%d%m%Y-%H%M%S")
else:
    path_from = os.getcwd() # если директория не указана, то бэкап создается относительно папки где расположен скрипт
    path_to = '../backups/'+path_from.split('/')[-1]+'_'+DT.today().strftime("%d%m%Y-%H%M%S")

#копируем директорию исключая файлы *.pyc, *.sock и папку backups. Можно скорректировать ignore под свои нужды, либо удалить, если необходимо копировать полностью содержимое директории
shutil.copytree( path_from, path_to, symlinks=False, ignore_dangling_symlinks=True, ignore=shutil.ignore_patterns('*.pyc', '*.sock', 'backups*') )

#вывод информации о копировании
print(path_from, ' => ', path_to, sys.argv)

Для запуска скрипта ежедневно в 0:00 в редакторе crontab -e прописываем команду:

0 0 * * * python3 /path/to/shell_backup.py <Путь к директории резервного копирования. Если не указывать, то будет копироваться директория, где лежит скрипт.>