Ответ
Главный и самый критичный минус — нарушение принципа идемпотентности. Ansible построен на идее, что плейбук можно запускать многократно, приводя систему к одному и тому же желаемому состоянию. Модули shell и command этого не гарантируют.
Они просто выполняют заданную команду в оболочке, не анализируя текущее состояние системы. Это приводит к побочным эффектам.
Плохой пример (неидемпотентный):
- name: Add entry to config file
ansible.builtin.shell: "echo 'ServerName localhost' >> /etc/apache2/apache2.conf"
При каждом запуске плейбука эта строка будет добавляться в файл заново, дублируясь.
Хорошая практика (идемпотентный модуль):
- name: Ensure entry exists in config file
ansible.builtin.lineinfile:
path: /etc/apache2/apache2.conf
line: 'ServerName localhost'
state: present
Модуль lineinfile проверит наличие строки и добавит её только если её нет.
Другие недостатки shell/command:
- Сложность обработки вывода: Вывод — простой текст, для его парсинга нужны фильтры
registerиstdout_lines. Специализированные модули возвращают удобный JSON. - Потенциальные проблемы с безопасностью: Необходимо вручную экранировать переменные с помощью фильтра
quote, чтобы избежать инъекций. - Меньшая переносимость: Команда, работающая в bash, может не сработать в sh или другой оболочке. Специализированные модули абстрагируют это.
Я использую shell/command только в крайних случаях, когда нет подходящего идемпотентного модуля, и всегда оборачиваю логику в проверки creates, removes или changed_when для имитации идемпотентности.