Расскажу про один трюк в strace, про который я вроде бы ещё ни разу не писал.
У strace и её производных (ltrace, latrace) есть ключ -o, через который настраивается вывод результата в файл. При этом вместо файла может выступать pipe, а не обычный файл. Покажу сразу на примере. Тут будет видно явное удобство такого подхода.
Strace много всего умеет и обычно используется при дебаге. Я про него часто упоминал в различных заметках в основном в контексте анализа дисковой активности процессов. Например, какие файлы читает процесс, в какие пишет. Вот сразу реальный и полезный пример с Angie/Nginx.
Если у вас навороченная конфигурация, где куча всего подключается из разных директорий, что бывает часто (привет настройкам Nginx в Bitrixenv), то хочется быстро посмотреть, а что реально из какой-то конкретной директории подключается в момент запуска веб сервера. Проще всего это сделать, анализируя активность процесса во время выполнения команды nginx -t. В этот момент конфигурация проверяется на ошибки, соответственно, она должна быть прочитана.
Можно просто посмотреть все системные вызовы openat, которые отвечают за чтение:
# strace -zf -e trace=openat nginx -t
В выводе будет много всего лишнего - библиотеки, логи, системные файлы и т.д. Можно попробовать грепнуть:
# strace -zf -e trace=openat nginx -t | grep /etc/nginx
У вас, кстати, ничего не получится. Это особенность nginx, про которую просто надо знать. Вывод этой команды улетает не в стандартный поток stdout, а в stderr. Не знаю, почему так, но в Nginx это исторически сложилось. А grep не грепает stderr. Вам нужно будет как минимум сделать вот так:
# strace -zf -e trace=openat nginx -t 2>&1 | grep /etc/nginx
То есть направить поток stderr в stdout. Тогда он грепнется. Но вывод всё равно будет не очень красивый и наглядный. И тут можно использовать вот такой трюк:
# strace -o "| grep -Eo '/etc/nginx/[^\"]+'" -zf -e trace=openat nginx -t
/etc/nginx/nginx.conf
/etc/nginx/modules-enabled
/etc/nginx/mime.types
/etc/nginx/conf.d
/etc/nginx/sites-enabled
/etc/nginx/sites-enabled/default
На выходе получили аккуратный обработанный список директорий и файлов в /etc/nginx, которые веб сервер прочитал. Смысл того, что мы сделали в том, что через ключ -o вывод отправили не в файл, а в пайп, где он сразу же был обработан тем же grep, который вывел только то, что было между " ", а это как раз путь в файловой системе. Вся остальная информация не нужна и только мешает.
В данном случае уже не имеет значение, куда и как пишет nginx. За этим не нужно следить. Аналогичная команда с обычным грепом выглядела бы так:
# strace -zf -e trace=openat nginx -t 2>&1 | grep -Eo '/etc/nginx/[^\"]+'
Тут обязательно перенаправление 2>&1.
Подобная обработка вывода через pipe актуальна для анализа каких-то интерактивных программ. Например, iftop:
# strace -o "| grep -Eo '/[^\"]+'" -zf -e trace=openat iftop
Запускаем и сразу закрываем iftop. В консоли видим список файлов, которые она прочитала. В данном случае команда:
# strace -zf -e trace=openat iftop | grep -Eo '/[^\"]+'
уже не сработает. До grep дело не дойдёт, так как сначала вывалится портянка strace, а потом запустится iftop. В первом случае мы сразу же обрабатываем вывод в strace, выводим его в консоль и потом запускается iftop.
Можно посмотреть, где живёт конфигурация mc, запущенная под рутом:
# strace -o "| grep -Eo '/root[^\"]+'" -zf -e trace=openat mc
/root/.config/mc/ini
/root/.bash_history
Просто и наглядно. Удобно смотреть, кто, что читает в момент запуска.
#bash #linux #terminal