15%

Збережіть 15% на всі хостинг-послуги

Перевірте свої навички і отримайте Знижку на будь-який план хостингу

Використовуй код:

Skills
Почати
23.10.2024

Як використовувати команду `grep` для пошуку інформації у файлах

Команда grep — скорочення від Global Regular Expression Print — це утиліта Unix/Linux, яка сканує один або кілька файлів рядок за рядком і виводить кожен рядок, що відповідає заданому шаблону. Вона є стандартом де-факто для пошуку тексту в будь-якій POSIX-сумісній системі та підтримує як базові, так і розширені регулярні вирази, що дозволяє знаходити збіги від простого рядка до складних багатосимвольних шаблонів.

Якщо вам потрібна найкоротша відповідь: виконайте grep "pattern" filename для пошуку у файлі, додайте -r для рекурсивного пошуку в дереві каталогів, -i для пошуку без урахування регістру та -n для відображення номерів рядків поряд із результатами. Наведені нижче розділи охоплюють значно більше: реальні робочі процеси, проблеми з продуктивністю та розширені техніки регулярних виразів, які більшість посібників повністю оминають.

Що насправді робить grep під капотом

grep читає вхідні дані рядок за рядком і застосовує до кожного рядка скінченний автомат, похідний від вашого регулярного виразу. Реалізація GNU (стандартна в Linux) використовує алгоритм Boyer-Moore-Horspool для літеральних рядків і конструкцію Thompson NFA для шаблонів регулярних виразів. Саме ця архітектура пояснює, чому grep надзвичайно швидко працює з великими файлами — він уникає зворотного відстеження, на відміну від інструментів на основі PCRE, таких як perl або python.

У сімействі GNU coreutils існують три окремі бінарні файли:

КомандаРушійВаріант використання
grepBRE / ERE (з -E)Пошук збігів рядків загального призначення
egrepERE (розширені регулярні вирази)Скорочення для grep -E
fgrepЛише фіксовані рядкиНайшвидший; без інтерпретації регулярних виразів
zgrepBRE / ERE для стиснутих файлівАрхіви .gz, .bz2
pgrepПошук збігів імен процесівШукає в таблиці процесів, а не у файлах

egrep та fgrep є застарілими псевдонімами в сучасних системах; у скриптах для забезпечення переносимості надавайте перевагу grep -E та grep -F відповідно.

Базовий синтаксис

grep [options] pattern [file ...]
  • pattern — рядок або регулярний вираз, взятий у лапки
  • file — один або кілька шляхів до файлів; пропустіть для читання зі стандартного введення
  • options — прапорці, що змінюють поведінку пошуку збігів, формат виведення або продуктивність

Мінімальний приклад, що знаходить кожен рядок зі словом "error" у syslog:

grep "error" /var/log/syslog

