Вопрос или проблема
Я пытаюсь извлечь дату и IP-адрес из вывода lastb
Я использую: lastb | awk '{print $5,$6,$7,$3}'
Проблема в том, что иногда первый столбец (userID) в lastb
пустой:
Пример данных:
wpsadmin ssh:notty 213.109.202.127 Tue Oct 1 12:07 - 12:07 (00:00) ssh:notty 8.219.222.66 Tue Oct 1 11:48 - 11:48 (00:00) quser ssh:notty 213.109.202.127 Tue Oct 1 11:03 - 11:03 (00:00) udatabas ssh:notty 139.19.117.130 Tue Oct 1 10:34 - 10:34 (00:00) Admin ssh:notty 213.109.202.127 Tue Oct 1 09:58 - 09:58 (00:00) ssh:notty 79.110.62.93 Tue Oct 1 09:40 - 09:40 (00:00) udatabas ssh:notty 139.19.117.130 Tue Oct 1 09:34 - 09:34 (00:00)
…что смещает мои переменные awk на одну позицию.
Поэтому использование: lastb | awk '{print $5,$6,$7,$3}'
для приведенного набора данных дает мне:
Oct 1 12:07 213.109.202.127 1 11:48 - Tue Oct 1 11:03 213.109.202.127 Oct 1 10:34 139.19.117.130 Oct 1 09:58 213.109.202.127 1 09:40 - Tue Oct 1 09:34 139.19.117.130
Как мне это исправить? Спасибо!
Чтобы смоделировать вызов lastb
OP:
$ cat lastb.out
wpsadmin ssh:notty 213.109.202.127 Tue Oct 1 12:07 - 12:07 (00:00)
ssh:notty 8.219.222.66 Tue Oct 1 11:48 - 11:48 (00:00)
quser ssh:notty 213.109.202.127 Tue Oct 1 11:03 - 11:03 (00:00)
udatabas ssh:notty 139.19.117.130 Tue Oct 1 10:34 - 10:34 (00:00)
Admin ssh:notty 213.109.202.127 Tue Oct 1 09:58 - 09:58 (00:00)
ssh:notty 79.110.62.93 Tue Oct 1 09:40 - 09:40 (00:00)
udatabas ssh:notty 139.19.117.130 Tue Oct 1 09:34 - 09:34 (00:00)
Один общий подход:
- нам нужно определить, следует ли распечатать поля
5,6,7,3
или поля4,5,6,2
5,6,7,3
то же самое, что и(5-0),(6-0),(7-0),(3-0)
4,5,6,2
то же самое, что и(5-1),(6-1),(7-1),(3-1)
- мы можем обобщить это на
(5-offset),(6-offset),(7-offset),(3-offset)
, гдеoffset
равно0
или1
- мы можем проверить атрибуты первого поля, чтобы определить значение
offset
Несколько идей awk
на основе различных атрибутов первого поля:
########
# определяем смещение по содержимому первого поля
awk '
{ offset = ( $1 ~ /ssh:/ ) ? 1 : 0 # если первое поле содержит строку "ssh:", то смещение = 1, иначе смещение = 0
print $(5-offset),$(6-offset),$(7-offset),$(3-offset) # применяем смещение, чтобы определить, какие поля печатать
}'
########
# определяем смещение по позиции первого поля в строке
awk '
{ offset = ( index($0,$1) != 1 ) ? 1 : 0 # если первое поле не начинается с первого столбца, то смещение = 1, иначе смещение = 0
print $(5-offset),$(6-offset),$(7-offset),$(3-offset)
}'
Другой подход – это вставить ‘заменяющее’ поле в начало строки, когда первое поле ‘отсутствует’.
Одна идея awk
, использующая атрибут index($0,$1)
:
awk '
{ $1 = (index($0,$1)==1 ? "" : "placeholder" FS) $1 # если первое поле начинается с первого столбца, то заменяющее не нужно, иначе добавляем перед первым полем строку "placeholder"
$0=$0 # заставляем awk повторно разобрать новую строку; поскольку теперь у всех строк одинаковое количество полей ...
print $5,$6,$7,$3 # не нужно смещение
}'
Удалив комментарии, сведя к однострочным выражениям и считывая вывод lastb
из stdin:
cat lastb.out | awk '{offset = ($1~/ssh:/) ? 1 : 0; print $(5-offset),$(6-offset),$(7-offset),$(3-offset)}'
cat lastb.out | awk '{offset = (index($0,$1)!=1) ? 1 : 0; print $(5-offset),$(6-offset),$(7-offset),$(3-offset)}'
cat lastb.out | awk '{$1 = (index($0,$1)==1 ? "" : "placeholder" FS) $1; $0=$0; print $5,$6,$7,$3}'
Все эти команды генерируют:
Oct 1 12:07 213.109.202.127
Oct 1 11:48 8.219.222.66
Oct 1 11:03 213.109.202.127
Oct 1 10:34 139.19.117.130
Oct 1 09:58 213.109.202.127
Oct 1 09:40 79.110.62.93
Oct 1 09:34 139.19.117.130
Вместо проверки атрибутов первого поля, вы могли бы (по крайней мере, для предоставленных образцов данных) проверить количество полей (NF
):
NF==9
==> 9 полей: мы ‘теряем’ первое поле, поэтому мы устанавливаемoffset=1
или добавляемplaceholder
в начало строкиNF==10
==> 10 полей: мы устанавливаемoffset=0
или не добавляем ничего в начало строки
Ответ или решение
Ваша проблема заключается в том, что при парсинге вывода команды lastb
с помощью awk
, когда поле идентификатора пользователя (userID) пустое, смещаются ваши переменные, что приводит к неправильной интерпретации данных. В данном ответе мы рассмотрим, как можно решить эту задачу.
Проблема
Команда lastb
выводит информацию о неудачных входах в систему и может содержать строки, где поле с идентификатором пользователя пустое. Это приводит к тому, что команда awk '{print $5,$6,$7,$3}'
, которая считает, что каждый элемент расположен в строго определенных позициях, не срабатывает как задумано.
Пример вывода
Рассмотрим следующий пример:
wpsadmin ssh:notty 213.109.202.127 Tue Oct 1 12:07 - 12:07 (00:00)
ssh:notty 8.219.222.66 Tue Oct 1 11:48 - 11:48 (00:00)
quser ssh:notty 213.109.202.127 Tue Oct 1 11:03 - 11:03 (00:00)
В данном примере, когда поле идентификатора пользователя пустое, ваши переменные в awk
смещаются на одну позицию. Это приводит к тому, что при парсинге данное поведение приводит к неправильной интерпретации строк.
Решение
Для решения данной проблемы мы можем использовать подход с определением смещения (offset). Это позволит корректно извлекать данные из строк, независимо от наличия поля идентификатора пользователя.
Пример команд awk
Вы можете использовать следующий скрипт для обработки вывода:
lastb | awk '
{
offset = ($1 ~ /^[[:space:]]*$/) ? 1 : 0; # Определяем смещение на основе наличия первого поля
print $(5-offset), $(6-offset), $(7-offset), $(3-offset);
}'
Этот код делает следующее:
- Проверяет, является ли первое поле пустым (содержит ли только пробелы).
- В зависимости от результата проверки устанавливает значение смещения.
- Извлекает необходимые поля, корректно обрабатывая их в зависимости от установленного смещения.
Альтернативный подход
Еще один метод — это добавление "заполнительного" поля в начале строки, когда первое поле отсутствует:
lastb | awk '
{
if ($1 ~ /^[[:space:]]*$/) {
$1 = "placeholder";
}
print $5, $6, $7, $3;
}'
При таком подходе вы просто добавляете заполнитель, что позволяет awk
корректно считать количество полей в каждой строке.
Заключение
Предложенные выше решения помогут эффективно парсить вывод команды lastb
, избегая проблем, связанных со смещением полей. Выбор подхода зависит от специфики ваших данных и личных предпочтений. Оба метода обеспечивают правильный вывод необходимой информации, включая дату и IP-адрес.
Таким образом, руководствуясь вышеизложенными рекомендациями, вы сможете успешно обрабатывать выходные данные команды и извлекать нужную информацию без ненужных ошибок.