Linux Bash Shell читает файл журнала, сравнивает каждую строку со сбросом файла - PullRequest
0 голосов
/ 13 сентября 2018

У меня есть этот действительно большой файл журнала аутентификации.Я связал его с необходимой мне информацией с помощью команд SED и AWK.Теперь мне нужно выполнить сопряжение, когда пользователь подключается и когда он отключается от сервера, чтобы регистрировать, как долго и в какое время пользователи входили в систему.

В журнале, когда пользователь входит в систему, вы можете увидеть его имя пользователя и IP-адрес.порт.Когда они выходят из системы, все, что вы можете видеть, это IP-порт.Поэтому мне нужно сопоставить эти IP-порты, а затем выплеснуть информацию из линии, к которой они подключены.

Файл журнала выглядит следующим образом:

Date,time,Username,Viewer,IPPort <br>
20180911,12:00,Chris,New,55567 <br>
20180911,12:30,Tom,New,55577                  <<<<<-Connections <br>
20180911,12:45,Larry,New,55587 <br>
20180911,14:00,,,55567 <br>
20180911,15:30,,,55577                 <<<<<-When user logs off <br>
20180911,16:45,,,55587 <br>

Моей первой мыслью было бы использоватьвложенный цикл while.Итак, перейдите к каждой строке, а затем, находясь в этой строке, снова пройдитесь по каждой строке, чтобы найти совпадения.Это проходит по файлу и сопоставляет вещи, но перепроверяет верхнюю строку против себя во вложенном цикле.Должен быть более ясный способ сделать это.

Вот так выглядит мой цикл в настоящее время.

INPUT=firstreport.csv
OLDIFS=$IFS
IFS=,
[ ! -f $INPUT ] && { echo "$INPUT file not found"; exit 99; }
while read Date Time Username Viewer IP
do
        echo "IP : $IP"
        IPCHECK=$IP
        while read Date Time Username Viewer IP
    do
    if [[ $IPCHECK == $IP ]]; then
    echo "Match : $IP"
    fi


    done < $INPUT
