Будь как дома путник,
Я ни в чём не откажу,
Я ни в чём не откажу,
Я ни в чём не откажу!
Множество историй,
Коль желаешь расскажу,
Коль желаешь расскажу,
Коль желаешь расскажу!

Под звёздами: ответы на вопросы у ночного костра

Ansible, bash и я: три мушкетёра в мире автоматизации управления компьютерами на Linux

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

Но не бойтесь, это не будет сухим перечнем вопросов и ответов.

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

А моими слушателями станут уставшие администраторы и инженеры, которые провели день, блуждая по просторам Хабра в поисках ответов на свои вопросы.

После первой статьи, многие наверное хотели спросить или спросили:

А зачем все это было написано? Много аналогов или инструментов гораздо лучше.

и зачем?
и зачем?

А все очень просто, я писал для начинающих администраторов, которые в глаза не видели linux и его терминал. Они привыкли к окошка и кнопкам далее-далее-готово.
Я же хотел помочь им перейти на Linux, ведь рано или поздно заставят или попросят заняться импортозамещением, а также не стоит забывать о старожилах нашего it-рынка, которые также привыкли к windows и работать с linux им не охота, но в связи с условиями необходимо.

И тут и появился Помогатор, и далее AstraWizard - они написаны для автоматизации рутинных процессов внутри небольших компаний. Где сотрудников it обычно днем с огнем не сыщешь.

Мой кейс: я работал в ВУЗе, и администраторов у нас было 2 человека отвечающих за сотрудников, и 1 администратор отвечающий за студентов. И также около 5-7 человек - anykey'щиков. И вот эти 5-7 человек и страдали больше всех. Им необходимо было устанавливать пакеты на большое количество студенческих ПК под управлением Astra Linux, а знаний им никто не давал. И тут я решил прокачать свои скиллы, и помощь коллегам. Сначала утилита была локальная и устанавливалась на каждый ПК, но им приходилось тогда ходить в каждый класс и нажимать одни и те же кнопки по 100500 раз, и я решил, а почему не сделать ansible под капотом моих bash скриптов?

И тут я подсвечу второй вопрос, который будет содержать два ответа:

Ну почему же проклятый bash, да еще с ansible в придачу?

Bash был изначально всегда со мной, как администратора linux систем и специалиста по информационной безопасности.

  1. Простота и доступность: Bash — это оболочка командной строки, которая предустановлена в большинстве дистрибутивов Linux. Это делает Bash доступным для использования без необходимости установки дополнительных программ.

  2. Интеграция с системой: Bash-скрипты могут взаимодействовать с операционной системой на низком уровне, что позволяет выполнять различные задачи, такие как управление файлами, процессами и сервисами.

  3. Быстрое прототипирование: Bash позволяет быстро создавать и тестировать простые скрипты для автоматизации задач. Это может быть полезно для быстрого решения небольших проблем или тестирования идей.

  4. Поддержка работы с командной строкой: Bash-скрипты могут использовать команды командной строки, что позволяет легко интегрировать их с другими инструментами и программами.

  5. Лёгкость изучения: синтаксис Bash относительно прост и понятен, что делает его доступным для изучения даже для тех, кто не имеет опыта программирования.

  6. Широкая распространённость: Bash является одним из наиболее популярных языков для написания скриптов в среде Linux, что обеспечивает большое количество примеров, документации и сообществ для поддержки.

  7. Гибкость: Bash-скрипты можно использовать для автоматизации практически любых задач, связанных с командной строкой, что делает их универсальными инструментами для системных администраторов и разработчиков.

А почему все таки ansible? Ведь ПК могут быть выключены или недоступны...

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

