Получите самое длинное время входа в систему для данного пользователя с помощью awk

Моя задача состоит в том, чтобы написать сценарий bash, используя awk, чтобы найти самый длинный вход в систему данного пользователя («все еще вошедший в систему» ​​не считается) и напечатать monthdayIPlogon time in minutes.

Пример ввода:./scriptname.sh username1

Содержание last username1:

username1       pts/        IP      Apr     2       ..      ..      ..      ..      (00.03)

username1       pts/        IP      Apr     3       ..      ..      ..      ..      (00.13)

username1       pts/        IP      Apr     5       ..      ..      ..      ..      (12.00)

username1       pts/        IP      Apr     9       ..      ..      ..      ..      (12.11)

Пример вывода:

Apr9IP731 (пояснение: 12 часов и 11 минут — всего 731 минута)

Я написал этот скрипт, но выскакивает куча ошибок, и я совсем запутался:

#!/bin/bash

usr=$1

last $usr | grep -v "still logged in" | awk 'BEGIN {max=-1;}
                                                {
                                                h=substr($10,2,2);
                                                min=substr($10,5,2) + h/60;
                                                }
                                                (max < min){
                                                max = min;
                                                }
                                                END{
                                                maxh=max/60;
                                                maxmin=max-maxh;
                                                ($maxh == 0 && $maxmin >=10){
                                                        last $usr | grep "00:$maxmin" | awk '{print $5," ",$6," ", $3," ",$maxmin}'
                                                        exit 1
                                                }
                                                ($maxh == 0 $$ $maxmin < 10){
                                                        last $usr | grep "00:0$maxmin" | awk '{print $5," ",$6," ",$3," ",$maxmin}'
                                                        exit 1
                                                }
                                                ($maxh < 10 && $maxmin == 0){
                                                        last $usr | grep "0$maxh:00" | awk '{print $5," ",$6," ",$3," ",$maxmin}'
                                                        exit 1
                                                }
                                                ($maxh < 10 && $maxmin < 10){
                                                        last $usr | grep "0$maxh:0$maxmin" | awk '{print $5," ",$6," ",$3," ",$maxmin}'
                                                        exit 1
                                                }
                                                ($maxh >= 10 && $maxmin < 10){
                                                        last $usr | grep "$maxh:0$maxmin" | awk '{print $5," ",$6," ",$3," ",$maxmin}'
                                                        exit 1
                                                }
                                                ($maxh >=10 && $maxmin >= 10){
                                                        last $usr | grep "$maxh:$maxmin" | awk '{print $5," ",$6," ",$3," ",$maxmin}'
                                                        exit 1
                                                }
                                                }'

Итак, небольшое объяснение того, как я себе это представлял:

После инициализации я хочу найти столбец (hh:mm) команды last $usr, сохранить h и min каждой строки, найти наибольшее число (в минутах, то есть это самое долгое время входа в систему).

После того, как я нашел самое длинное время входа в систему (в минутах, сохраненное в переменной max), мне нужно переформатировать единственный формат минут в hh:mm, чтобы иметь возможность использовать grep, снова использовать последнюю команду, но теперь только поиск строки (s), которые содержат max время входа в систему, и распечатать всю необходимую информацию в формате monthdayIPlogon time in minutes, используя другой awk.

Ошибки, которые я получаю при запуске этого кода: Куча синтаксических ошибок, когда я пытаюсь использовать grep и awk внутри оригинального awk.

