Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Утилиты системного администратора Linux: Strace

Оригинал: Linux super-duper admin tools: Strace
Автор: Igor Ljubuncic
Дата публикации: 29 января 2010 г.
Перевод: А. Кривошей
Дата перевода: декабрь 2012 г.

В моих руководствах по LKCD и Kdump я описывал большое количество примеров того, как работать с дампом краха ядра, как отлаживать приложения, и о многом другом. Сегодняшняя статья посвящена самой важной отладочной утилите второго уровня - strace.

Введение

Strace - это утилита, которая отслеживает системные вызовы, которые представляют собой механизм трансляции, обеспечивающий интерфейс между процессом и операционной системой (ядром). Эти вызовы могут быть перехвачены и прочитаны. Это позволяет лучше понять, что процесс пытается сделать в заданное время.
Перехватывая эти вызовы, мы можем добиться лучшего понимания поведения процессов, особенно если что-то идет не так. Функциональность операционной системы, позволяющая отслеживать системные вызовы, называется ptrace. Strace вызывает ptrace и читает данные о поведении процесса, возвращая отчет.
Сегодня мы изучим, когда нужно использовать strace, как ее использовать, как интерпретировать вывод программы, как находить ошибки в выводе strace и быстро и эффективно решать возникающие проблемы.

Strace с точки зрения системного администратора

Использование strace требует некоторого хакерского инстинкта. Это не для всех. Большинству простых пользователей, вероятно, никогда не понадобится strace, хотя они и могут. С другой стороны, системных администраторов, особенно занимающихся технической поддержкой, вряд ли придется уговаривать воспользоваться strace.
Однако, если вы любопытны, или хотите лучше понять, как работает система, или копание в системе является частью вашей работы, strace может стать хорошей отправной точкой. В любом случае время не будет потрачено зря.
Теперь о том, когда и как нужно использовать strace, и самое важное - на какую информацию нужно обращать особенное внимание. Сначала это покажется похожим на черную магию, но вникнув в детали и проявив некоторую дисциплинированность, вы сможете успешно управлять strace и успешно ее применять.
Strace не является единственной утилитой, способной трассировать системные вызовы. Есть еще ltrace, которая умеет работать не только с системными, но и с библиотечными вызовами, а также популярный Gnu Debugger (gdb), который представляет собой полнофункциональный отладчик программного кода.
Далее мы поговорим об этом в деталях. Важно помнить, что хотя strace не столь мощная утилита, как две вышеуказанные, она намного безопаснее и проще в использовании. ltrace имеет склонность обрушивать процессы, которые она отслеживает. gdb намного более сложен и требует глубокого знания кода. Лучше всего с ним работать, если доступны исходные коды, что бывает не всегда. strace можно назвать легкой артиллерией, но он удобен и всегда под рукой.

Что нужно знать перед тем, как начать работу со strace

strace не является чудодейственным средством. Она всего лишь предоставляет некоторую, весьма ограниченную, информацию о запущенном процессе. Чтобы получить полную картину, понадобится намного больше действий, включая использование ltrace и отладку, а также компилирование вашего приложения (или ядра) с отладочной информацией, профилирование запуска приложения с помощью соотвествующей утилиты, и кое-что еще.
strace - это только начало. Но очень хорошее начало. Она направит вас в нужном направлении, либо обеспечит решение проблемы.
strace нужно использовать в том случае, когда вы встречаетесь с проблемой, которую можно воспроизвести, и при этом вы не видите очевидных причин ее возникновения. Ниже мы рассмотрим примеры такого рода.
strace цепляет процесс и обычно заставляет его выполнять каждую операцию дважды - один раз для трассировки, и один раз для его собственного назначения. Это приводит к дополнительным затратам времени. Более того, это означает, что могут появиться некоторые более деликатные проблемы, зависящие от точного времени выполнения, например различные баги, связанные со скоростью работы, могут не проявиться при трассировке.
strace может привести к краху приложения.
64-битная версия strace может не заработать нормально с 32-битными программами.
Не все программы могут трассироваться. Причиной этого могут быть как специфические ошибки в коде программы, так и целенаправленная защита от трассировки. Последнее особенно часто встречается при работе с проприетарными программами.
Теперь, если вы готовы, начнем.

Примеры!

Мы начнем с основ, а затем я покажу вам два тестовых примера, моделирующих реальные проблемы с исполнением программ, которые невозможно решить путем изменения настроек самих программ или основываясь на визулальных подсказках. Но они легко решаются при помощи strace.