Завжди беріть шаблон у лапки. Шаблони без лапок, що містять метасимволи оболонки (*, ?, [, $), будуть розгорнуті оболонкою до того, як grep їх побачить, що призведе до мовчазних некоректних результатів.

Основні параметри, які повинен знати кожен адміністратор

Пошук у кількох файлах і каталогах

Перелічіть файли явно або використовуйте глобінг оболонки:

grep "error" access.log error.log debug.log
grep "error" *.log

Для пошуку в усьому дереві каталогів використовуйте -r (слідкуйте за символічними посиланнями за допомогою -R):

grep -r "error" /var/log/

Застереження: На виробничих серверах із глибоко вкладеними ієрархіями журналів необмежений -r може споживати значний обсяг вводу/виводу. Обмежте область пошуку за допомогою --include, щоб уникнути сканування бінарних файлів або нерелевантних розширень:

grep -r --include="*.log" "error" /var/log/

Пошук без урахування регістру (-i)

grep -i "error" application.log

Це знаходить збіги для error, Error, ERROR, eRrOr та будь-якої іншої комбінації регістрів. Внутрішньо GNU grep з -i перетворює і шаблон, і вхідні дані на нижній регістр перед порівнянням, що додає невеликі накладні витрати на дуже великих файлах.

Відображення номерів рядків (-n)

grep -n "error" application.log

Приклад виведення:

25:error occurred during processing
103:error: connection refused

Номери рядків незамінні, коли потрібно перейти безпосередньо до збігу в редакторі: vim +25 application.log відкриває файл на рядку 25.

Підрахунок збігів (-c)

grep -c "error" application.log

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

grep -c "error" *.log
access.log:0
debug.log:14
error.log:3

Інвертований пошук (-v)

grep -v "error" application.log

Повертає кожен рядок, який не відповідає шаблону. Практичне застосування: видалення рядків коментарів із файлу конфігурації перед передачею його далі по конвеєру:

grep -v "^#" /etc/nginx/nginx.conf | grep -v "^$"

Це видаляє як рядки коментарів (що починаються з #), так і порожні рядки, залишаючи лише активні директиви.

Пошук цілих слів (-w)

grep -w "error" application.log

Без -w пошук error також знаходив би збіги для errors, error_code та myerror. Прапорець -w прив’язує збіг до меж слів, визначених як переходи між символами слів ([a-zA-Z0-9_]) і символами, що не є символами слів.

Обмеження кількості рядків виведення (-m)

grep -m 5 "error" application.log

grep припиняє читання файлу після знаходження 5 рядків зі збігами. У файлі журналу розміром 10 ГБ, де потрібно лише підтвердити наявність шаблону, -m 1 може скоротити час виконання з секунд до мілісекунд, оскільки grep завершує роботу одразу після першого збігу.

Рядки контексту (-A, -B, -C)

Одна з найменш використовуваних функцій. При діагностиці помилки навколишні рядки часто містять першопричину:

grep -A 3 "error" application.log   # 3 lines After the match
grep -B 3 "error" application.log   # 3 lines Before the match
grep -C 3 "error" application.log   # 3 lines of Context (before and after)

Це різниця між тим, щоб побачити error: connection refused і побачити повний стек викликів або попередній запит, що спричинив помилку.

Підсвічування кольором (--color)

grep --color=auto "error" application.log

Більшість дистрибутивів встановлюють alias grep='grep --color=auto' у /etc/profile.d/ або ~/.bashrc. Використовуйте --color=always при передачі в less -R для збереження ANSI-кодів:

grep --color=always "error" application.log | less -R

Виведення лише частини рядка, що збігається (-o)

За замовчуванням grep виводить весь рядок зі збігом. Прапорець -o виводить лише ту частину рядка, яка відповідає шаблону:

grep -o "192.[0-9]*.[0-9]*.[0-9]*" access.log

Це витягує кожну IPv4-адресу з журналу доступу — по одній адресі на рядок виведення — що ідеально підходить для передачі в sort | uniq -c | sort -rn для пошуку найактивніших клієнтів.

Придушення виведення імені файлу (-h) та його примусове відображення (-H)

При пошуку в кількох файлах grep додає ім’я файлу перед кожним збігом. -h придушує це; -H примусово відображає навіть при пошуку в одному файлі. Використовуйте -H у скриптах для гарантованого однакового формату виведення незалежно від кількості переданих файлів.

Виведення лише імен файлів (-l та -L)

grep -l "error" *.log    # files that contain the pattern
grep -L "error" *.log    # files that do NOT contain the pattern

Корисно в скриптах розгортання для визначення файлів конфігурації, що посилаються на застарілий параметр.

Регулярні вирази з grep

Базові регулярні вирази (BRE)

grep за замовчуванням використовує BRE. Ключові метасимволи:

МетасимволЗначенняПриклад
^Початок рядкаgrep "^error" — рядки, що починаються з "error"
$Кінець рядкаgrep "error$" — рядки, що закінчуються на "error"
.Будь-який одиночний символgrep "err.r" — збігається з "error", "errar" тощо
*Нуль або більше попередніхgrep "err*" — "er", "err", "errr" тощо
[abc]Клас символівgrep "[aeiou]" — будь-яка голосна
[^abc]Заперечений класgrep "[^0-9]" — будь-який нецифровий символ
Екранування метасимволуgrep "." — літеральна крапка

У BRE символи +, ?, {, }, (, ) та | повинні бути екрановані зворотною косою рискою, щоб сприйматися як метасимволи. Це є поширеним джерелом плутанини при переключенні між BRE та ERE.

Розширені регулярні вирази (ERE) з -E

grep -E "error|failure|critical" application.log

ERE робить синтаксис чистішим — +, ?, |, () та {} працюють без зворотних косих рисок:

grep -E "err(or|ata)?" application.log       # matches "err", "error", "errata"
grep -E "[0-9]{1,3}.[0-9]{1,3}" access.log  # partial IP pattern
grep -E "^(ERROR|WARN|FATAL)" app.log        # lines starting with severity levels

Perl-сумісні регулярні вирази (PCRE) з -P

GNU grep підтримує PCRE через прапорець -P, що відкриває доступ до випереджальних та ретроспективних перевірок і нежадібних квантифікаторів:

grep -P "(?<=user=)w+" auth.log    # extract username after "user="
grep -P "d{4}-d{2}-d{2}" app.log # ISO date format

Важливо: -P є розширенням GNU і недоступний у BSD grep (стандартний на macOS). Скрипти, що використовують -P, не є переносимими без встановлення GNU grep (brew install grep на macOS).

Пошук у стиснутих файлах за допомогою zgrep

Ротація журналів зазвичай стискає старіші журнали за допомогою gzip. zgrep дозволяє шукати в них без ручного розпакування:

zgrep "error" /var/log/syslog.2.gz

Для файлів .bz2 використовуйте bzgrep. Для файлів .xz використовуйте xzgrep. Якщо потрібно шукати одночасно в стиснутих і нестиснутих журналах однією командою:

zgrep -r "error" /var/log/

Крайній випадок: zgrep внутрішньо викликає zcat для розпакування, а потім передає дані в grep. Він не підтримує всі прапорці grep. Якщо вам потрібні -P або -o для стиснутих файлів, спочатку розпакуйте їх у тимчасовий файл або використовуйте zcat file.gz | grep -P "pattern".

Поєднання grep з іншими командами

Справжня потужність grep проявляється при його поєднанні з іншими утилітами через конвеєри.

Фільтрація виведення процесів

ps aux | grep "[n]ginx"

Трюк із дужками [n]ginx запобігає появі самого процесу grep в результатах, оскільки шаблон [n]ginx не збігається з літеральним рядком [n]ginx у списку процесів.

Витягування та агрегування даних журналів

grep "error" application.log | sort | uniq -c | sort -rn | head -20

Цей конвеєр: знаходить усі рядки з помилками, сортує їх, підраховує унікальні входження, повторно сортує за частотою у спадному порядку та показує 20 найпоширеніших помилок. Це техніка першочергового сортування при будь-якому виробничому інциденті.

Пошук файлів, що містять шаблон, з подальшими діями над ними

grep -rl "deprecated_function" /var/www/html/ | xargs sed -i 's/deprecated_function/new_function/g'

grep -rl виводить список файлів, що містять шаблон; xargs передає їх у sed для заміни на місці. Завжди спочатку тестуйте без -i або використовуйте -i.bak для створення резервних копій.

Пошук через SSH

ssh user@server "grep -r 'error' /var/log/app/" | less

Ви можете запустити grep на віддаленому сервері та передавати результати до свого локального терміналу — корисно, коли файли журналів занадто великі для передачі.

Поєднання з awk для структурованого розбору

grep "POST /api" access.log | awk '{print $1, $7, $9}'

grep фільтрує відповідні рядки; awk витягує конкретні поля (IP, URL, код статусу). Ця комбінація вирішує більшість завдань аналізу журналів без потреби у спеціалізованій платформі агрегації журналів.

Міркування щодо продуктивності

На великих файлах або при частій автоматизації ці оптимізації мають значення:

  • Використовуйте -F для літеральних рядків. grep -F "exact string" повністю обходить компіляцію регулярних виразів і є помітно швидшим.
  • Використовуйте LC_ALL=C. Встановлення LC_ALL=C grep "pattern" file примушує до обробки в однобайтовій локалі, що може бути в 2–5 разів швидше на UTF-8 файлах, оскільки пропускає обробку багатобайтових символів.
  • Уникайте -r на мережевих файлових системах. Рекурсивний grep через NFS або CIFS може насичувати мережевий вввід/вивід. Натомість використовуйте find з -exec та явним обмеженням шляху.
  • Використовуйте --mmap на Linux. grep --mmap використовує відображення пам’яті замість системних викликів read(), що зменшує накладні витрати на великих файлах (доступно не на всіх платформах).
  • Паралелізуйте за допомогою xargs -P. Для пошуку в багатьох незалежних файлах розподіліть навантаження:
find /var/log -name "*.log" | xargs -P 4 grep -l "error"

Це запускає 4 процеси grep паралельно, використовуючи кілька ядер CPU.

grep порівняно з альтернативними інструментами пошуку

ІнструментШвидкість на великих репозиторіяхПідтримка регулярних виразівВраховує `.gitignore`Найкраще для
grepПомірнаBRE/ERE/PCREНіСистемні файли, журнали, скриптинг
ripgrep (rg)Дуже швидкаPCRE2ТакПошук коду в репозиторіях
ag (Silver Searcher)ШвидкаPCREТакПошук коду, старша альтернатива rg
ackПомірнаPCREЧастковоКодові бази, орієнтовані на Perl
fgrep / grep -FНайшвидшаВідсутня (лише літерали)НіСканування журналів за фіксованими рядками

Для завдань системного адміністрування — сканування /var/log, /etc або виведення активних процесів — grep залишається правильним інструментом, оскільки він доступний повсюдно без встановлення. Для пошуку в кодових базах застосунків ripgrep є значно швидшим і зручнішим.

Практичні реальні робочі процеси

Аудит невдалих спроб входу через SSH

grep -i "failed password" /var/log/auth.log | grep -oP "from K[d.]+" | sort | uniq -c | sort -rn | head -10

Це витягує вихідний IP кожної невдалої спроби входу через SSH та ранжує їх за частотою — перший крок у виявленні джерел брутфорс-атак перед оновленням правил брандмауера.

Пошук помилок конфігурації перед перезапуском служби

grep -rn "listens*443" /etc/nginx/

Підтверджує, які файли конфігурації Nginx визначають HTTPS-слухачів. Поєднайте з налаштуванням SSL Certificates, щоб перевірити, чи дійсно існують шляхи до сертифікатів, зазначені в цих файлах.

Моніторинг файлу журналу в реальному часі

tail -f /var/log/app/production.log | grep --line-buffered "ERROR"

--line-buffered примушує grep скидати виведення після кожного рядка замість буферизації, що є обов’язковим при передачі даних з tail -f через конвеєр. Без цього ви можете не бачити жодного виведення протягом хвилин, навіть якщо збіги відбуваються.

Перевірка розгорнутої конфігурації

grep -c "server_name" /etc/nginx/sites-enabled/* | grep -v ":0"

Виводить список кожного увімкненого сайту Nginx, що має принаймні одну директиву server_name — швидка перевірка після розгортання нового віртуального хоста в середовищі VPS Hosting.

Витягування адрес електронної пошти з файлу

grep -Eo "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}" contacts.txt

Прапорець -o у поєднанні з шаблоном ERE витягує лише знайдені адреси електронної пошти, по одній на рядок, готові до подальшої обробки.

Пошук у журналах застосунків на кількох серверах

На Dedicated Server з кількома екземплярами застосунків може знадобитися зіставлення журналів із різних каталогів:

grep -rh --include="*.log" "transaction_id=abc123" /var/log/app1/ /var/log/app2/ /var/log/app3/

-h придушує імена файлів, щоб виведення можна було передати по конвеєру в представлення, відсортоване за часовою міткою.

Поширені помилки та способи їх уникнення

Забуття взяти в лапки шаблони з пробілами:

# Wrong — shell splits "connection refused" into two arguments
grep connection refused /var/log/syslog

# Correct
grep "connection refused" /var/log/syslog

Використання синтаксису BRE там, де потрібен ERE:

# Wrong in BRE — + is literal
grep "error+" app.log

# Correct — use -E or escape in BRE
grep -E "error+" app.log
grep "error+" app.log

Рекурсивний пошук, що зачіпає бінарні файли:

# Produces "Binary file matches" noise
grep -r "config" /usr/

# Correct — skip binary files
grep -r --binary-files=without-match "config" /usr/
# or equivalently
grep -rI "config" /usr/

Плутанина з прив’язками — ^ всередині класу символів:

[^abc] означає "не a, b або c". ^ означає "початок рядка" лише тоді, коли він з’являється на самому початку шаблону, поза дужками.

Ключові висновки та матриця прийняття рішень

Використовуйте цей контрольний список при складанні команди grep:

  • Літеральний рядок, регулярний вираз не потрібен? Додайте -F для максимальної швидкості.
  • Невідомий регістр у цільовому файлі? Додайте -i.
  • Потрібно знати, де у файлі знаходиться збіг? Додайте -n.
  • Пошук у дереві каталогів? Додайте -r --include="*.ext" для обмеження області пошуку.
  • Великий файл, потрібно лише підтвердити наявність? Додайте -m 1 і grep завершить роботу після першого збігу.
  • Потрібен навколишній контекст для діагностики? Додайте -C 3.
  • Шаблон містить метасимволи оболонки? Візьміть шаблон в одинарні лапки: grep '$variable'.
  • Пошук у стиснутих журналах? Використовуйте zgrep або zcat file.gz | grep.
  • Потрібне чергування або квантифікатори +/?? Додайте -E для ERE.
  • Потрібні випереджальні перевірки або нежадібне зіставлення? Додайте -P для PCRE (лише GNU grep).
  • Витягування конкретного знайденого тексту, а не цілих рядків? Додайте -o.
  • Пошук у кодовій базі, а не в системних файлах? Розгляньте ripgrep натомість.

При управлінні серверною інфраструктурою — чи то на VPS з cPanel, чи то в чистому середовищі Linux — grep є першим інструментом, до якого ви звертаєтеся, коли щось ламається. Засвоєння комбінацій прапорців та можливості поєднання з awk, sed, sort та xargs перетворює необроблені дані журналів на корисну діагностичну інформацію за лічені секунди.

Для середовищ, де Email Hosting або веб-застосунки генерують великі обсяги структурованих журналів, природним наступним кроком є поєднання grep з конвеєром агрегації журналів (стек ELK, Loki або подібні) — але grep залишається запасним варіантом, який працює скрізь, завжди, без жодних залежностей.

Часті запитання

У чому різниця між grep, egrep та fgrep?

grep за замовчуванням використовує базові регулярні вирази. egrep еквівалентний grep -E і використовує розширені регулярні вирази, де +, ?, | та () працюють без зворотних косих рисок. fgrep еквівалентний grep -F і трактує шаблон як фіксований літеральний рядок без інтерпретації регулярних виразів, що робить його найшвидшим варіантом. Обидва egrep та fgrep є застарілими псевдонімами; використовуйте grep -E та grep -F у скриптах.

Чому grep -r іноді повертає "Binary file matches"?

grep виявляє бінарні файли шляхом сканування на наявність нульових байтів. Коли він знаходить збіг у тому, що вважає бінарним файлом, він виводить це повідомлення замість рядка зі збігом. Придушіть бінарні файли за допомогою grep -rI (велика I) або примусово увімкніть текстовий режим обробки за допомогою grep -ra (обробляти всі файли як текст). Використовуйте -I у виробничому середовищі, щоб уникнути спотвореного виведення через випадкове зіставлення скомпільованих об’єктів або стиснутих файлів.

Як шукати шаблон, що містить пряму косу риску?

Прямі косі риски не мають спеціального значення в шаблонах grep (на відміну від sed або awk). Їх можна використовувати буквально: grep "var/log" /etc/logrotate.conf. Екранування не потрібне.

Який найшвидший спосіб перевірити, чи існує рядок у великому файлі?

Використовуйте grep -qF "string" file && echo "found". Прапорець -q придушує все виведення та завершує роботу зі статусом 0 при першому збігу, 1 якщо збігів немає. Прапорець -F вимикає обробку регулярних виразів. Разом grep читає лише стільки файлу, скільки потрібно, і негайно завершує роботу — критично важливо для файлів розміром у гігабайти.

Чи може grep шукати у файлах на віддаленому сервері без їх локального копіювання?

Так. Передайте через SSH: ssh user@host "grep -r 'pattern' /var/log/". Пошук виконується на віддаленому хості, і по мережі передаються лише рядки зі збігами. Для регулярних пошуків розгляньте можливість монтування віддаленої файлової системи за допомогою sshfs та локального запуску grep, або використовуйте централізоване рішення для збору журналів, якщо обсяг виправдовує інфраструктуру.

15%

Збережіть 15% на всі хостинг-послуги

Перевірте свої навички і отримайте Знижку на будь-який план хостингу

Використовуй код:

Skills
Почати