Мы каждый день сталкиваемся со множеством однотипных задач. Постоянно возвращаясь к ним, мы расходуем самый ценный ресурс — время. В итоге застреваем в рутине, рискуем не уложиться в сроки и совершить ошибку.

Но можно остановиться и передать повторяющуюся работу тому, кто не забудет и не промахнётся. Нас спасёт автоматизация!

Сегодня расскажем о том, как автоматизировать рутинные задачи на Linux-сервере при помощи cron и немного с помощью скриптов.

Планировщик заданий в Linux: cron

Cron — стандартный планировщик в Unix-подобных операционных системах. Он работает как фоновый демон: непрерывно следит за расписанием и в нужный момент запускает указанную команду или скрипт.

Cron — от греческого «χρόνος» (chronos) — время. Он появился в Unix ещё в 1970-х и с тех пор не потерял своей значимости в администрировании систем. Cron запускает задачу с точностью до минуты. Его расписание может быть очень гибким: от «каждую минуту» до «один раз в год». Cron может иметь отдельные планы заданий для каждого пользователя системы, и после настройки он работает автономно и не требует вмешательства пользователя. По факту, любую повторяющуюся задачу, которую вы делаете вручную по расписанию, можно автоматизировать через cron. Любую на Linux. Почти любую.

Для работы с cron используется утилита crontab, которая управляет таблицей заданий для текущего пользователя. В основных Linux-системах каждый пользователь может иметь собственный crontab, независимый от других.

А может и не иметь, ведь crontab создаётся только тогда, когда пользователь впервые запускает команду:

crontab -e

Данная команда открывает файл задач в текстовом редакторе, обычно это — vi или nano, и после сохранения cron сразу же подхватывает изменения без перезапуска сервиса.

Задание в cron задаётся в следующем формате:

* * * * * команда

│ │ │ │ └────────── день недели (0–7)

│ │ │ └────────── месяц (1–12)

│ │ └────────── день месяца (1–31)

│ └────────── час (0–23)

└────────── минута (0–59)

Звёздочку (*) система воспринимает как любое значение, то есть задание будет выполняться при каждом значении соответствующего поля.

Кроме звёздочки, поля в задании могут содержать:

  • одно какое-либо число, например, 29 или 6;

  • диапазон чисел, например, 1-4, то есть все значения от 1 до 4 включительно из диапазона, допустимого для данного поля;

  • список чисел, например, 2,5,6;

  • шаг, например, */5 означает каждые 5 единиц, начиная с минимального значения.

Здесь есть некоторые неочевидные для новичков тонкости. Например, дни недели могут принимать значения от 0 до 7. Не от одного, а от нуля. В итоге получается целых 8 значений, а дней недели — всего 7. Почему так? Потому что в cron два воскресенья — 0 и 7. Дело в том, что в старых его реализациях для воскресенья использовался 0, но чтобы упростить совместимость с ISO-стандартом, позже разрешили ещё и 7 для обозначения воскресного дня.

Или, вот шаг. В нём число после знака / определяет, через сколько единиц значений будет выполняться задание, начиная с минимально допустимого в этом поле значения. Например, /10 для минут будет означать, что задание будет выполняться в минимально возможное количество минут, а затем каждые +10 пока не закончится нумерация минут в пределах часа. То есть, данная запись означает выполнение задания в 0, 10, 20, 30, 40 и 50 минут означенного часа. В отношении часов такая запись означает запуск задачи в 0 (полночь), 10 и 20 часов означенных суток. Для дней месяца минимальным значением является 1 — первый день месяца. Это означает. что запись /10 в третьей слева позиции инициирует выполнение задачи в первый день месяца, а затем в каждый +10-й день, пока не закончится месяц — 11, 21 и 31-е число, при условии, что последнее значение присутствует в нумерации текущего месяца. Аналогично для месяцев: /10  означает 1-й и 11-й месяцы, то есть январь и ноябрь. Применительно к дням недели запись /10 не имеет практического смысла, так как диапазон значений здесь ограничен числами от 0 до 7, то есть всего восемь возможных значений. Таким образом, шаг 10 превышает длину диапазона, и задание будет выполняться только для минимального значения, то есть для 0 — воскресенья. Здесь важно понимать, что указанное в шаге число не означает каждые x единиц времени от последнего запуска или от текущего момента, а определяет выполнение задачи каждые x значений поля от его минимального значения.

Это мы рассмотрели запись */10. А ведь можно вместо звёздочки использовать число, например, 3/10. Такая запись означает, что планировщик будет прибавлять 10, но уже не к минимальному значению, а к значению 3. То есть, для минут задание будет выполняться в 3, 13, 23, 33, 43, 53 минуты; для часов и чисел месяца — в 3, 13, 23; для месяцев и дней недели — только в 3 (март или среда).