Основы использования strace

Прежде всего, перед тем, как начать работу, рекомендую вам почитать man-страницу утилиты.
strace можно вызвать для программы, запущенной в командной строке, независимо от того, является ли она исполняемым файлом или скриптом, или может быть прикреплена к уже работающему процессу. Вывод можно направить на экран, но обычно его перенаправляют в файл.
Специальные флаги используются для измерения тайминга системного вызова, как внутри вызова, так и между ними. Также можно трассировать дочерние процессы, а также выводить переменные окружения. Имеется также возможность фильтровать только заданные системные вызовы.
Базовый синтаксис strace:

$ strace command-line

Пример использования с командой dd:

$ strace dd if=/dev/zero of=/tmp/file bs=1024K count=5

использование strace с командой dd

В результате получим следующий вывод:

вывод strace с командой dd

Выглядит достаточно беспорядочно и трудно для понимания.

Дополнительные флаги

Вы можете вызвать strace с дополнительными флагами:

$ strace -o /tmp/strace-file -s 512 dd if=/dev/zero of=/tmp/file bs=1024k count=5

strace дополнительными флагами

Мы использовали следующие флаги:
-o указывает, в какой файл перенаправляется вывод, чтобы его можно было спокойно почитать позже.
-s 512 увеличивает длину строки до 512 байт. По умолчанию она равна 32 байта.

Теперь результат выглядит лучше:

вывод strace дополнительными флагами

И содержимое файла:

содержимое лога

Полный вывод

Теперь мы хотим изучить трассируемый процесс более подробно. Например, вам могут быть интересны не только привлекающие к себе внимание детали, но вы хотите видеть полную таблицу всех системных вызовов, используемых процессом, включая ошибки. Это может быть очень полезно при сравнении нормально работающей системы с неисправной, позволяя быстро находить отличия в их поведении.

$ strace -c command

И наш пример:

полный вывод

Например, у нас есть 1500 вызовов записи, включая 8 ошибок. 67% времени процесса затрачено на запись, вероятно вследствие работы команды dd. Но у нас есть также достаточно много вызовов чтения.
Другие полезные флаги - это -f (ответвление), -Tt (время, затраченное на системный вызов, или между вызовами) и другие. Для трассировки уже запущенного процесса необходимо использовать флаг -p, за которым идет ID процесса (PID). Его можно узнать, выведя список процессов командой ps и найдя требуемый процесс по имени.

$ strace -p PID

Теперь мы знаем, как использовать strace. Давайте посмотрим, что с помощью него можно сделать.

Пример 1

Мы будем копировать файл. Очень просто. Но мы удалим исходный файл и перенаправим сообщение об ошибке в /dev/null, чтобы пользователь не увидел в командной строке, что произошло после выполнения команды.
Мы работаем в системе openSUSE 11.2 Gnome edition, в директории Documents, где находится несколько шаблонов OpenOffice.

содержимое директории Documents

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

ошибка при копировании

Но если вы не можете по каким-либо причинам увидеть сообщение об ошибке? Как вы сможете узнать, что пошло не так при выполнении команды?
Чтобы продемонстрировать это, я собираюсь перенаправить весь вывод в /dev/null, чтобы пользователь не увидел никаких сообщений:

$ strace command > /dev/null 2>&1

Последние символы, 2>&1, сообщают системе, что необходимо перенаправить STDERR (FD 2) туда же, куда и STDOUT (FD 1), в нашем случае в /dev/null, чтобы не увидели сообщений об ошибках. Далее, мы проверим статус выполнения программы с помощью команды echo $?. Если она вернет 0, значит все в порядке, если 1 - у нас проблема.

перенаправление вывода

Итак, команда cp выполнена, видимых ошибок нет, отлично. Теперь проверим статус. Получаем 1, значит что-то пошло не так. Если это простая команда копирования, проверить ее выполнение достаточно просто, но что, если вы запустили сложный скрипт, который работает с десятками директорий и копирует сотни файлов?

Применим strace.

Итак, я собираюсь показать вам действительную мощь strace. Сейчас мы протрассируем неудачно выполненную команду копирования и проанализируем лог strace.

$ strace -o /tmp/cp-fail -s 512 \
cp "New Document.ott" "Test" > /dev/null 2>&1

трассировка команды копирования

