Ad-hoc команды для быстрых задач

Урок 6 - выполняем разовые задачи без playbook через ad-hoc команды.

«Не всё стоит писать в playbook. Иногда нужно просто перезапустить сервис на всех серверах - прямо сейчас».

Ad-hoc команда - это разовый запуск одного модуля без playbook. Она удобна для быстрых операций: проверить связь, посмотреть аптайм, установить пакет, перезапустить сервис. Формат: ansible <группа> -m <модуль> -a "<аргументы>".

Полезные примеры

# Узнать uptime всех веб-серверов
ansible web -m command -a "uptime"

# Установить пакет (нужны права root, поэтому --become)
ansible web -m ansible.builtin.apt -a "name=htop state=present" --become

# Перезапустить nginx на всех веб-серверах
ansible web -m ansible.builtin.service -a "name=nginx state=restarted" --become

# Собрать все факты об одном хосте
ansible web1.example.com -m setup

Флаг --become повышает права через sudo - он нужен для действий, требующих root (установка пакетов, управление сервисами). Модуль command просто выполняет команду (без shell-возможностей вроде пайпов), setup - собирает факты о хосте.

Как работает под капотом

Ad-hoc команда - это, по сути, playbook из одной задачи, который Ansible собирает на лету. Он раскрывает группу в хосты, для каждого устанавливает SSH-соединение, копирует указанный модуль с аргументами, выполняет, собирает результат. Разница с playbook только в том, что описание задачи ты передал прямо в командной строке, а не в файле.

Смоделируем, как Ansible применяет один модуль к группе хостов и собирает сводку changed/ok.

# Применяем ad-hoc "service restart" к группе и считаем сводку
web_hosts = ["web1", "web2", "web3"]

def restart_service(host, service):
    # имитация: сервис всегда переводится в restarted -> это change
    return {"host": host, "service": service, "changed": True, "state": "restarted"}

results = [restart_service(h, "nginx") for h in web_hosts]

changed = sum(1 for r in results if r["changed"])
print(f"web : ok={len(results)}  changed={changed}")
for r in results:
    print(f"  {r['host']}: {r['service']} -> {r['state']}")

Попробуй сам ▶ Каждый рестарт - это changed, потому что «перезапустить» - всегда действие. А вот state=started у уже запущенного сервиса вернул бы ok без изменений: разница между «обеспечь запущенность» и «перезапусти» - важная и про идемпотентность.

Частые ошибки

  • Забыть --become. Установка пакетов и управление сервисами требуют root. Без повышения прав - «Permission denied».
  • Использовать command там, где нужен shell. Модуль command не понимает пайпы, перенаправления и переменные окружения - для них есть shell (но злоупотреблять им не стоит).
  • Делать через ad-hoc то, что повторяется. Если команда нужна регулярно - её место в playbook под git, а не в истории терминала.

Best practices

  • Ad-hoc - для разовых операций и диагностики. Повторяемое - в playbook.
  • Предпочитай специализированные модули (service, apt) сырому command - они идемпотентны.
  • Модуль setup - твой друг при отладке: показывает все факты, которые можно использовать в шаблонах.

В реальной работе

Ad-hoc команды незаменимы в инцидентах. Упал сервис на десяти серверах в три часа ночи - одной командой ansible web -m service -a "name=nginx state=restarted" --become ты поднимаешь его везде сразу, не заходя на каждую машину руками. Так же быстро собирают диагностику: ansible all -m command -a "df -h" покажет свободное место на всех дисках парка. Но есть железное правило: если ты выполнил ad-hoc команду дважды - значит, она повторяется, и её место в playbook под git. Ad-hoc - это скальпель для разовых операций и расследований, а не замена воспроизводимой автоматизации.

Итоги

Ad-hoc команды позволяют быстро выполнить один модуль на группе хостов без playbook - идеально для диагностики и разовых действий. Для root-операций нужен --become. Повторяющееся лучше оформить в playbook, к которому мы переходим дальше.

Проверьте себя
1. Зачем в ad-hoc команде установки пакета нужен флаг --become?
AЧтобы ускорить выполнение
BЧтобы повысить права до root через sudo - установка пакетов требует прав суперпользователя
CЧтобы включить отладочный режим
DЧтобы команда выполнилась на всех хостах
2. В чём разница между state=started и state=restarted у модуля service?
AНикакой, это синонимы
Bstarted обеспечивает запущенность (идемпотентно), restarted всегда перезапускает (всегда changed)
Crestarted работает быстрее
Dstarted требует root, а restarted нет