Однако ansible:

  1. Простота и минимализм. Ansible использует декларативный подход и YAML-формат для описания конфигураций, что делает его простым в изучении и использовании. Нет необходимости в глубоком понимании сложных концепций или синтаксиса.

  2. Отсутствие агентов. Ansible работает по принципу «push», не требуя установки агентов на управляемые узлы. Это упрощает развёртывание и снижает нагрузку на систему.

  3. Идемпотентность. Ansible гарантирует, что выполнение плейбука (сценария) несколько раз приведёт к одинаковому состоянию системы. Это обеспечивает предсказуемость и стабильность конфигураций.

  4. Масштабируемость. Ansible легко масштабируется от нескольких компьютеров до тысяч узлов. Вы можете управлять большими инфраструктурами с помощью одних и тех же инструментов и подходов.

  5. Модульность и расширяемость. Ansible имеет обширную библиотеку модулей, которые можно использовать для автоматизации различных задач. Кроме того, вы можете создавать собственные модули и роли для решения специфических задач.

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

  7. Сообщество и экосистема. Ansible имеет большое и активное сообщество пользователей и разработчиков, которые создают и поддерживают множество ролей, модулей и инструментов, расширяющих функциональность Ansible.

Ну это сухая информация, так почему я выбрал его?

Я изначально управлял серверами на базе Linux и уже привык к нему. Я быстро разворачивал готовые системы, например: nextcloud, zabbix, mattermost и так далее и поэтому мне для дальнейшей поддержки моего приложения удобнее было выбрать то, с чем лично я уже был знаком.

А понимая, что проект буду поддерживать один, то и выбор был очевиден!

AstraWizard раскрывает свои секреты: что под силу новому помощнику двух мушкетёров

Для понимания кому будет полезен мой проект, и что от него ожидать в дальнейшем его развитие и становление, важно подсветить... а что он умеет сейчас?

Групповые политики

  1. Работа с репозиториями

    1. Репозитории frozen 1.7.6

    2. Репозитории frozen 1.7.7

    3. Репозитории frozen 1.8.1

    4. Репозитории frozen 1.8.2

    5. Репозитории stable

    6. Установить репозитории debian 10

    7. Удалить репозитории debian 10

    8. Установить репозитории вручную

    9. Развернуть локальные репозитории на удаленном ПК

    10. Развернуть локальные репозитории на локальном ПК

  2. Работа со службами

    1. Остановка службы

    2. Запуск службы

    3. Перезапуск службы

    4. Добавление службы в автозапуск

    5. Удаление службы из автозапуска

    6. Узнать статус службы

  3. Работа с пакетами

    1. Установка ПО с репозитория

    2. Удаление установленное ПО

    3. Установка deb-пакет по ссылке

    4. Установка deb-пакет скаченный локально

    5. Проверка установлена ли программа

  4. Работа  с Freeipa

    1. Развернуть домен Freeipa

    2. Ввести клиента в домен Freeipa

    3. Развернуть реплику Freeipa

  5. Ввод клиента в домен MS AD

  6. Проверка доступности хостов

  7. Вывести сообщение на экран

  8. Выключить пк

  9. Скопировать файлы на другие пк

  10. Скопировать файл с удаленного пк

  11. Узнать версию ОС на хостах

  12. Обновить систему

  13. Заменить строку в файле на вашу

  14. Сменить обои всем пользователям

  15. Настроить правила монтирования usb

  16. Вывод сообщения о сроке пароля

  17. Выполнить терминальную команду

  18. Запустить bash скрипт

  19. Установка zabbix сервера

  20. Установка zabbix-agent

  21. Установить удаленный доступ

    Инструкции

    1. Меню работа с пакетами

    2. Меню работа со службами

    3. Меню работа с репозиториями

    4. Остальные пункты

    5. Установка сервера Freeipa

    6. Ввод клиента в домен Freeipa

    7. Разворачивание реплики Freeipa

    Настройки

    1. Настройка cтатического списка хостов

    2. Настройка динамического списка хостов на основе домена Freeipa

    3. Настройка динамического списка хостов на сканирования подсети

    4. Настройка логина/пароля для доступа к удаленным хостам

    5. Удаление ssh ключей из базы

    6. Обновить приложение

    7. Посмотреть нововведения

    8. Об авторе

Много пунктов, мало понимания? Продолжим на конкретных интересных примерах.


Вывести сообщение на экран

Эта функция, которая позволяет администратору, со своего рабочего места, где установлен AstraWizard, вывести на на экран сообщение набранное вручную в интерактивное окно, или выбрать файл с текстом с рабочего ПК.

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

Как это реализовано?

Playbook, который запускается под капотом

- hosts: all
  become: true
  gather_facts: false
  tasks:
  - name: скачать скрипт
    copy:
      src: /opt/astrawizard/scripts/text.sh
      dest: /opt/
  - name: скачать текст
    copy:
      src: "{{ lookup('env', 'HOME') }}/astrawizard/message_text"
      dest: /opt/message_text
  - name: права скрипта с сообщением
    file:
      path: /opt/text.sh
      mode: +x
  - name: запуск скрипта
    command: systemd-run /bin/bash /opt/text.sh
  - name: удалить скрипт
    file:
      path: /opt/text.sh
      state: absent
  - name: удалить сообщение
    file:
      path: /opt/message_text
      state: absent

C playbook'ом все понятно, поэтому перейдем подробнее к скрипту bash.
Содержание скрипта text.sh

#!/bin/bash
text=$(cat /opt/message_text)
for i in $(who -u | grep -v pts | awk '{print $1}');
 do
   T=$(who -u | grep -v pts | grep $i | awk '{print $2}')
   homeuser=$(eval echo ~$i)
   echo "Найден пользователь $homeuser - $T"
   systemd-run /bin/bash -c "XAUTHORITY='$homeuser'/.Xauthority DISPLAY='$T' zenity --info --title='Уведомление' --text='$text' --height=200 --width=400"
done

Ну и коротко опишу, что тут происходит:

  1. text=$(cat /opt/message_text) - Эта строка считывает содержимое файла /opt/message_text и сохраняет его в переменную text.

  2. for i in $(who -u | grep -v pts | awk '{print $1}');- Эта строка начинает цикл for, который будет перебирать имена пользователей. Команда who -u  выводит список пользователей, подключённых к системе, с информацией о времени подключения. grep -v pts исключает строки, содержащие pts, что обычно указывает на подключения через терминал. awk '{print $1}' извлекает первое поле каждой строки, которое обычно содержит имя пользователя.

  3. Далее начало цикла для каждого найденного пользователя с активной сессией

  4. T=$(who -u | grep -v pts | grep $i | awk '{print $2}') - Эта строка находит время подключения для текущего пользователя $i. Команда who -u снова выводит список пользователей, grep -v pts исключает терминалы, grep $i фильтрует вывод, чтобы найти строку с именем пользователя $i, а awk '{print $2}' извлекает второе поле, которое содержит дисплей пользовательской сессии.

  5. homeuser=$(eval echo ~$i) - Эта строка получает домашний каталог пользователя $ieval echo ~$i использует eval для расширения имени пользователя до его домашнего каталога.

  6. systemd-run /bin/bash -c "XAUTHORITY='$homeuser'/.Xauthority DISPLAY='$T' zenity --info --title='Уведомление' --text='$text' --height=200 --width=400" - Эта строка запускает команду zenity в отдельном процессе с помощью systemd-runZenity — это инструмент для создания графических диалоговых окон в системах Linux. Здесь он используется для отображения информационного окна с заголовком «Уведомление» и текстом из переменной text. Переменные XAUTHORITY и DISPLAY устанавливаются для корректной работы zenity в графическом окружении.
    P.S. важно уточнить, почему именно systemd-run, если не использовать данную команду, то скрипт покажет окно первому пользователю и будет ждать его завершения, а мои эксперименты с &, тоже не давали успешной реализации сообщения на экране именно всем пользователям.


Установка удаленного доступа

- hosts: all
  gather_facts: false
  become: true
  tasks:
  - name: Установить пакеты x11vnc
    apt:
      name: x11vnc, zenity
      state: present

  - name: Создать ярлык в Пуск
    copy:
      dest: /usr/share/applications/flydesktop/remote_desktop.desktop
      content: |
        [Desktop Entry]
        Name=Удаленный помощник
        Name[ru]=Удаленный помощник
        Type=Application
        Exec=/opt/remote_vnc/x11server.sh
        OnlyShowIn=FLY
        Icon=/opt/remote_vnc/remote-access.png

  - name: Создать ярлык на рабочем столе
    copy:
      dest: /usr/share/applications/flystartmenu/remote_desktop.desktop
      content: |
        [Desktop Entry]
        Name=Удаленный помощник
        Name[ru]=Удаленный помощник
        Type=Application
        Exec=/opt/remote_vnc/x11server.sh
        OnlyShowIn=FLY
        Icon=/opt/remote_vnc/remote-access.png

  - name: Создать папку 
    file:
      path: /opt/remote_vnc
      state: directory
      mode: '0755'
      recurse: yes
      force: yes

  - name: Создать скрипт запуска
    copy:
      dest: /opt/remote_vnc/x11server.sh
      mode: '0755'
      content: |
        #!/bin/bash
        # Получение идентификаторов процессов x11vnc, запущенных от имени текущего пользователя
        pids=$(pgrep -u $(id -u) x11vnc)
        # Завершение всех процессов x11vnc, запущенных от имени текущего пользователя
        if [ -n "$pids" ]; then
          kill $pids
        fi
        # Генерация случайного пароля
        password=$(shuf -i 0-9 -n 6 | tr -d '\n')
        # Запись пароля в файл
        x11vnc -storepasswd "$password" ~/.password_vnc
        # Запуск сервера x11vnc с указанием пароля и получением порта
        x11vnc -rfbauth ~/.password_vnc -auth guess -ncache 10 -o ~/.x11vnc.log -bg &
        # Ожидание запуска x11vnc
        sleep 3
        ip_address=$(hostname -I)
        port=$(cat ~/.x11vnc.log | grep "Autoprobing selected TCP port*" | tail -n 1 | awk '{print $NF}')
        # Вывод порта и пароля
        zenity --info --title="Успех" --text="Рабочий порт $port\n Пароль: $password\n Имя пк: $HOSTNAME\n IP-адрес: $ip_address \n Сообщите данные администратору вашей системы для подключения"

  - name: Скачать иконку приложения
    copy:
      src: /opt/astrawizard/scripts/remote-access.png
      dest: /opt/remote_vnc/remote-access.png


Сам playbook вроде понятен, не буду заострять внимания на нем.
А вот скрипт разберем подробнее.

#!/bin/bash
# Получение идентификаторов процессов x11vnc, запущенных от имени текущего пользователя
pids=$(pgrep -u $(id -u) x11vnc)
# Завершение всех процессов x11vnc, запущенных от имени текущего пользователя
if [ -n "$pids" ]; then
  kill $pids
fi
# Генерация случайного пароля
password=$(shuf -i 0-9 -n 6 | tr -d '\n')
# Запись пароля в файл
x11vnc -storepasswd "$password" ~/.password_vnc
# Запуск сервера x11vnc с указанием пароля и получением порта
x11vnc -rfbauth ~/.password_vnc -auth guess -ncache 10 -o ~/.x11vnc.log -bg &
# Ожидание запуска x11vnc
sleep 3
ip_address=$(hostname -I)
port=$(cat ~/.x11vnc.log | grep "Autoprobing selected TCP port*" | tail -n 1 | awk '{print $NF}')
# Вывод порта и пароля
zenity --info --title="Успех" --text="Рабочий порт $port\n Пароль: $password\n Имя пк: $HOSTNAME\n IP-адрес: $ip_address \n Сообщите данные администратору вашей системы для подключения"

При нажатие на ярлык на рабочем столе происходит:

  1. pids=$(pgrep -u $(id -u) x11vnc) - Получение идентификаторов процессов x11vnc, запущенных от имени текущего пользователя;

  2. Далее функция завершение всех процессов x11vnc, запущенных от имени текущего пользователя;

  3. password=$(shuf -i 0-9 -n 6 | tr -d '\n') - Генерация случайного шестизначного цифрового пароля;

  4. x11vnc -storepasswd "$password" ~/.password_vnc - Запись пароля в файл;

  5. x11vnc -rfbauth ~/.password_vnc -auth guess -ncache 10 -o ~/.x11vnc.log -bg & - Запуск сервера x11vnc с указанием пароля и получением порта;

  6. Sleep - используется для того, чтобы x11vnc успел запуститься, и порт на котором поднялась служба записалась в переменную;

  7. Далее получаем ip-адрес ПК и порт, на котором запустился сервер x11vnc

  8. В конце пользователю выводиться на рабочий стол информация, которую надо сообщить администратору для подключения к его сессии:

    1. Рабочий порт для подключения;

    2. Пароль для подключения;

    3. Имя ПК и ip-адрес ПК.


Развернуть локальные репозитории на удаленном ПК или Развернуть локальные репозитории на локальном ПК

Обычная и тривиальная задача для пользователя знакомого с терминалом и работой с iso файлами, но если вы администратор Linux и никогда не делали никакие там репозитории, и тем более через apache/nginx или ftp.

Тогда у вас 2 пути:
- Читать инструкцию и надеется, что все получиться;
- Использовать AstraWizard, который делает всею инструкцию автоматически, а вам лишь остается загрузить файл в графическое окно и выбрать протокол http или ftp.

Если выбор пал на AstraWizard, то тут все просто, есть playbook, куда передаются значения, которые пользователь выбрал в GUI и также указывается путь до iso, если необходимо развернуть на удаленной машине.

Из минусов, что iso будет передаваться по сети, и это достаточно медленно, но окей для небольших компаний.

