Нужна помощь со скриптом

Автор CoolAller, 18 ноября 2023, 16:34:40

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

CoolAller

Здравствуйте.
Не могу понять почему не получается перенаправить вывод в файл. Идея такая, нужно получать ip адреса из лога dnsmasq. Настройки для dnsmasq:

/etc/dnsmasq.conf:
listen-address=127.0.0.1
bind-interfaces
cache-size=1000
log-queries
log-facility=/var/log/dnsmasq.log

/etc/resolv.conf:
nameserver 127.0.0.1
nameserver 8.8.8.8

При запуске команды:
sudo tail -n 0 -f /var/log/dnsmasq.log | grep --line-buffered nnmclub.to | awk '{if ($8 ~ /^[0-9]/ && $8 != "127.0.0.1" && $8 != "8.8.8.8") print $8}'

Выводятся ip адреса:
188.114.96.1
188.114.97.1
188.114.97.1
188.114.96.1
2a06:98c1:3120::1
2a06:98c1:3121::1

Но если я пытаюсь перенаправить вывод в файл, то в файл ничего не пишется. Тоже самое происходит, если я пытаюсь отфильтровать уникальные ip адреса и вывести их в терминал.

sudo tail -n 0 -f /var/log/dnsmasq.log | grep --line-buffered nnmclub.to | awk '{if ($8 ~ /^[0-9]/ && $8 != "127.0.0.1" && $8 != "8.8.8.8") print $8}' > output.txt
sudo tail -n 0 -f /var/log/dnsmasq.log | grep --line-buffered nnmclub.to | awk '{if ($8 ~ /^[0-9]/ && $8 != "127.0.0.1" && $8 != "8.8.8.8") print $8}' | sort | uniq
Может кто-нибудь помочь?

ChubaDuba

#1
Не понятно почему:
tail -n 0 ...
По умолчанию выводятся последние десять строк.
-n number, где number - количество строк, которое нужно взять с конца файла.
Пример :
Если делаем
$ lsusb > lsusb.txt
$ tail -n 0 lsusb.txt > tail.txt
то tail.txt пустой
делаем:
$ tail -n 3 lsusb.txt > tail.txt
то tail.txt содержит три последние строчки из lsusb.txt



SerW

Короче, у вас выводятся адреса, в которых присутствует `8`.
Сергей Швайко » DragonSerW

CoolAller

#3
Цитата: ChubaDuba от 19 ноября 2023, 19:26:55Не понятно почему:
tail -n 0 ...
Эта команда выводит последние 0 строк из файла лога и затем продолжает мониторить его в реальном времени (-f), отображая новые строки, когда они добавляются.

Цитата: SerW от 19 ноября 2023, 20:52:07Короче, у вас выводятся адреса, в которых присутствует `8`.

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

Всем спасибо за помощь, решил вопрос по-другому.

ChubaDuba, классная аватарка)

SerW

> Всем спасибо за помощь, решил вопрос по-другому.

И, конечно же, решением не поделитесь.
Как обычно всё в Интернете :-)
Сергей Швайко » DragonSerW

CoolAller

#5
SerW, я просто думал, что кроме меня это никому неинтересно)

Описанная проблема, связана с буферизацией ввода/вывода команд в конвейере. В awk по умолчанию включена буферизация вывода. Буферизированные данные не сразу передаются из одной команды в другую в режиме реального времени. Если попытаться сохранить вывод в переменную, это приведет к тому, что данные не передаются немедленно и поэтому sort и uniq не будут работать в режиме реального времени. Утилита tail ожидает получение новых данных, поэтому ее вывод также будет динамическим.

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

Можно использовать команду fflush() в awk, чтобы принудительно сбросить буфер после каждой строки и записать вывод в файл:
tail -n 0 -f /var/log/dnsmasq.log | grep --line-buffered yandex.ru | awk '{if ($8 ~ /^[0-9]/ && $8 != "127.0.0.1" && $8 != "8.8.8.8") { print $8; fflush(); }}' > output.txt

Поскольку, вывод в файл выглядит костыльным решением, поэтому было сделано через массив awk, в который разбивается строка переменной domains по пробелам, затем по шаблону, который срабатывает, если в строке присутствует "reply" и последующий IP-адрес, то происходит итерация по массиву domain_array для сопоставления домена IP-адресу:

    tail -n 0 -f "$LOG_FILE" | awk -v domains="$DOMAINS" -v vpn_interface="$VPN_INTERFACE" -v log_update_file="$LOG_UPDATE_FILE" '
    function add_route(domain, ip) {
        if (system("ip route | grep -q " ip) != 0) {
            if (system("ip route add " ip "/32 dev " vpn_interface) == 0) {
                print "Added route for " domain " (" ip ")"
            }
        }
    }

    BEGIN {
        split(domains, domain_array, " ")
    }

    /reply.*is/ && /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ {
        for (i in domain_array) {
            domain_pattern = domain_array[i]
            gsub(/\*/, ".*", domain_pattern)  # Заменяем * на .* для учета масок
            if ($0 ~ domain_pattern) {
                split($0, arr, " ")
                for (j in arr) {
                    if (arr[j] ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) {
                        ip = arr[j]
                        add_route(domain_pattern, ip)
                    }
                }
            }
        }

Этот скрипт awk служит для отслеживания определенных строк в файле журнала и, при необходимости, добавляет маршруты в таблицу маршрутизации на основе распознанных данных.