done < $INPUT
IFS=$OLDIFS`

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

Спасибо, Крис

Ответы [ 3 ]

0 голосов
/ 13 сентября 2018

Замена внутреннего цикла следующим образом:

line=0
while read Date Time Username Viewer IP COMMENT
do
  let line=1+$line
  awk -F "$IFS" '
    BEGIN {
      IP="'${IP}'"
      if(!match(IP, "^[0-9]+$")) {exit}
      line='"${line}"'
    }
    NR<line { next }
    NR==line {
      print "CONNECT:",$0
      next
    }
    $5==IP && $4 != "New" {
      print "DISCONNECT:", $0
      exit
    }
    $5==IP {
      print "FOUND RECONNECT BEFORE DISCONNECT"
      exit
    }
  ' $INPUT
done < $INPUT

И немного изменив ввод, чтобы он выглядел так:

20180911,12:00,Chris,New,55567,
20180911,12:30,Tom,New,55577, <<<<<-Connections 
20180911,12:45,Larry,New,55587, 
20180911,14:00,,55567, 
20180911,15:30,,55577, <<<<<-When user logs off 
20180911,16:45,,55587, 
20180911,16:45,Tom,New,55577, <<<<<-reconnect
20180911,16:45,55577, <<<<<-redisconnect
20180911,16:45,CURLY,New,55577, <<<<<-reconnect
20180911,16:45,MOE,New,55577, <<<<<- foobar
20180911,16:45,55577, <<<<<-redisconnect

Даёт это:

CONNECT: 20180911,12:00,Chris,New,55567,
DISCONNECT: 20180911,14:00,,55567, 
CONNECT: 20180911,12:30,Tom,New,55577, <<<<<-Connections 
DISCONNECT: 20180911,15:30,,55577, <<<<<-When user logs off 
CONNECT: 20180911,12:45,Larry,New,55587, 
DISCONNECT: 20180911,16:45,,55587, 
CONNECT: 20180911,16:45,Tom,New,55577, <<<<<-reconnect
FOUND RECONNECT BEFORE DISCONNECT
CONNECT: 20180911,16:45,CURLY,New,55577, <<<<<-reconnect
FOUND RECONNECT BEFORE DISCONNECT
CONNECT: 20180911,16:45,MOE,New,55577, <<<<<- foobar

Что я думаю, это то, что вы хотите. Я подозреваю, что в ваших реальных данных вам нужно будет добавить больше условных выражений, чтобы убедиться, что пользователи и порты имеют смысл.

Сложным способом было бы сделать это (весь скрипт) на python или perl и использовать многострочное регулярное регулярное выражение.

**** Обратите внимание, что скрипт awk обновлен, но ввод / вывод по-прежнему оригинален

0 голосов
/ 13 сентября 2018

Это GNU awk:

gawk '
    BEGIN { FS = OFS = "," }
    NR == 1 {next}
    $3 != "" { # connection
        conn[$5]["on"] = $3 FS $4 FS $1 FS $2
    }
    $3 == "" {
        if ($5 in conn) {
            conn[$5]["off"] = $1 FS $2
        }
        else {
            print "Error: found a log off with no log on, line " NR
        }
    }
    END {
        print "IPPort","User","Viewer","ON date","ON time","OFF date","OFF time"
        for (id in conn) {
            print id, conn[id]["on"], conn[id]["off"]
        }
    }
' file
IPPort,User,Viewer,ON date,ON time,OFF date,OFF time
55567,Chris,New,20180911,12:00,20180911,14:00
55577,Tom,New,20180911,12:30,20180911,15:30
55587,Larry,New,20180911,12:45,20180911,16:45

для старых awk (протестировано с )

awk '
    BEGIN { FS = OFS = "," }
    NR == 1 {next}
    $3 != "" { ids[$5]; conn[$5,"on"] = $3 FS $4 FS $1 FS $2 }
    $3 == "" {
        if ($5 in ids)
            conn[$5,"off"] = $1 FS $2
        else
            print "Error: found a log off with no log on, line " NR
    }
    END {
        print "IPPort","User","Viewer","ON date","ON time","OFF date","OFF time" 
        for (id in ids)
            print id, conn[id,"on"], conn[id,"off"]
    }
' file
0 голосов
/ 13 сентября 2018

Учитывая, что зарегистрированные порты достаточно уникальны и что они всегда регистрируются в 5-м столбце, как описано в комментариях, вы сможете использовать следующую команду sort, чтобы сгруппировать записи по портам, перегруппировав всю информацию.о подключении пользователя:

sort -t, -k 5,5

В этой команде sort мы используем опцию -t,, чтобы указать, что поля разделяются запятыми, затем мы используем -k 5,5, чтобы задать sort для сортировкитолько 5-е поле.

(Примечание: в комментариях я предложил использовать -k 5.1, что означает сортировку по первому символу 5-го поля, но 1) смещение символа .x по умолчанию соответствует первому / последнему символуполя для начальной / конечной позиции и могут быть пропущены; 2) у вас может быть больше полей, чем опубликовано в выписке, которые без необходимости использовались бы в сортировке, если бы поле конца не было указано)

Примененок вашему примеру ввода исправлено, чтобы сделать порт 5-м полем в записях выхода из системы:

20180911,12:00,Chris,New,55567
20180911,12:30,Tom,New,55577
20180911,12:45,Larry,New,55587
20180911,14:00,,,55567
20180911,15:30,,,55577
20180911,16:45,,,55587

Он производит следующеевывод:

20180911,12:00,Chris,New,55567
20180911,14:00,,,55567
20180911,12:30,Tom,New,55577
20180911,15:30,,,55577
20180911,12:45,Larry,New,55587
20180911,16:45,,,55587

Вы можете попробовать здесь .

...