Админим с Буквой
5.52K subscribers
303 photos
8 videos
59 files
1.16K links
Канал о системном администрировании, DevOps и немного Инфобеза.

По всем вопросам обращаться к @bykva. Рекламу не размещаю.
Download Telegram
grep show lines after match

Как пример того, как заставить вывести несколько строчек следющих за той, которую искали:
kubectl describe nodes | grep -A 2 -e "^\\s*CPU Requests"


-A после
-B до
-C с обеих сторон

  CPU Requests  CPU Limits
------------ ----------
550m (55%) 0 (0%)
--
CPU Requests CPU Limits
------------ ----------
360m (36%) 100m (10%)
--
CPU Requests CPU Limits
------------ ----------
0 (0%) 0 (0%)


(output truncated)

#kubernetes #grep
Греп - главный инструмент администратора (с)

Очень часто (и это действительно так) приходится что-то фильтровать. Это может быть все что угодно - логи, конфиги, проекты, чужие наработки - набор данных в которых нужно что-то найти, stdout... Умение пользоваться функционалом программ поиска\фильтрования может порой сэкономить вам кучу времени.

Какие инструменты используются для такой фильтрации?
1) cat - вывести файл на stdout
2) tail - вывести последие n строк из файла
3) less - утилита для просмотра stdout\файла с большим спектром возможностей. как пример - поиск строк по паттерну, введя вот такую конструкцию: /pattern для поиска по документу.
4) | - pipe, конвейер. ну, куда же без него. pipe - перенаправление стандартного потока вывода на стандартный поток ввода. В нашем случае это важный иструмент передачи данных между фильтрами.
5) ack - красочный поиск
6) grep - собственно самый главный инструмент. Тот самый инструмент, который и выполняет основную функцию фильтрования.

Искусство фильтрования кроется в умении объединять эти инструменты через pipe, правильной подаче входных данных на инструмент фильтрования и написание самих фильтров.

Что значит правильная подача данных?
Давайте сразу условимся, что работаем мы не с файлами на 50 строчек, а, например, с логами размером пару десятков гигабайт. Подача данных - это то, что мы отдадим фильтру на вход. Здесь есть несколько вариантов. Вариант первый - мы точно знаем что искать и вариант второй - мы не знаем, что на самом деле ищем. Второй случай - когда мы знаем, что-то происходило в такой-то период. За данный период у нас было несколько сотен тысяч записей. Что же делать? нужно пытаться подавать на вход фильтру ограниченное количество данных, а дальше смотреть глазами на получившийся вывод, стараясь понять какие записи в логах нам точно не нужны, снова фильтровать, исключая эти записи и так до тех пор, пока не останется вменяемо количество информации, которое можно анализировать.

Для подачи информации могут пригодиться команды cat, tail, head:

tail -n 1000 very_big_log | less
cat *.log | less


В первом случае мы подали ограниченное количество информации из конца файла, которую будем анализировать. Следующий этап - выкинуть лишние строчки из вывода. Кроме того, мы можем, например посчитать количество полученных строк после фильтрации, это можно сделать с помощью wc -l Например, это нужно, чтобы посчитать кол-во ошибок одного типа или просто знать сколько строк вы нагрепали:

bzcat error.log.201803290* | grep -v 'upstream prematurely closed connection' | wc -l


Есть еще одно правило, которое гласит "don't pipe cats" - не пропускайте кошек через трубы. Правильнее (и менее трудозатратно) писать так:

bzgrep -v 'upstream prematurely closed connection' error.log.201803290* | less


И так дальше, убирая все больше и больше лишних строк, приходим к нужному результату. За отбрасывание ненужного паттерна отвечает ключ -v.

bzcat error.log.201803290* | grep -v 'upstream prematurely closed connection' | grep -v 'overlimit resources' |less


Также полезно знать и помнить о том, что не всегда логи находятся в открытом виде - иногда могут быть и сжаты разными алгоритмами. Я уже писал про это ранее, но повторюсь:

bzcat, bzgrep, bzless - для алгоритма bzip
zcat, zgrep, zless - для gzip.


Вот простой пример использованая grep для фильтрования веб-трафика (ловим пакеты от нужных url):

tcpdump -i eth1 -A|grep example.com


Одна из немаловажных вещей - умение использовать регулярные выражения при осуществлении поиска. Самый банальный пример - поиск логов в указанный период. для этого нам вновь поможет grep, но здесь о нас заранее позаботились. можно использовать ключ, а можно написать egrep\fgrep. И они такж могут быть скомбинированы с bz\z, например bzegrep.

egrep = grep -E
Interpret PATTERN as an extended regular expression
fgrep = grep -F
Interpret PATTERN as a list of fixed strings (instead of regular expressions), separated by newlines, any of which is to be matched.

Ищем ip-адреса в логах:

egrep '(46.200.110.19|13.104.34.97)' /var/log/nginx/...


#grep
парсим вывод и приводим в нужный вид

Тут в чате прислали ссылку на пример того как человек парсил вывод сайта, чтобы выцепить видео:

$ curl -s "https://www.docker.com/dockercon/2019-videos/" | grep -i -A3  "2019-videos?"  | grep -v "\-\-" | grep -v "img id" | sed 's/<a href="/https:\/\/www.docker.com/g' | sed 's/">//g' | sed 's/<p>//g' | sed 's/<\/p>//g' | sed 'n;G;'

кмк это немножечко не практично. И поэтому в рамках самообучения я решил поднатаскать свои навыки в awk. В итоге получился такой вариант:

curl -s "https://www.docker.com/dockercon/2019-videos/" | \
awk 'match($0, /dockercon\/2019-videos\?watch=.*[a-zA-Z0-9]/) \
{ print "https://www.docker.com/"substr( $0, RSTART, RLENGTH ) } \
{ getline; if ( match($0, /<p>(.*)<\/p>/, m) ){print m[1]"\n"}}'

З.Ы. не являюсь гуру авк, парсинга и прочего. Если у вас есть мнение что мое решение не совсем верно или можно сделать красивее\лаконичнее, прошу вас писать замечения в ЛС (с пруфами) и я обязательно опубликую ваш вариант.

#awk #sed #grep