Для некоторых значений времени в cron существуют специальные директивы:

  • @yearly или @annually означает один раз в год и заменяет собой комбинацию 0 0 1 1 *, то есть в 00:00 1 января каждого года;

  • @monthly — раз в месяц, заменяет комбинацию 0 0 1 * *, то есть в 00:00 первого числа каждого месяца;

  • @weekly — раз в неделю, заменяет комбинацию 0 0 * * 0 и означает каждое воскресенье в 00:00;

  • @daily или @midnight — раз в день, заменяет комбинацию 0 0 * * * и означает в полночь каждый день;

  • @hourly — догадайтесь сами :-) (ответ — ноль и четыре звёздочки).

Есть ещё одна полезная директива — @reboot. Она позволяет выполнять указанную команду один раз при запуске системы. Полезность данной директивы заключается в том, что она не зависит от времени или дня и запускается только при перезагрузке или старте сервера.

Ну если разобрались с форматом записи месяцев, дней, часов и минут, то в шестом поле указываем команду, которая должна выполняться в указанное время.

Что можно использовать в качестве команды? Во-первых, любые shell-команды: ls, cp, rm и т.д. Во-вторых, скрипты: bash, python, php и т.п. В-третьих, исполняемые файлы. А также, цепочки команд с операторами &&, ||, ; и перенаправление вывода типа >, >>, 2>&1.

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

Какие задачи можно решать при помощи cron?

Основное назначение cron — делегирование системе задач, для выполнения которых можно использовать расписание, чтобы разгрузить администратора данной системы, оградив его от определённого количества рутинной работы. Давайте рассмотрим некоторые типы и примеры задач, решить которые может помочь cron.

Резервное копирование и архивация

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

0 2 * * * /usr/bin/mysqldump -u mysql-user -p'mysql-password' mysql-database > /backup/db_$(date +\%Y\%m\%d).sql

Такая строка в cron представляет собой  пример ежедневного создания дампа базы данных MySQL или MariaDB с сохранением его в директории /backup/ под именем, частью которого будет текущая дата. Это, чтобы можно было понять, когда этот бэкап сделан.   

Ещё один пример — еженедельное создание tar-архива каталога /var/www/html/, в котором, вероятно, находятся файлы веб-сайта. 0 в пятой позиции означает запуск команды каждое воскресенье, а имя архива, как и в предыдущем примере, будет содержать дату архивирования данных:

0 3 * * 0 tar -czf /backup/weekly_$(date +\%Y\%m\%d).tar.gz /var/www/html

Подобным же образом при помощи rsync — утилиты для быстрой и надёжной синхронизации файлов и каталогов, можно с определённой периодичностью копировать данные из одной Linux-системы в другую:

30 4 * * * rsync -avz /important/data/ remote-user@192.168.0.11:/backup/

Прелесть данной утилиты в том, что она копирует только изменённые данные, что позволяет экономить трафик и время. Конкретно в этой команде:

  • /important/data/ — каталог, содержимое которого подлежит синхронизации с удалённым ресурсом. Обратите внимание на слэш в конце: он означает, что копировать нужно только содержимое каталога, а не сам каталог.

  • remote-user@192.168.0.11:/backup/ — место назначения, где:

    • remote-user — это имя пользователя на удалённой системе;

    • 192.168.0.11 — IP-адрес удалённой системы;

    • /backup/ — директория на удалённом узле, в который будет помещено содержимое исходного каталога.

На VPS всё это особенно актуально: регулярные дампы, архивация и перенос данных между серверами — типичная практика. На виртуальных серверах UltraVDS, например, можно настроить такие задачи буквально за несколько минут.

Очистка и обслуживание системы

Это — ещё одно направление в администрировании Linux-систем, где использование планировщика является частью повседневности. При работе операционной системы, служб и приложений появляются и накапливаются временные файлы, которые создаются при установке, обновлении или обработке данных, и после выполнения своей задачи зачастую становятся бесполезными.

Ниже — пример простенького скрипта, который удаляет из каталога /tmp файлы, не изменявшиеся больше семи дней: 

#!/bin/bash

TMP_DIR="/tmp"

find "$TMP_DIR" -type f -mtime +7 -delete

Такая запись в cron позволит запускать этот скрипт раз в сутки:

0 5 * * * /usr/local/bin/clean_script.sh >/dev/null 2>&1

Можно обойтись и без скрипта, записав команду удаления файлов сразу в cron:

0 5 * * * find /tmp -type f -mtime +7 -delete

То же относится к логам — записям о событиях, ошибках и действиях системы. Логи полезны для диагностики, но со временем становятся слишком объёмными и могут занимать полезное пространство. Так может выглядеть задача по еженедельному удалению старых лог-файлов в директории /var/log. Здесь опция -mtime +30 говорит нам, что необходимо найти и удалить файлы старше тридцати дней: 

0 0 *  0 find /var/log -name ".log" -mtime +30 -exec rm {} \;

