Юниты systemd и их разновидности.
Если вы когда-либо играли в стратегии, то наверняка помните, что юнитами там называли единицу любой разновидности войск. Лучник, инженер, большой шагающий робот — все это юниты.
В контексте systemd юниты — это отдельные объекты, которыми управляет эта система. Как и игровые войска, они имеют свои разновидности, у каждой из которых есть свое предназначение. Если вы читали предыдущие статьи, то знаете как минимум одну разновидность таких объектов — сервисы. Вот некоторые другие виды юнитов, о которых я, возможно, расскажу в следующих статьях:
- точки монтирования,
- таймеры,
- таргеты или цели,
- устройства.
Основными директориями для хранения юнитов в Ubuntu 16.04 являются:
- /lib/systemd/system — здесь находятся юниты, созданые автоматически при установке пакетов;
- /etc/systemd/system — пользовательские, вернее, администраторские юниты.
Скриншот выше демонстрирует содержимое директории с файлами юнитов.
Создаем юнит.
Файлы юнитов содержат разделы с набором параметров и их значений, разделенных знаком «=». Слева название параметра, справа значение, все предельно просто. Для начала создадим файл с названием my_backup.service и поместим его в /etc/systemd/system. Впишем в него следующие строки:
Идея этого решения принадлежит человеку с ником mezcalero из IRC чата systemd.
Давайте разберем представленный выше код.
Раздел [Unit]
хранит общие сведения о юните. В данном случае он содержит только описание (Description).
Раздел [Service]
объединяет сведения, необходимые для выполнения юнитом его задач. Type определяет тип сервиса (не путайте его с разновидностями юнитов), oneshot означает, что сервис должен выполнить разовую задачу и завершиться. ExecStop указывает скрипт, который должен быть выполнен перед остановкой сервиса. Есть еще ExecStart, этот параметр используется чаще и определяет команду, которая должна быть выполнена сразу после запуска сервиса. RemainAfterExit=true предписывает systemd считать процесс активным после его завершения.
Секция [Install]
содержит сведения о том, при каких обстоятельствах должен быть запущен сервис. WantedBy=multi-user.target устанавливает запуск при обычной загрузке компьютера.
Но это еще не все. Скрипт, который мы указали в качестве значения ExecStop, на данный момент не существует.
Пишем скрипт.
Приведенный выше код нужно поместить в файл /usr/local/bin/my_backup, а затем сделать его исполняемым:
Хотя наш скрипт совсем простой, давайте все же разберем его. Первая строка — обязательное начало любого bash скрипта. Вторая получает текущую дату и время в определенном нами формате и помещает ее в переменную current_date. Третья запускает архиватор и сообщает ему, что и куда архивировать. Кстати, не забудьте подставить свои пути вместо русского текста.
Теперь нам осталось лишь добавить наш сервис в автозагрузку и запустить его, чтобы он включился немедленно:
Обратите внимание: в команде выше я использовал my_backup, а не my_backup.service, хотя подразумевал именно это. Дело в том, что если тип юнита не указан, предполагается, что это .serivice. Полный вариант сработал бы точно так же.
Перезагрузите компьютер и проверьте, появился ли архив в указанном месте.
По желанию можно настроить сохранение резервных копий вне локального компьютера, например, в облачном хранилище. В этом случае может потребоваться проверка подключения к сети и доступности самого хранилища. Можно также настроить создание резервных копий не перед выключением, а по расписанию с помощью юнита timer. Возможно, в следующих статьях я продолжу эту тему и покажу, как это можно сделать, а заодно — продемонстрирую работу юнитов других типов.
Далеко не всегда нужно писать собственный скрипт при создании сервиса systemd. Зачастую сервисные файлы пишутся с целью управления уже существующими программами, путь к которым определяется параметрами ExecStart или ExecStop. Наш скрипт тоже использует существующую программу — tar. По большому счету, можно было обойтись и вовсе без него, сразу прописав все необходимые параметры в сервисном файле. Я включил его создание в статью только с целью демонстрации самой возможности. Но пользовательский скрипт все же будет полезен, если вы захотите усложнить задачу: отослать уведомление на электронную почту, удалить самый старый из архивов и т. д.
P.S.
В скрипте я допустил ошибку, вследствие чего после перезагрузки компьютера резервной копии не обнаружилось. Установить причину было легко:
Вот так с помощью способа, описанного в прошлой статье, я легко нашел и устранил проблему. Вы тоже можете использовать этот способ, если что-то не заработает сразу. При следующей перезагрузке архив уже лежал в отведенном ему месте: