--- - name: Сбор инвентаря Windows (Nmap SMB + DNS) hosts: localhost connection: local gather_facts: yes vars: inventory_file: "/tmp/windows_inventory2.ini" # Список подсетей subnets: - "192.168.0.0/24" - "192.168.1.0/24" - "192.168.2.0/24" - "192.168.3.0/24" - "172.19.8.0/23" - "172.19.9.0/23" - "172.19.10.0/23" - "172.19.24.0/23" - "172.19.26.0/23" - "172.19.40.0/23" - "172.19.42.0/23" - "172.19.56.0/23" - "172.19.58.0/23" # Порты для проверки доступности (WinRM, SSH, SMB) scan_ports: - 5985 - 22 - 445 tasks: - name: Сканирование сети (поиск живых IP) command: > nmap -p {{ scan_ports | join(',') }} -Pn -n --open --min-rate 1000 -T4 -oG - {{ subnets | join(' ') }} register: nmap_result changed_when: false - name: Извлечение IP адресов set_fact: active_ips: "{{ nmap_result.stdout | regex_findall('Host: ([0-9.]+).*Ports:.*(?:' + scan_ports | join('|') + ')/open') | unique | list }}" - name: Статистика debug: msg: "Найдено активных IP: {{ active_ips | length }}" # ГЛАВНОЕ ИЗМЕНЕНИЕ: Получаем имя через SMB (NetBIOS) или DNS - name: Определение имен хостов (SMB Discovery) shell: | IP="{{ item }}" # 1. Пробуем узнать имя через SMB (самый надежный способ для Windows) SMB_NAME=$(nmap -p 445 --script smb-os-discovery $IP -Pn -n | grep "Computer name:" | awk -F': ' '{print $2}') if [ ! -z "$SMB_NAME" ]; then echo "$SMB_NAME" | tr '[:upper:]' '[:lower:]' else # 2. Если SMB закрыт/не ответил, пробуем DNS (как раньше) DNS_NAME=$(nslookup -timeout=1 $IP 192.168.1.250 2>/dev/null | grep 'name =' | awk '{print $NF}' | sed 's/\.$//' | head -n 1) if [ ! -z "$DNS_NAME" ]; then echo "$DNS_NAME" | tr '[:upper:]' '[:lower:]' else echo "UNKNOWN" fi fi loop: "{{ active_ips }}" register: host_names changed_when: false no_log: true # Чтобы не засорять лог # Фильтруем и готовим списки - name: Сортировка хостов set_fact: # Ищем 'pc' в любом месте имени (было ^pc - только в начале) pc_list: >- {{ host_names.results | selectattr('stdout', 'search', 'pc') | map(attribute='item') | list | zip(host_names.results | selectattr('stdout', 'search', 'pc') | map(attribute='stdout') | list) | list }} # Остальные (сервера, принтеры, неизвестные) other_list: >- {{ host_names.results | rejectattr('stdout', 'search', 'pc') | map(attribute='item') | list | zip(host_names.results | rejectattr('stdout', 'search', 'pc') | map(attribute='stdout') | list) | list }} - name: Запись инвентаря copy: content: | # === Найденные PC (по имени содержит 'pc') === [windows_pcs] {% for ip, name in pc_list %} {{ name }} ansible_host={{ ip }} {% endfor %} # === Остальные устройства (Servers, Unknown) === [windows_other] {% for ip, name in other_list %} {% if name == "UNKNOWN" %} unknown_{{ ip | replace('.', '_') }} ansible_host={{ ip }} {% else %} {{ name }} ansible_host={{ ip }} {% endif %} {% endfor %} [windows:children] windows_pcs windows_other [windows:vars] ansible_connection=winrm ansible_winrm_transport=ntlm ansible_winrm_server_cert_validation=ignore ansible_port=5985 ansible_user=Administrator # Пароль лучше задать в Secret Store, не здесь dest: "{{ inventory_file }}" - name: ПОКАЗАТЬ РЕЗУЛЬТАТ (Скопируйте это в новый инвентарь) command: cat {{ inventory_file }} register: cat_inventory changed_when: false - name: Вывод в лог debug: var: cat_inventory.stdout_lines