Что такое скрипты администрирования и зачем они нужны
Ежедневная работа системного администратора и DevOps-инженера складывается из повторяющихся операций: проверить место на диске, забрать бэкап, посмотреть логи Nginx, завести учётную запись. Скрипт администрирования превращает такую цепочку в один исполняемый файл, который запускается по расписанию или вручную и отрабатывает одинаково при каждом старте.
Определение: скрипт администрирования - текстовый файл с командами, который интерпретатор выполняет последовательно. Первая строка задаёт интерпретатор через shebang: #!/bin/bash для Bash, #!/usr/bin/env python3 для Python. Дальше идут команды, проверки состояния, обработка ошибок и логирование.
Ответ на главный вопрос статьи: скрипты закрывают локальные и повторяющиеся задачи на одном-двух серверах, а когда одинаковое состояние нужно поддерживать на десятках машин силами команды, выгоднее декларативные инструменты - Ansible, Puppet, Chef, SaltStack. Скрипт отвечает на вопрос «какие команды выполнить», конфигурационный менеджер - «каким должно быть состояние системы». Критерии выбора, примеры и чек-листы разбираем ниже.
Чем скрипт отличается от ad-hoc команды
Разовая команда в терминале решает задачу здесь и сейчас. df -h показывает заполнение разделов, free -m - свободную память, uptime - время работы и среднюю загрузку, ss -tulpn - слушающие порты. Набирать их руками удобно при диагностике: результат нужен через секунду, сохранять его негде.
Скрипт начинается там, где появляется повторяемость. Три запуска одной и той же команды за неделю, зависимость от времени суток, потребность сохранить вывод и передать задачу коллеге - признаки, что логику пора перенести в файл.
| Критерий | Ad-hoc команда | Скрипт |
|---|---|---|
| Кто запускает | Инженер вручную в терминале | Планировщик, CI или инженер |
| Повторяемость | Набор заново каждый раз | Один и тот же код |
| Обработка ошибок | На усмотрение оператора | set -euo pipefail, trap, exit code |
| Логирование | Только история оболочки | Файл лога или journald |
| Передача коллегам | Скриншот или сообщение в чат | Файл в Git с описанием |
| Проверка перед запуском | Нет | bash -n, shellcheck, dry-run |
Минимальный каркас скрипта: shebang, строгий режим set -euo pipefail, переменные в начале файла, запись лога через exec >> /var/log/task.log 2>&1, осмысленный код возврата. У ad-hoc команды этих частей нет, и это нормально: у неё другая задача и другое время жизни.
Ключевые преимущества скриптов в работе сисадмина
- Время. Один запуск заменяет серию ручных вводов, а расписание избавляет от необходимости помнить о задаче.
- Одинаковый результат. Скрипт не устаёт и не пропускает шаг, если он выполняется в 4 утра.
- Воспроизводимость. Файл переносится на другой сервер и даёт то же поведение.
- Живая документация. Код показывает, какие шаги и в каком порядке нужны для бэкапа или ротации.
- История изменений. Файл в Git хранит, кто и зачем менял логику, а откат занимает одну команду.
- Передача задач. Коллеге достаточно файла и строки запуска вместо устных инструкций.
Долю рутины в процентах не приводим: она зависит от инфраструктуры и различается между командами. Практическая оценка выглядит так: откройте историю команд за неделю и посчитайте повторы. Если одна и та же последовательность встречается три раза, она окупает написание скрипта. Каркас многоэтапного сценария с предусловиями, переменными окружения и постпроверкой разобран в материале про скрипт развертывания: там же таблица различий между идемпотентными и неидемпотентными сценариями.
Типовые сценарии автоматизации: бэкапы, мониторинг, ротация логов, управление пользователями
Четыре задачи закрывают большую часть рутины: резервное копирование, мониторинг, ротация логов и управление учётными записями. Ниже рабочие заготовки на Bash, команды проверки результата и строки для планировщика. Расширенные сценарии с Ansible и Python собраны в гайде по автоматизации администрирования Linux.
Скрипт для бэкапа сервера: пример с rsync и tar
#!/bin/bash set -euo pipefail BACKUP_DIR=/backup SRC=/var/www STAMP=$(date +%F) LOG=/var/log/backup.log exec >> "$LOG" 2>&1 echo "[$(date +%FT%T)] start backup" tar -czf "$BACKUP_DIR/www-$STAMP.tar.gz" "$SRC" tar -tzf "$BACKUP_DIR/www-$STAMP.tar.gz" > /dev/null rsync -az --delete "$BACKUP_DIR/" backup@10.0.0.5:/srv/backups/ find "$BACKUP_DIR" -name 'www-*.tar.gz' -mtime +14 -delete echo "[$(date +%FT%T)] done"
Разбор: set -euo pipefail останавливает скрипт на первой ошибке, tar -tzf читает архив и подтверждает, что он не побился, rsync -az --delete держит удалённую копию в том же состоянии, что и локальную, а find -mtime +14 чистит архивы старше двух недель.
Строка для планировщика: 0 2 * * * /usr/local/bin/backup.sh. Проверка: tar -tzf /backup/www-2026-09-24.tar.gz | head, ls -lh /backup, tail -n 20 /var/log/backup.log.
Для баз данных архива файлов недостаточно. MySQL и MariaDB: mysqldump --single-transaction --routines --triggers app > /backup/app-$(date +%F).sql. PostgreSQL: pg_dump -Fc -f /backup/app.dump app, проверка списка объектов: pg_restore -l /backup/app.dump. Бэкап, который ни разу не восстанавливали, бэкапом не считается: раз в квартал разворачивайте архив на тестовом стенде и сверяйте содержимое. Место контролируйте командой df -h /backup.
Скрипт мониторинга сервера: проверка доступности и ресурсов
#!/bin/bash
set -euo pipefail
source /etc/myapp/secrets.env
THRESH=85
DISK=$(df --output=pcent / | tail -1 | tr -dc '0-9')
LOAD=$(awk '{print $1}' /proc/loadavg)
CODE=$(curl -s -o /dev/null -w '%{http_code}' http://localhost/health)
if [ "$DISK" -ge "$THRESH" ] || [ "$CODE" != "200" ]; then
curl -s -X POST "$ALERT_WEBHOOK" \
--data-urlencode "text=disk=${DISK}% http=${CODE} load=${LOAD}"
fi
Скрипт собирает три сигнала: заполнение корневого раздела через df, load average из /proc/loadavg, код ответа HTTP через curl. Порог 85% и код, отличный от 200, отправляют уведомление в вебхук, адрес которого лежит в файле секретов. Проверка: bash monitor.sh; echo $?.
Для продакшена такой скрипт - быстрый старт, а не замена системе мониторинга. Prometheus с node_exporter, Zabbix, Netdata или алерты облачного провайдера дают историю метрик, дедупликацию и графики. Самописная проверка удобна для того, чего нет в стандартных экспортёрах: бизнес-транзакция, наличие конкретного файла, ответ партнёрского API.
Скрипт ротации логов: альтернатива logrotate
#!/bin/bash
set -euo pipefail
LOG_DIR=/var/log/myapp
find "$LOG_DIR" -type f -name '*.log' -mtime +7 -exec gzip -9 {} \;
find "$LOG_DIR" -type f -name '*.gz' -mtime +30 -delete
logrotate остаётся стандартом: конфиг в /etc/logrotate.d/ описывает daily, rotate 14, compress, delaycompress и postrotate для перезагрузки сервиса, а проверка выполняется командой logrotate -d /etc/logrotate.d/myapp в режиме dry-run. Свой скрипт нужен для нестандартных случаев: приложения пишут в каталоги с датой, файлы лежат вне поддерживаемых шаблонов, имя меняется по расписанию.
Перед сжатием убедитесь, что файл не удерживает процесс: lsof /var/log/myapp/app.log. Удалять активный файл через rm нельзя, рост продолжится через открытый дескриптор, а место не освободится. Размер архивов проверяйте командой du -sh /var/log/myapp.
Скрипт управления пользователями: массовое создание и удаление
#!/bin/bash
set -euo pipefail
for user in $(cat /root/users.txt); do
if id "$user" > /dev/null 2>&1; then
echo "$user уже есть, пропускаем"
continue
fi
useradd -m -s /bin/bash "$user"
passwd -e "$user"
chage -d 0 "$user"
done
Скрипт читает список из файла и пропускает существующих пользователей: проверка через id делает операцию идемпотентной. passwd -e и chage -d 0 требуют смены пароля при первом входе, второй вариант удобнее читать в аудите. Добавление в группы: usermod -aG sudo,docker user1. Удаление: userdel -r user1, перед ним полезно проверить активные процессы через ps -u user1 и завершить их командой pkill -u user1.
Проверка: id user1, getent passwd user1, ls -ld /home/user1. Пароли в файле users.txt хранить нельзя, об этом ниже в разделе про секреты.
Когда скрипт оправдан, а когда пора переходить к конфигурационным менеджерам
Скрипт оправдан, пока задача локальная, состояние легко проверить глазами, а машин одна или две. Признаки, что модель перестала работать: одинаковые правки вносятся на каждой машине отдельно, результат зависит от того, кто и когда запускал файл, проверка состояния занимает больше времени, чем само изменение.
Антипаттерны самописной автоматизации: файл на пятьсот строк с вложенными условиями, дублирование одной логики в cron и в скрипте развёртывания, отсутствие комментариев, скрипт, который нельзя запустить второй раз без побочных эффектов (создаёт дубли пользователей, дописывает строки в конфиг, плодит архивы). Идемпотентность в Bash достигается ручными проверками вида if id "$user" > /dev/null 2>&1 или if [ ! -f /etc/app/config.yml ]. В декларативных инструментах эта проверка встроена в модуль.
Сравнение скриптов и конфигурационных менеджеров: таблица критериев
| Критерий | Скрипт | Ansible, Puppet, Chef |
|---|---|---|
| Модель | Императивная: список команд | Декларативная: описание состояния |
| Идемпотентность | Ручные проверки в коде | Встроена в модули |
| Порог входа | Bash знает любой сисадмин | YAML, инвентарь, модули, основы Python |
| Масштаб | Копия файла на каждый хост | Один playbook на сотни хостов |
| Командная работа | Ревью файла вручную | Роли, окружения, инвентарь, ревью |
| Секреты | Файлы 600, переменные окружения | Vault, внешние хранилища |
| Тестирование | bash -n, shellcheck, bats | check-mode, molecule, dry-run |
| Проверка состояния | Свой код проверок | Факты и отчёт об изменениях |
| Когда выбирать | 1-5 хостов, утилиты, разовые операции | 10+ хостов, типовые роли, гарантия состояния |
Пример из практики: привести Nginx к единому конфигу на десяти серверах скриптом означает десять копий файла, десять запусков и десять вариантов результата. Playbook Ansible с шаблоном и handlers применяет одну роль за один прогон и сообщает, что изменилось. Разбор классов инструментов, включая CMDB-системы аудита и версионирование в Git, есть в статье про инструменты управления конфигурациями.
Чек-лист: 7 признаков, что пора переходить на Ansible, Puppet или Chef
- Больше пяти машин с одинаковым набором сервисов. Копировать один и тот же скрипт на каждую становится отдельной задачей, а расхождения копятся молча.
- Больше часа в неделю уходит на однотипные правки. Время считается по истории задач и коммитов, а не на глаз.
- Нужна гарантия состояния, а не факт запуска. Пакет установлен, сервис запущен и включён в автозапуск, файл содержит нужные строки, а не просто существует.
- Над инфраструктурой работает больше одного человека. Роли и инвентарь делают изменения воспроизводимыми для всей команды.
- Нужна история изменений и откат. Ansible и аналоги хранят конфигурацию в Git рядом с кодом приложения.
- Секреты нужно выдавать централизованно и отзывать. Ansible Vault, внешние хранилища и права по ролям закрывают эту задачу.
- Планируется рост. Новое окружение, staging, второй регион или переход в облако требуют одинакового описания инфраструктуры.
Стартуйте с Ansible: агенты не нужны, доступ по SSH, описание на YAML, готовые модули для пакетов, сервисов, шаблонов и пользователей. Существующие скрипты не выбрасывайте: модули command, shell и script позволяют вызвать их из playbook, а со временем заменить декларативными модулями. Практическое сравнение Ansible, Terraform и Chef по восьми критериям с готовыми сценариями собрано в материале выбор инструмента автоматизации.
Безопасность и надёжность скриптов: как не выстрелить в ногу
Скрипт с root-правами выполняет всё, что в нём написано, включая опечатки. Основные риски: пароли и токены в открытом виде, отсутствие строгого режима, права 777 на файлы с секретами, запуск от root там, где хватает обычного пользователя, чувствительные данные в логах и внешние данные без проверки.
Обработка ошибок и логирование в Bash-скриптах
Три опции в set -euo pipefail закрывают три класса проблем: -e останавливает выполнение при ненулевом коде возврата, -u запрещает обращение к неинициализированным переменным (опечатка в имени переменной не превратится в пустую строку), -o pipefail возвращает ошибку, если упала любая команда в конвейере, а не только последняя.
#!/bin/bash set -euo pipefail TMP=$(mktemp -d) trap 'rm -rf "$TMP"' EXIT exec >> /var/log/myscript.log 2>&1 echo "[$(date +%FT%T)] start"
Строка trap ... EXIT гарантирует уборку временных файлов даже при аварийном завершении. Логирование через exec направляет весь вывод в файл, а tee добавляет дублирование в консоль при ручном запуске.
Проверки до запуска: bash -n script.sh ловит синтаксические ошибки, shellcheck script.sh находит незакавыченные переменные и ошибки в условиях, bash -x script.sh показывает трассировку выполнения по шагам. Скрипты с rm, dd, mkfs и правкой конфигов прогоняйте на staging с теми же путями, что и в проде.
Как безопасно хранить секреты в скриптах
Хардкод пароля означает, что пароль попадёт в Git, в бэкапы и в историю оболочек. Рабочие варианты: файл с правами 600, который читает root, переменные окружения, менеджер секретов (HashiCorp Vault, Ansible Vault, хранилище облака).
install -m 600 -o root -g root /dev/null /etc/myapp/secrets.env printf 'DB_PASS=%s\n' "$DB_PASS" > /etc/myapp/secrets.env # в скрипте source /etc/myapp/secrets.env mysql --defaults-extra-file=/etc/myapp/my.cnf -e 'SHOW DATABASES;'
Передача секрета аргументом командной строки оставляет его в выводе ps aux и в файле /proc/PID/cmdline. Для MySQL берите --defaults-extra-file с конфигом 600, для curl - заголовок из переменной, для ssh - ключ с парольной фразой через агент. Дополнительно выставьте umask 077, чтобы новые файлы создавались закрытыми.
Проверки: stat -c '%a %U %G' /etc/myapp/secrets.env должен вернуть 600 и владельца root, grep -rn 'PASSWORD=' /etc/cron* /etc/systemd/system, history | grep -i pass. В репозитории ведите .gitignore с .env, secrets.env и ключами, а старые утечки ищите командой git log -p | grep -i 'secret'.
Инструменты и окружение для разработки скриптов в 2026 году
Набор инструментов вокруг скриптов устоялся: редактор (VS Code с расширением ShellCheck, vim, neovim), статический анализ shellcheck, форматтер shfmt, тесты bats-core, Git для версий, запуск через cron или systemd timers, автоматическая проверка в CI на каждом pull request. Рабочие примеры на Ansible, Terraform, Bash и Python собраны в практическом гайде по автоматизации инфраструктуры для DevOps и сисадминов.
Bash или Python: что выбрать для скриптов администрирования
Выбор определяется характером задачи. Bash удобен для оркестрации утилит: файловые операции, вызовы rsync и tar, проверки состояния, строки планировщика. Python берёт на себя парсинг JSON и YAML, работу с REST API, сложные структуры данных, расчёты, отправку метрик в несколько систем и тесты.
- Bash есть в базовом образе Debian, Ubuntu, Alpine, RHEL.
- Python требует установки: в минимальных контейнерах его может не быть.
- Проверка места на диске и перезапуск сервиса: Bash, несколько строк.
- Сбор метрик из API облака и запись в базу: Python, модули requests, json, psycopg.
- Скрипт длиннее 150 строк с вложенными условиями и парсингом текста: переписывайте на Python.
Смешанный вариант рабочий: Python выполняет логику, а Bash-обёртка запускает его по расписанию и пишет лог.
Планировщики задач: cron vs systemd timers
cron живёт десятилетиями, прост в синтаксисе и есть везде. Ограничения: нет зависимостей между задачами, разброс выполнения задают вручную, логи уходят в почту или файл настроенного MTA, пропущенный запуск (сервер был выключен) не компенсируется.
systemd timers решают эти задачи: unit-файлы описывают зависимости, journald хранит вывод, Persistent=true догоняет пропущенные запуски, RandomizedDelaySec разносит нагрузку на инфраструктуру.
[Unit] Description=Nightly backup [Service] Type=oneshot ExecStart=/usr/local/bin/backup.sh [Timer] OnCalendar=*-*-* 02:00:00 Persistent=true RandomizedDelaySec=300 [Install] WantedBy=timers.target
Команды проверки: systemctl list-timers --all, journalctl -u backup.service -n 50, systemctl status backup.timer. Для cron: crontab -l, journalctl -u cron -n 20. На современных дистрибутивах берите таймеры, cron оставляйте там, где он уже настроен и работает.
Актуальность в 2026 году: тренды и изменения
Роль скриптов сместилась, но не исчезла. Конфигурацию всё чаще описывают декларативно: Terraform создаёт ресурсы, Ansible настраивает узлы, Argo CD синхронизирует состояние кластера с Git, приложения живут в контейнерах и Kubernetes. Скрипты при этом остаются связующим слоем: bootstrap узла, миграции базы, шаги пайплайна, сборка образов, разовые операции с данными.
Практические следствия для инженера:
- Скрипты всё чаще запускаются в контейнере с зафиксированными версиями утилит, чтобы результат не зависел от дистрибутива хоста.
- Проверка shellcheck и bats в CI стала нормой для репозиториев с инфраструктурным кодом.
- Ветвление по окружениям уходит из скриптов в переменные и инвентарь Ansible или Terraform.
- AI-ассистенты ускоряют написание черновика, а ревью, тесты и понимание последствий остаются на инженере.
- Идемпотентность ожидается от любого кода, который может выполниться дважды.
Навык чтения и написания скриптов остаётся базовым: без него сложно отладить pipeline, разобраться в entrypoint контейнера или починить сервер ночью. Декларативные инструменты не отменяют shell, а надстраиваются над ним.
Заключение: как системно подойти к автоматизации рутины
- Выпишите повторяющиеся задачи за две недели: бэкап, проверка места, ротация логов, создание учётных записей.
- Возьмите одну задачу и оформите её скриптом с shebang, set -euo pipefail и логом.
- Добавьте проверку результата: код возврата, тестовое восстановление архива, echo $? после запуска.
- Пройдите по чек-листу безопасности: права 600 на файлы с секретами, никаких паролей в аргументах, shellcheck без замечаний.
- Посчитайте серверы и участников. Больше пяти машин или больше одного инженера: выбирайте Ansible, Puppet, Chef или SaltStack и переносите повторяемые роли туда.
Начните с одной задачи сегодня: скрипт ротации логов или бэкапа пишется за 20 минут и снимает ручную работу на месяцы. Справочник admin-wiki собран из проверенных на практике инструкций с готовыми конфигами и чек-листами, так что возвращайтесь за следующей задачей.
Источники
- Ansible как инструмент автоматизации инфраструктуры
- systemd-таймеры на практике: OnCalendar, RandomizedDelaySec
- Почему Bash и shell-скрипты всё ещё важны для DevOps-автоматизации
- Порядок ротации журналов безопасности подсистемы (Astra Linux)
- MySQL 8.4 Reference Manual: Command-Line Option Files
- Пособие по Ansible
- Systemd для продолжающих. Part 1 — Запуск юнитов по расписанию
- Использование Logrotate в Linux: как настроить автоматическую ротацию