Библиотека сайта 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 с дополнительными флагами:
$ strace -o /tmp/strace-file -s 512 dd if=/dev/zero of=/tmp/file bs=1024k count=5
Мы использовали следующие флаги:
-o указывает, в какой файл перенаправляется вывод, чтобы его можно было спокойно почитать позже.
-s 512 увеличивает длину строки до 512 байт. По умолчанию она равна 32 байта.
Теперь результат выглядит лучше:
И содержимое файла:
Полный вывод
Теперь мы хотим изучить трассируемый процесс более подробно. Например, вам могут быть интересны не только привлекающие к себе внимание детали, но вы хотите видеть полную таблицу всех системных вызовов, используемых процессом, включая ошибки. Это может быть очень полезно при сравнении нормально работающей системы с неисправной, позволяя быстро находить отличия в их поведении.
$ 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.
Теперь, если мы переименуем исходный файл, а затем попытаемся его скопировать под старым именем, получим ошибку:
Но если вы не можете по каким-либо причинам увидеть сообщение об ошибке? Как вы сможете узнать, что пошло не так при выполнении команды?
Чтобы продемонстрировать это, я собираюсь перенаправить весь вывод в /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, и никакие другие.
В таком случае вывод будет намного короче и проще для сортироваки, так как у нас всего два файла, к которым требуется доступ.
Изучение системных вызовов
Если вы хотите узнать больше о системных вызовах, информацию о них можно почерпнуть из man-страниц с помощью команды man 2. Конечно, они предназначены в основном для гиков и системных программистов, но если вы хотите углубить свои знания и лучше понять, что пытаются сделать ваши процессы, это хороший способ расширить свой кругозор.
$ man 2 system call
В нашем случае:
Давайте посмотрим второй пример.
Пример 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
Как вы можете видеть, статус выполнения 2, что нехорошо. Но мы не знаем, в чем дело. Время запустить strace, чтобы найти причину ошибки.
$ strace -o /tmp/ping -s 512 \ ping -c 3 192.168.1.1 > /dev/null 2>&1
Теперь давайте глянем на лог. Лично я не знаю, чего ждать, поэтому давайте поищем ошибки, связанные с 192.168.1.1.
И вот они. Мы открыли сокет и попытались соединиться. Но затем мы получили ошибку ENETUNREACH, которая означает, что сеть недоступна. Причина найдена. Конечно, теперь нам нужно понять, почему сеть недоступна, но теперь мы можем сосредоточиться на решении проблемы, вместо того, чтобы пытаться понять, что происходит.
Заключение
strace - это могучая утилита. Она очень проста в использовании и при этом имеет хорошую функциональность. Конечно, я не могу рекомендовать ее большинству обычных пользователей, но, имея немного терпения и инсктинкта исследователя, соединенных с любопытством и желанием учиться, вы можете сделать с ее помощью что-нибудь полезное.
Могу показать это на личном примере. Я использовал strace для решения самых различных проблем, начиная от поиска файлов и ошибок монтирования и заканчивая шрифтами и проблемами с производительностью системы. И каждый раз strace была полезной. Можно сказать, что каждая третья проблема может быть легко диагностирована с помощью strace.
Расширяйте свои знания и повышайте умения. Не бойтесь. Возьмите strace и начинайте с ней работать. Очень скоро вы почувствуете себя более свободным и повысите свою продуктивность.