- hosts: all
  gather_facts: false
  become: true
  vars:
    choose_system: "{{ choose_system }}"
  tasks:
  - name: Установить значение переменной
    set_fact:
      remote_host: "{{ ansible_host }}"
  - name: Скопировать iso в папку /opt/
    copy:
      src: "{{ path_to_iso }}"
      dest: /opt/
  - name: Создать папку /srv/repo/
    file:
      path: "/srv/repo/{{ name_dir_repo }}"
      state: directory
      mode: '0755'
      recurse: yes
      force: yes
  - name: Создать папку /media/cdrom
    file:
      path: /media/cdrom
      state: directory
      mode: '0755'
      force: yes
  - name: Примонтировать файл
    command: mount "/opt/{{ path_to_iso | basename }}" /media/cdrom
  - name: Скопировать пакеты 
    shell: cp -a /media/cdrom/* /srv/repo/{{ name_dir_repo }}
  - name: Unmount a mounted volume
    command: umount /media/cdrom

  - name: Выбрали apache2
    block:
      - name: Установка и настройка apache2
        apt:
          name: apache2
          state: present
      - name: создание ссылки на папку
        command: ln -s /srv/repo /var/www/html/
        ignore_errors: yes
      - name: Проверить наличие строки в файле /etc/apache2/sites-enabled/000-default.conf
        command: grep -q "<Directory /var/www/html/repo>" /etc/apache2/sites-enabled/000-default.conf
        register: grep_result
        changed_when: false
        ignore_errors: true 
      - name: Дописать в /etc/apache2/sites-enabled/000-default.conf
        command: sed -i '/DocumentRoot \/var\/www\/html/a \ \ \ \ <Directory \/var\/www\/html\/repo>\n \ \ \ \ \ \ Options Indexes MultiViews FollowSymLinks\n \ \ \ \ \ \ AllowOverride None\n \ \ \ \ \ \ Order Deny,Allow\n \ \ \ \ \ \ Require all granted\n \ \ \ \ <\/Directory>' /etc/apache2/sites-enabled/000-default.conf
        when: grep_result.rc != 0    
      - name: Измнение AstraMode on
        command: sed -i 's/# AstraMode on/AstraMode off/g'  /etc/apache2/apache2.conf
      - name: Настройка apache2
        service:
          name: apache2
          state: restarted
    

      - name: Проверить файл /Desktop/sources.list
        local_action:
          module: file
          path: "{{ lookup('env', 'HOME') }}/Desktop/sources.list"
          state: touch
      - name: Записать результаты в файл /Desktop/sources.list
        local_action:
          module: lineinfile
          path: "{{ lookup('env', 'HOME') }}/Desktop/sources.list"
          line: deb http://{{ remote_host }}/repo/{{ name_dir_repo }} stable main contrib non-free   


    when: choose_system == 'apache2'

  - name: Выбрали ftp
    block:
      - name: Установка и настройка apache2
        apt:
          name: vsftpd
          state: present
      - name: Измнение listen=NO/listen=yes
        command: sed -i 's/listen=NO/listen=yes/g'  /etc/vsftpd.conf 
      - name: Измнение listen_ipv6=YES/listen_ipv6=no
        command: sed -i 's/listen_ipv6=YES/listen_ipv6=no/g'  /etc/vsftpd.conf 
      - name: Измнение anonymous_enable=NO/anonymous_enable=YES
        command: sed -i 's/anonymous_enable=NO/anonymous_enable=YES/g'  /etc/vsftpd.conf                 
      - name: Измнение local_enable=YES/local_enable=no
        command: sed -i 's/local_enable=YES/local_enable=no/g'  /etc/vsftpd.conf

      - name: Проверить наличие строки anon_root=/srv/repo в файле /etc/vsftpd.conf
        command: grep -q "anon_root=/srv/repo" /etc/vsftpd.conf
        register: grep_result
        changed_when: false
        ignore_errors: true 
      - name: Дописать строку anon_root=/srv/repo в конец файла
        lineinfile:
          path: /etc/vsftpd.conf
          line: "anon_root=/srv/repo"
        when: grep_result.rc != 0  

      - name: Проверить наличие строки в no_anon_password=yes файле /etc/vsftpd.conf
        command: grep -q "no_anon_password=yes" /etc/vsftpd.conf
        register: grep_result
        changed_when: false
        ignore_errors: true 
      - name: Дописать строку no_anon_password=yes в конец файла123
        lineinfile:
          path: /etc/vsftpd.conf
          line: "no_anon_password=yes"
        when: grep_result.rc != 0

      - name: Проверить наличие строки в hide_ids=yes файле /etc/vsftpd.conf
        command: grep -q "hide_ids=yes" /etc/vsftpd.conf
        register: grep_result
        changed_when: false
        ignore_errors: true 
      - name: Дописать строку hide_ids=yes в конец файла
        lineinfile:
          path: /etc/vsftpd.conf
          line: "hide_ids=yes"
        when: grep_result.rc != 0

      - name: Настройка vsftpd
        service:
          name: vsftpd
          state: restarted     

      - name: Проверить файл /Desktop/sources.list
        local_action:
          module: file
          path: "{{ lookup('env', 'HOME') }}/Desktop/sources.list"
          state: touch
      - name: Записать результаты в файл /Desktop/sources.list
        local_action:
          module: lineinfile
          path: "{{ lookup('env', 'HOME') }}/Desktop/sources.list"
          line: deb ftp://{{ remote_host }}/{{ name_dir_repo }} stable main contrib non-free   

    when: choose_system == 'ftp'

Предвещая комментарии по поводу:

почему ты не используешь fqcn в ansible - это же best practice

Когда зарождался проект, в ALSE использовалась старая версия ansible. И пока не хватает времени именно на красоту в проекте.

Руководство по портированию Ansible 2.10

В Ansible 2.10 многие плагины и модули были перенесены в Collections на Ansible Galaxy . Ваши плейбуки должны продолжать работать без каких-либо изменений. Мы рекомендуем вам начать использовать полное имя коллекции (FQCN) в ваших плейбуках как явный и авторитетный индикатор того, какую коллекцию использовать, поскольку некоторые коллекции могут содержать дублирующиеся имена модулей. Вы можете выполнить поиск по индексу всех модулей , чтобы найти коллекцию, в которую был перемещен модуль.

Грядет новое... Продолжение зовёт!

Будь как дома путник, Я ни в чём не откажу, Я ни в чём не откажу, Я ни в чём не откажу!
Множество историй, Коль желаешь расскажу, Коль желаешь расскажу, Коль желаешь расскажу!

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


  1. LexD1
    05.07.2025 08:19

    Неуместно пафосное начало\конец (I.M.H.O.).

    Возможно, за это первые два минуса.


    1. MikeyTide Автор
      05.07.2025 08:19

      Да я знаю что площадка хабр цениться своими ценителями и оценщиками.

      Ведь главное не содержимое статьи , а то что человек написал во вступление.


      1. LexD1
        05.07.2025 08:19

        Сарказм?

        За необоснованное употребление мягкого знака (-ться\тся) тоже могут минусануть. И за пробел перед запятой.


        1. MikeyTide Автор
          05.07.2025 08:19

          Ну странно имхо это все.

          А так ну оценка не главное, главное чтобы люди кто и до этого пользовался проектом поняли его суть


          1. LexD1
            05.07.2025 08:19

            Ничего странного, это Хабр.

            По сути. Ansible обязательно? Для небольшого количества машин (домашняя локальная сеть) хватит и одного bash?

            Мне интересно самому написать нужные сценарии, пусть даже это будет "изобретением велосипеда".


            1. MikeyTide Автор
              05.07.2025 08:19

              Ansible использовал чтобы админы не ходили ножками на 100500 компов.

              А так все мои плейбуки можно переписать под баш и использовать чисто их.

              То есть просто кладем баш на тачку заходим по ссш и запускаем и все


              1. LexD1
                05.07.2025 08:19

                +.

                Уточнил на всякий.


            1. MikeyTide Автор
              05.07.2025 08:19

              Первый проект помогатор, был полностью на bash.

              Исходники у меня в гите также есть


  1. Tamerlan666
    05.07.2025 08:19

      - name: Примонтировать файл
        command: mount "/opt/{{ path_to_iso | basename }}" /media/cdrom
      - name: Скопировать пакеты 
        shell: cp -a /media/cdrom/* /srv/repo/{{ name_dir_repo }}

    Серьезно? :)


    1. MikeyTide Автор
      05.07.2025 08:19

      ?

      То, что я не использовать модуль ?


  1. Tamerlan666
    05.07.2025 08:19

          - name: создание ссылки на папку
            command: ln -s /srv/repo /var/www/html/
            ignore_errors: yes
          - name: Проверить наличие строки в файле /etc/apache2/sites-enabled/000-default.conf
            command: grep -q "<Directory /var/www/html/repo>" /etc/apache2/sites-enabled/000-default.conf
            register: grep_result
            changed_when: false
            ignore_errors: true 
          - name: Дописать в /etc/apache2/sites-enabled/000-default.conf
            command: sed -i '/DocumentRoot \/var\/www\/html/a \ \ \ \ <Directory \/var\/www\/html\/repo>\n \ \ \ \ \ \ Options Indexes MultiViews FollowSymLinks\n \ \ \ \ \ \ AllowOverride None\n \ \ \ \ \ \ Order Deny,Allow\n \ \ \ \ \ \ Require all granted\n \ \ \ \ <\/Directory>' /etc/apache2/sites-enabled/000-default.conf
            when: grep_result.rc != 0    
          - name: Измнение AstraMode on
            command: sed -i 's/# AstraMode on/AstraMode off/g'  /etc/apache2/apache2.conf

    Вы решили поставить рекорд по количеству антипаттернов в статье с примерами кода Ansible?


    1. MikeyTide Автор
      05.07.2025 08:19

      ?

      То что я не кладу готовый кофеин в правлю его на удаленной тачке ?