У нас есть лог-файл по имени cp-fail. Мы откроем его в текстовом редакторе и посмотрим на содержимое. Самый большой вопрос - что там нужно искать? В нашем случае, мы производили копирование, для чего нужны исходный и целевой файлы. У нас могут быть проблемы с наличием исходного или целевого файлов, недостаток прав для выполнения операции, или проблема со свободным пространством на диске. Возможен любой из этих вариантов.
Поэтому мы найдем имя исходного файла в логе и посмотрим, имеются ли здесь какие-либо ошибки.

лог трассировки

Точно, это здесь! Системный вызов stat64 завершен неудачно с сообщением ENOENT (No such file or directory). Значит проблема здесь. У нас нет исходного файла!
strace прекрасна, не так ли?
Далее мы расширим и упростим наш поиск. Вместо того, чтобы трассировать все, мы ограничим область наших исследований только заданными системными вызовами. Для этого имеется флаг -e.
-e позволяет вам трассировать только заданные системные вызовы. Например:

$ strace -e trace=stat64 command

Это значит, что нас интересует только вызов stat64, и никакие другие.

трассировка системного вызова stat64

В таком случае вывод будет намного короче и проще для сортироваки, так как у нас всего два файла, к которым требуется доступ.

лог трассировки системного вызова stat64

Изучение системных вызовов

Если вы хотите узнать больше о системных вызовах, информацию о них можно почерпнуть из man-страниц с помощью команды man 2. Конечно, они предназначены в основном для гиков и системных программистов, но если вы хотите углубить свои знания и лучше понять, что пытаются сделать ваши процессы, это хороший способ расширить свой кругозор.

$ man 2 system call

В нашем случае:

man-страница системного вызова stat64

Давайте посмотрим второй пример.

Пример 2

В этом примере я покажу вам, как отлаживать проблемы с сетью. Вы попытаемся пропинговать маршрут в своей локальной сети. Снача мы увидим успешный пример, затем мы остановим сеть и увидим ошибку. Затем мы перенаправим все ошибки в /dev/null, чтобы мы не знали, что произошло. strace поможет нам докопаться до первопричины.

Итак, нормальный пинг:

$ ping -c 3 192.168.1.1

пинг с работающей сетью

Теперь мы отключаем сеть:

$ /etc/init.d/network stop

Пинг не проходит с сообщением, что сеть недоступна:

Пинг не проходит

Однако, если мы теперь перенаправим все ошибки в /dev/null, то не сможем увидеть сообщение и не будем знать, в чем дело. Представьте, что какое-либо приложение пингует свой сервер для проверки лицензии или получения обновлений.

$ ping -c 3 192.168.1.1 >/dev/null 2>&1

перенаправление сообщения об ошибке в /dev/null

Как вы можете видеть, статус выполнения 2, что нехорошо. Но мы не знаем, в чем дело. Время запустить strace, чтобы найти причину ошибки.

$ strace -o /tmp/ping -s 512 \
ping -c 3 192.168.1.1 > /dev/null 2>&1

поиск ошибки с помощью strace

Теперь давайте глянем на лог. Лично я не знаю, чего ждать, поэтому давайте поищем ошибки, связанные с 192.168.1.1.

лог strace

И вот они. Мы открыли сокет и попытались соединиться. Но затем мы получили ошибку ENETUNREACH, которая означает, что сеть недоступна. Причина найдена. Конечно, теперь нам нужно понять, почему сеть недоступна, но теперь мы можем сосредоточиться на решении проблемы, вместо того, чтобы пытаться понять, что происходит.

Заключение

strace - это могучая утилита. Она очень проста в использовании и при этом имеет хорошую функциональность. Конечно, я не могу рекомендовать ее большинству обычных пользователей, но, имея немного терпения и инсктинкта исследователя, соединенных с любопытством и желанием учиться, вы можете сделать с ее помощью что-нибудь полезное.
Могу показать это на личном примере. Я использовал strace для решения самых различных проблем, начиная от поиска файлов и ошибок монтирования и заканчивая шрифтами и проблемами с производительностью системы. И каждый раз strace была полезной. Можно сказать, что каждая третья проблема может быть легко диагностирована с помощью strace.
Расширяйте свои знания и повышайте умения. Не бойтесь. Возьмите strace и начинайте с ней работать. Очень скоро вы почувствуете себя более свободным и повысите свою продуктивность.