Задача «найти файл, в котором упоминается вот эта строка» возникает постоянно. Куда поехал трафик, где прописан старый домен, в каком конфиге живёт устаревший пароль от базы данных — на все эти вопросы отвечает поиск по содержимому. Инструментов несколько, у каждого свои сильные стороны.
grep — основной инструмент
grep расшифровывается как global regular expression print. Утилита читает файлы и выводит строки, совпавшие с шаблоном.
Базовый синтаксис:
grep [опции] "шаблон" файл_или_путь
Самое частое применение на сервере — рекурсивный поиск по директории:
grep -r "искомая_строка" /путь/к/директории
Флаг -r заставляет grep обходить все вложенные папки. Без него grep смотрит только в указанный файл или список файлов.
Флаги, которые реально используются
-i — регистр не важен
grep -ri "error" /var/log/nginx/
С этим флагом Error, ERROR и error — одно и то же. На практике незаменим при поиске по логам, где уровень ошибки может быть записан по-разному.
-n — номера строк в выводе
grep -n "listen 80" /etc/nginx/nginx.conf
Показывает, в какой конкретно строке найдено совпадение. Удобно, когда нужно сразу открыть файл в редакторе и перейти к нужному месту.
-l — только имена файлов
grep -rl "database_name" /etc/
Вместо вывода самих строк — просто список файлов, где встретился шаблон. Когда результатов много и нужно сначала понять масштаб.
-c — количество совпадений
grep -c "POST" /var/log/nginx/access.log
Выводит число строк с совпадениями, а не сами строки. Быстрый способ оценить, сколько POST-запросов в логе, не листая его целиком.
-v — инвертированный поиск
grep -v "127.0.0.1" /var/log/nginx/access.log
Показывает строки, где шаблон не встречается. Полезно отфильтровать локальные запросы из лога и посмотреть только внешний трафик.
-A, -B, -C — контекст вокруг совпадения
grep -A 3 "fatal error" /var/log/php/error.log
-A 3 выводит 3 строки после совпадения. -B 3 — 3 строки до. -C 3 — по 3 строки с обеих сторон. Незаменимо при разборе стектрейсов в логах.
Комбинации флагов для реальных задач
Найти все конфиги, где упоминается конкретный IP
grep -rn "192.168.1.100" /etc/ --include="*.conf"
--include ограничивает поиск только файлами с указанным расширением. Без этого grep полезет в бинарники и всё лишнее.
Искать сразу несколько строк
grep -E "error|warning|critical" /var/log/syslog
Флаг -E включает расширенные регулярные выражения. Вертикальная черта работает как логическое ИЛИ — найдёт строки с любым из трёх слов.
Исключить определённые файлы из поиска
grep -r "old_domain.com" /var/www/ --exclude="*.log" --exclude-dir=".git"
--exclude и --exclude-dir позволяют убрать из поиска ненужное — логи, кеш, репозиторий git.
Подсчитать уникальные IP из лога
grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
-o выводит только совпавшую часть строки, а не строку целиком. В связке с sort и uniq получаем топ-20 IP-адресов по количеству запросов.
Поиск в сжатых логах: zgrep
Логи на серверах часто ротируются и сжимаются в .gz. Обычный grep не читает архивы — для этого есть zgrep:
zgrep "error" /var/log/nginx/error.log.2.gz
Работает идентично grep, но умеет читать gzip-архивы напрямую. Синтаксис и флаги те же.
Для поиска сразу по всем ротированным логам:
zgrep -h "critical" /var/log/nginx/error.log*.gz
-h убирает имена файлов из вывода — полезно, когда нужно только содержимое строк.
ripgrep — быстрая альтернатива
rg (ripgrep) — современная замена grep, написанная на Rust. На больших кодовых базах и объёмных директориях работает в разы быстрее за счёт параллельного обхода файлов.
Установка:
apt install ripgrep
Базовое использование — тот же синтаксис:
rg "строка" /путь
Ключевые отличия от grep:
- автоматически игнорирует
.git,node_modulesи всё из.gitignore - рекурсивный режим включён по умолчанию
- цветной вывод с подсветкой совпадений из коробки
- поддерживает поиск по сжатым файлам с флагом
-z
rg -z "error" /var/log/
Для разовой диагностики разница незаметна. На проекте с тысячами файлов — существенная.
find + grep: когда нужен поиск с фильтрацией по атрибутам файла
Иногда нужно искать не во всех файлах, а только в тех, что изменились за последние сутки, или только в файлах определённого размера. Здесь grep нужна помощь find:
find /var/www -name "*.php" -mtime -1 | xargs grep -l "eval("
Находит .php-файлы, изменённые за последние сутки, и проверяет каждый на наличие eval( — классический признак инжекции вредоносного кода.
find /etc -type f -size -10k | xargs grep -rn "password"
Ищет слово password только в файлах меньше 10 килобайт — отсекает большие бинарники и медиафайлы.
xargs передаёт результаты find на вход grep. Без него пришлось бы писать сложнее.
Шпаргалка
| Задача | Команда |
|---|---|
| Рекурсивный поиск по директории | grep -r "строка" /путь/ |
| Поиск без учёта регистра | grep -ri "строка" /путь/ |
| Показать номера строк | grep -n "строка" файл |
| Только имена файлов с совпадением | grep -rl "строка" /путь/ |
| Инвертированный поиск | grep -v "строка" файл |
| Контекст вокруг совпадения | grep -C 3 "строка" файл |
| Только по .conf файлам | grep -r "строка" /путь/ --include="*.conf" |
| Поиск по сжатым логам | zgrep "строка" файл.gz |
| Несколько шаблонов | grep -E "а|б|в" файл |
| Через find с фильтром | find /путь -name "*.php" | xargs grep "строка" |
Итог
Для большинства задач хватает grep -rn с нужным флагом. Сжатые логи — zgrep. Большой проект с тысячами файлов — стоит установить ripgrep. Поиск с фильтрацией по дате или размеру — find в связке с xargs grep.
Всё это работает на любом Linux-сервере без дополнительной настройки. Если сервер ещё не выбран — подобрать конфигурацию можно в каталоге PQ.Hosting.