Ваш код будет легче читать, если вы не сделаете отступ в своем awk-скрипте на 50 пробелов или что-то еще, и вы сделаете отступ блоков кода внутри {...} [airs.

Ed Morton 23.04.2022 15:06
редактировать ваш вопрос, чтобы сообщить нам, каким должен быть вывод, если пользователь входил в систему дважды в течение одной и той же самой продолжительной продолжительности каждый раз, но в разные даты или с разных IP-адресов (первый? последний? оба? что-то еще?). Кроме того, покажите другой IP-адрес в вашем примере, а не просто говорите «IP», чтобы мы могли видеть, КАКОЙ IP-адрес печатается в выводе.
Ed Morton 23.04.2022 15:12

Поскольку ваша первоначальная команда grep по конвейеру удаляет строку, содержащую still logged in, она должна быть доступна в вашем вводе, поэтому, пожалуйста, редактировать ваш вопрос, чтобы включить подобную строку в ваш пример ввода. Также покажите нам, каким должен быть вывод, если для данного пользователя нет ввода для обработки.

Ed Morton 23.04.2022 15:25
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
0
3
73
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Если в этом примере file содержит содержимое примера, а последний столбец содержит вход в систему:

awk '
match ($(NF), /\(([0-9]+)\.([0-9]+)\)/, a) {
  hm = (a[1] * 60) + a[2]
  if(hm > max) {max = hm; line = $0;}
}
END {
  n = split(line,a,/[[:space:]]+/)
  print a[3], a[4], a[5], max
}
' file

Выход

IP Apr 9 731

@EdMorton Я предположил, что чтение 12.11 означает «expl: 12 часов и 11 минут, всего 731 минута». Тем не менее, это действительные точки в ваших комментариях, но я изменил их на реализацию с использованием gnu-awk с шаблоном и группами захвата (хотя ваш ответ читается как солнечный свет в пасмурный день)

The fourth bird 23.04.2022 18:05

Ах, вы правы в часах и минутах, моя ошибка, я неправильно понял, что ОП имел в виду под logon time in minutes в начале вопроса - они описывают вывод, а не ввод.

Ed Morton 23.04.2022 23:12
Ответ принят как подходящий

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

Используя любой awk в любой оболочке на каждом компьютере Unix и предполагая, что если несколько строк имеют максимальное время, которое вы хотите, чтобы все они были напечатаны, и что, если строки с отметкой времени не найдены, вы хотите напечатать что-то вроде No matching records (легкая настройка, если нет, просто сообщите нам ваши требования для этих случаев и включите их в пример вашего вопроса):

last username1 |
awk '
    /still logged in/ {
        next
    }
    {
        split($NF,t,/[().]/)
        cur = (t[2] * 60) + t[3]
    }
    cur >= max {
        out = ( cur > max ? "" : out ORS ) $4 OFS $5 OFS $3 OFS cur
        max = cur
    }
    END {
        print (out ? out : "No matching records")
    }
'
Apr 9 IP 731

Благодарю вас! не могли бы вы объяснить синтаксис «ORS» и «OFS»? Кроме того, как? : операторы работают (это делают это ? fnc иначе : fnc ) ?

David Gall 23.04.2022 16:10

Пожалуйста. ORS и OFS определены на справочной странице и руководстве awk, см. gnu.org/software/gawk/manual/gawk.html#Output-Separators, а ? : — это просто тернарный оператор, как и во многих языках, см. https://en.wikipedia.org/wiki/%3F:. Дайте мне знать, если у вас возникнут какие-либо конкретные вопросы после прочтения этих ссылок.

Ed Morton 23.04.2022 16:22

Тестирование команды last на моей машине:

Использование Red Hat Linux 7.8 Получил следующий вывод:

user0022 pts/1        10.164.240.158   Sat Apr 25 19:32 - 19:47  (00:14)
user0022 pts/1        10.164.243.80    Sat Apr 18 22:31 - 23:31 (1+01:00)
user0022 pts/1        10.164.243.164   Sat Apr 18 19:21 - 22:05  (02:43)
user0011 pts/0        10.70.187.1      Thu Nov 21 15:26 - 18:37  (03:10)
user0011 pts/0        10.70.187.1      Thu Nov  7 16:21 - 16:59  (00:38)
astukals pts/0        10.70.187.1      Mon Oct  7 19:10 - 19:13  (00:03)
reboot   system boot  3.10.0-957.10.1. Mon Oct  7 22:09 - 14:30 (156+17:21)
astukals pts/0        10.70.187.1      Mon Oct  7 18:56 - 19:08  (00:12)
reboot   system boot  3.10.0-957.10.1. Mon Oct  7 21:53 - 19:08  (-2:-44)
IT       pts/0        10.70.187.1      Mon Oct  7 18:50 - 18:53  (00:03)
IT       tty1                          Mon Oct  7 18:48 - 18:49  (00:00)
user0022 pts/1        30.30.30.168     Thu Apr 16 09:43 - 14:54  (05:11)
user0022 pts/1        30.30.30.59      Wed Apr 15 11:48 - 04:59  (17:11)
user0022 pts/1        30.30.30.44      Tue Apr 14 19:03 - 04:14  (09:11)

Найденный формат времени DD+HH:MM появляется только тогда, когда DD не равен нулю.

Найдены дополнительные технические пользователи: IT, system, reboot нужно отфильтровать.

Предлагаемое решение:

last | awk 'BEGIN {FS="[ ()+:]*"}
/reboot|system|still/{next}
{ print $5 OFS $6 OFS $3 OFS $(NF-1) + ($(NF-2) * 60) + ($(NF-3) * 60 * 24)}
' |sort -nk 4| head -1

Результат:

Apr 15 30.30.30.59 85991

Другие вопросы по теме