Или вот кэш — временное хранилище данных, которое призвано ускорить загрузку приложения, но по прошествии времени в нём накапливается много устаревших и ненужных данных. Пример ниже — ежедневное принудительное удаление содержимого кэш-директории условного приложения app:

15 3 * *  rm -rf /var/cache/app/

Мониторинг и уведомления

Планировщик cron в том числе можно использовать как простейший инструмент мониторинга системы. Например, так можно настроить периодическую отправку отчёта об использовании дискового пространства на электронную почту администратора:

0 */6 * * * df -h | mail -s "Disk Space Report" admin@vash-domain.ru

Правда, чтобы отправка писем действительно работала, сервер нужно заранее настроить — почтовая система должна понимать, куда и каким способом доставлять сообщения.

Мониторинг используется не только как внимательный наблюдатель за состоянием сервисов и процессов. При помощи планировщика и несложного скрипта можно попытаться своевременно, или почти своевременно, поднять упавшую службу. Например, следующим образом каждые 10 минут cron проверяет, запущена ли служба Nginx, и если не запущена — перезапускает её:

*/10 * * * * systemctl is-active --quiet nginx || systemctl restart nginx

Обновления

Классическая задача для cron — обновление бесплатного SSL-сертификата от Let's Encrypt с использованием Certbot. Как правило, такой сертификат выдаётся на 90 дней и перед истечением данного срока его нужно обновить, чтобы сайт продолжал быть доступным через HTTPS. Certbot — это утилита, которая позволяет автоматизировать процесс получения и продления SSL-сертификата от Let's Encrypt. Для проверки срока действия сертификата и его обновления в Certbot используется cron. Официальная документация Let's Encrypt рекомендует запускать проверку дважды в день, что должно гарантировать обновление сертификата даже при временном отсутствии интернета.

0 7,19 * * * certbot renew --quiet --deploy-hook "systemctl reload nginx"

Здесь:

  • certbot renew — команда, которая пытается обновить SSL-сертификаты Let’s Encrypt, срок которых подходит к концу;

  • --quiet — опция, определяющая запуск команд в «тихом» режиме, то есть без вывода сообщений;

  • --deploy-hook — команда, которая выполнится только при успешном обновлении сертификата — перезапустит конфигурацию веб-сервера, в данном случае Nginx, чтобы он применил новый сертификат.

Обработка данных

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

Примером могут послужить ежедневные отчёты, которые необходимо собирать в нерабочее время — до начала или, наоборот, после окончания рабочего дня. Сюда же можно отнести различную периодическую аналитику или статистику за определённый регулярно повторяющийся период. Такой отчёт, как правило, сохраняется в файл для последующей отправки на email, загрузки на файлообменник или ещё куда-либо.

Python-скрипт, допустим, собирает данные из SQLite:

#!/usr/bin/env python3

import sqlite3

import smtplib

from email.mime.text import MIMEText

conn = sqlite3.connect('/data/base.db')

cursor = conn.cursor()

cursor.execute("SELECT SUM(amount), COUNT(*) FROM orders WHERE date > date('now', '-7 days')")

total, count = cursor.fetchone()

conn.close()

Потом формирует текстовый отчёт и отправляет его на электронную почту:

report = f"Продажи за неделю:\nЗаказов: {count}\nСумма: {total} руб."

msg = MIMEText(report)

msg['Subject'] = 'Еженедельный отчёт'

msg['To'] = 'ceo@org.com'

with smtplib.SMTP('localhost') as server:

     server.send_message(msg)

Запуск задачи поручаем cron — в 8 утра каждый понедельник:

0 8 * * 1 /usr/bin/python3 /scripts/weekly.py >> /var/log/reports.log 2>&1

Некоторые полезные команды

Кроме команды crontab -e, упомянутой в самом начале, при работе с планировщиком будут полезны инструменты командной строки, как, например, просмотр текущих задач:

crontab -l

Команда выводит список всех запланированных заданий для текущего пользователя. Удобно, например, для того, чтобы убедиться в корректном добавлении задачи.

Для удаления всех заданий запускаем:

crontab -r

Команда полностью очищает crontab текущего пользователя. Поэтому используйте её осторожно, при выполнении команды не выводится никаких подтверждений.

Команда для просмотра логов cron выглядит как:

grep CRON /var/log/syslog

Вывод показывает записи о событиях при запуске задач cron.

Заключение

Потратив немного времени на настройку и проверку заданий для планировщика, мы получаем отличный бонус — больше не нужно вручную выполнять однообразные задачи и переживать, что что-то пойдёт не так. Теперь всё происходит по расписанию и без лишних нервов.

Так мы постепенно переключаемся с вечного «тушения пожаров» на спокойное, продуманное управление. А своё время наконец можно потратить на то, что действительно требует человеческих мозгов или творчества.

Комментарии (0)