Как использовать strace?

273

Коллега однажды сказал мне, что последний вариант, когда все не удалось отладить в Linux, это использовать strace .

Я пытался изучить науку за этим странным инструментом, но я не гуру системного администратора, и я действительно не получил результатов.

Так,

  • Что это такое и для чего оно нужно?
  • Как и в каких случаях его следует использовать?
  • Как следует понимать и обрабатывать результаты?

Вкратце, простыми словами , как это работает?

е-удовлетворяться
источник
2
strace -p <pid> расскажет вам, что происходит сейчас с вашей программой .....
быстрее
1
Я лично нахожу man straceдействительно легким для чтения и полезным. (PS не знал о strace до вчерашнего дня и не эксперт по Linux)
Александр Малахов
1
«strace - это трассировщик системных вызовов» - он просто показывает вам, какие функции ядра вызываются (с их аргументами) в результате вашей программы.
Питикос,

Ответы:

184

Strace Overview
strace можно рассматривать как легкий отладчик. Это позволяет программисту / пользователю быстро узнать, как программа взаимодействует с ОС. Это осуществляется путем мониторинга системных вызовов и сигналов.

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

Хорошее небольшое введение
я наткнулся на это введение, чтобы использовать strace только на днях: strace hello world

Джон Малдер
источник
Так что, если вы используете что-то ниже слоя, который контролирует strace?
Pacerier
В этом случае проверка @Pacerier ltrace stackoverflow.com/a/52012215/5884955
prosti
Он отлично подходит для отладки низкоуровневых программ, которые существуют только / главным образом для выполнения интересных системных вызовов, или для экспериментов с новыми опциями системных вызовов, чтобы увидеть, что делает ваша ОС. Это в основном избавляет от необходимости написания кода регистрации / проверки ошибок для одноразовых экспериментов. (Или если вы пишете в asm или где-то еще, есть вероятность, что вы случайно передали неправильные аргументы или даже номер вызова.) Strace намного быстрее, чем GDB, потому что он ищет коды ошибок для вас, например -EFAULT(упс, только для чтения буфер) или -ENOENT(ой, бежал из неправильного каталога, где относительный путь не работал).)
Питер Кордес
62

Проще говоря, strace отслеживает все системные вызовы, выпущенные программой, вместе с их кодами возврата. Подумайте о таких вещах, как операции с файлами / сокетами и многое другое.

Это наиболее полезно, если у вас есть некоторые практические знания C, поскольку здесь системные вызовы более точно обозначают стандартные вызовы библиотеки C.

Допустим, ваша программа / usr / local / bin / cough. Просто используйте:

strace /usr/local/bin/cough <any required argument for cough here>

или

strace -o <out_file> /usr/local/bin/cough <any required argument for cough here>

записать в 'out_file'.

Весь вывод strace будет идти в stderr (будьте осторожны, его громкость часто требует перенаправления в файл). В простейших случаях ваша программа будет прервана с ошибкой, и вы сможете увидеть, где она в последний раз взаимодействует с ОС, в выводе strace.

Более подробная информация должна быть доступна с:

man strace
bltxd
источник
36

strace перечисляет все системные вызовы, сделанные процессом, к которому он применяется. Если вы не знаете, что означают системные вызовы, вы не сможете получить много пробега от этого.

Тем не менее, если ваша проблема связана с файлами, путями или значениями среды, запуск strace для проблемной программы и перенаправление вывода в файл, а затем поиск этого файла в строке пути / file / env может помочь вам увидеть, что ваша программа на самом деле пытается делать, в отличие от того, что вы ожидали.

Асаф Бартов
источник
7
А для нетривиальных программ это часто похоже на питье из пожарного шланга, так что вам не нужна работа, чтобы вы могли просмотреть результаты ...
dmckee --- котенок экс-модератора
17
strace <prog_name>отследить программу. strace -o <out_file> <prog_name>положить в файл
Джестин Джой
8
strace prog 2> & 1 | grep ^ open \ (
eisbaw
10
Или просто: strace -e open myprogИЛИ для всех системных вызовов, связанных с файлами:strace -e file myprog
Амит Найду
17

Strace выделяется как инструмент для исследования производственных систем, где вы не можете позволить себе запускать эти программы под отладчиком. В частности, мы использовали strace в следующих двух ситуациях:

  • Программа foo оказалась в тупике и перестала отвечать. Это может быть целью для GDB; однако, у нас не всегда был исходный код, или мы иногда имели дело со скриптовыми языками, которые было не просто запустить в отладчике. В этом случае вы запускаете strace для уже запущенной программы и получите список выполняемых системных вызовов. Это особенно полезно, если вы исследуете приложение клиент / сервер или приложение, которое взаимодействует с базой данных.
  • Расследование, почему программа работает медленно. В частности, мы только что перешли на новую распределенную файловую систему, и новая пропускная способность системы была очень медленной. Вы можете указать strace с помощью опции '-T', которая сообщит вам, сколько времени было потрачено на каждый системный вызов. Это помогло определить, почему файловая система вызывала замедление.

Для примера анализа использования strace см. Мой ответ на этот вопрос .

Паттерсона
источник
15

Я все время использую strace для устранения проблем с разрешениями. Техника идет так:

$ strace -e trace=open,stat,read,write gnome-calculator

Где gnome-calculatorкоманда, которую вы хотите запустить.

Джефф Шеффилд
источник
8

strace -tfp PID будет отслеживать системные вызовы процесса PID, поэтому мы можем отлаживать / отслеживать состояние нашего процесса / программы.

Лесли Чжу
источник
6

Strace можно использовать как инструмент отладки или как примитивный профилировщик.

Как отладчик, вы можете видеть, как данные системные вызовы вызывались, выполнялись и что они возвращали. Это очень важно, так как позволяет увидеть не только то, что программа завершилась неудачей, но и ПОЧЕМУ программа потерпела неудачу. Обычно это просто результат паршивого кодирования, не улавливающего все возможные результаты программы. В других случаях это просто жестко заданные пути к файлам. Без ограничений вы можете догадаться, что пошло не так, где и как. С помощью strace вы получаете разбивку системного вызова, обычно просто просмотр возвращаемого значения говорит вам о многом.

Профилирование - это еще одно применение. Вы можете использовать его для определения времени выполнения каждого системного вызова по отдельности или в виде совокупности. Хотя этого может быть недостаточно для решения ваших проблем, по крайней мере, это значительно сузит список потенциальных подозреваемых. Если вы видите много пар fopen / close в одном файле, вы, вероятно, без необходимости открываете и закрываете файлы при каждом выполнении цикла, вместо того, чтобы открывать и закрывать его вне цикла.

Ltrace - близкий родственник Strace, также очень полезный. Вы должны научиться различать, где находится ваше узкое место. Если общее выполнение составляет 8 секунд, и вы тратите только 0,05 сек на системные вызовы, то использование программы не принесет вам большой пользы, проблема в вашем коде, что обычно является проблемой логики, или программе действительно нужны чтобы так долго бежать.

Самая большая проблема с strace / ltrace - это чтение их вывода. Если вы не знаете, как выполняются вызовы или хотя бы имена системных вызовов / функций, будет сложно расшифровать смысл. Знание того, что возвращают функции, также может быть очень полезным, особенно для разных кодов ошибок. Хотя расшифровывать это очень сложно, иногда они действительно возвращают жемчужину знаний; как только я увидел ситуацию, когда у меня закончились inode, но не было свободного места, таким образом, все обычные утилиты не дали мне никакого предупреждения, я просто не смог создать новый файл. Чтение кода ошибки из вывода strace указало мне правильное направление.

Marcin
источник
4

Strace - это инструмент, который сообщает вам, как ваше приложение взаимодействует с вашей операционной системой.

Он делает это, сообщая вам, какие системные вызовы использует ваша прикладная программа и с какими параметрами она их вызывает.

Например, вы видите, какие файлы пытается открыть ваша программа, и выдерживает ли вызов успешно.

Вы можете отлаживать все виды проблем с этим инструментом. Например, если приложение сообщает, что не может найти библиотеку, которую, как вы знаете, вы установили, вы сразу указали, где приложение ищет этот файл.

И это только верхушка айсберга.

Лука Маринко
источник
это очень точно.
прости
4

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

Один хороший пример использования strace - отладка состояния гонки во время создания временного файла. Например, программа, которая может создавать файлы путем добавления идентификатора процесса (PID) к некоторой предварительно определенной строке, может столкнуться с проблемами в многопоточных сценариях. [PID + TID (идентификатор процесса + идентификатор потока) или лучший системный вызов, такой как mkstemp, исправит это].

Это также хорошо для отладки сбоев. Вы можете найти эту (мою) статью о сбоях strace и отладке полезной.

Мохит
источник
4

Минимальный исполняемый пример

Если концепция не ясна, есть более простой пример, который вы не видели, который объясняет это.

В данном случае этот пример - свободно распространяемая сборка Linux x86_64 (без libc):

hello.S

.text
.global _start
_start:
    /* write */
    mov $1, %rax    /* syscall number */
    mov $1, %rdi    /* stdout */
    mov $msg, %rsi  /* buffer */
    mov $len, %rdx  /* buffer len */
    syscall

    /* exit */
    mov $60, %rax   /* exit status */
    mov $0, %rdi    /* syscall number */
    syscall
msg:
    .ascii "hello\n"
len = . - msg

GitHub вверх по течению .

Собрать и запустить:

as -o hello.o hello.S
ld -o hello.out hello.o
./hello.out

Выводит ожидаемое:

hello

Теперь давайте используем strace на этом примере:

env -i ASDF=qwer strace -o strace.log -s999 -v ./hello.out arg0 arg1
cat strace.log

Мы используем:

strace.log теперь содержит:

execve("./hello.out", ["./hello.out", "arg0", "arg1"], ["ASDF=qwer"]) = 0
write(1, "hello\n", 6)                  = 6
exit(0)                                 = ?
+++ exited with 0 +++

В таком минимальном примере каждый отдельный символ вывода очевиден:

  • execveстрока: показывает, как straceвыполняется hello.out, включая аргументы CLI и среду, как описано вman execve

  • writeстрока: показывает системный вызов write, который мы сделали. 6это длина строки "hello\n".

    = 6это возвращаемое значение системного вызова, которое, как задокументировано, man 2 writeявляется количеством записанных байтов.

  • exitстрока: показывает системный вызов выхода, который мы сделали. Нет возвращаемого значения, так как программа вышла!

Более сложные примеры

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

Примечательно, что большинство системных вызовов, с которыми вы можете столкнуться в Linux, имеют оболочки glibc, многие из них из POSIX .

Внутри оболочки glibc используют встроенную сборку более или менее так: Как вызвать системный вызов через sysenter во встроенной сборке?

Следующий пример, который вы должны изучить, - это writeпривет POSIX :

main.c

#define _XOPEN_SOURCE 700
#include <unistd.h>

int main(void) {
    char *msg = "hello\n";
    write(1, msg, 6);
    return 0;
}

Скомпилируйте и запустите:

gcc -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out

На этот раз вы увидите, что glibc выполняет кучу системных вызовов, mainчтобы настроить приятную среду для main.

Это потому, что мы сейчас не используем отдельно стоящую программу, а скорее более распространенную программу glibc, которая обеспечивает функциональность libc.

Затем, на каждом конце, strace.logсодержит:

write(1, "hello\n", 6)                  = 6
exit_group(0)                           = ?
+++ exited with 0 +++

Итак, мы заключаем, что writeфункция POSIX использует, удивительно, writeсистемный вызов Linux .

Мы также наблюдаем, что return 0приводит к exit_groupзвонку вместо exit. Ха, я не знал об этом! Вот почему straceтак круто. man exit_groupзатем объясняет:

Этот системный вызов эквивалентен exit (2) за исключением того, что он завершает не только вызывающий поток, но и все потоки в группе потоков вызывающего процесса.

А вот еще один пример, где я изучал, какой системный вызов dlopenиспользует: /unix/226524/what-system-call-is-used-to-load-libraries-in-linux/462710#462710

Протестировано в Ubuntu 16.04, GCC 6.4.0, ядре Linux 4.4.0.

Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
источник
2

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

Проверьте время до первого байта следующим образом:

time php index.php > timeTrace.txt

Посмотрите, какой процент действий делает что. Многое lstatи fstatможет быть признаком того, что пришло время очистить кеш:

strace -s 200 -c php index.php > traceLstat.txt

Выводит, trace.txtчтобы вы могли точно видеть, какие звонки были сделаны.

strace -Tt -o Fulltrace.txt php index.php

Используйте это , чтобы проверить , было ли что - нибудь между .1к .9секунде к нагрузке:

cat Fulltrace.txt | grep "[<]0.[1-9]" > traceSlowest.txt

Посмотрите, какие недостающие файлы или каталоги попали в папку strace. Это выведет много вещей, связанных с нашей системой - единственные важные биты касаются файлов клиента:

strace -vv php index.php 2>&1 | sed -n '/= -1/p' > traceFailures.txt
Кервин Смит
источник
1

Мне понравились некоторые ответы, где читается straceпроверка того, как вы взаимодействуете с вашей операционной системой.

Это именно то, что мы можем видеть. Система звонков. Если сравнивать straceи ltraceразница более очевидна.

$>strace -c cd
Desktop  Documents  Downloads  examples.desktop  Music  Pictures  Public  Templates  Videos
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  0.00    0.000000           0         7           read
  0.00    0.000000           0         1           write
  0.00    0.000000           0        11           close
  0.00    0.000000           0        10           fstat
  0.00    0.000000           0        17           mmap
  0.00    0.000000           0        12           mprotect
  0.00    0.000000           0         1           munmap
  0.00    0.000000           0         3           brk
  0.00    0.000000           0         2           rt_sigaction
  0.00    0.000000           0         1           rt_sigprocmask
  0.00    0.000000           0         2           ioctl
  0.00    0.000000           0         8         8 access
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         2           getdents
  0.00    0.000000           0         2         2 statfs
  0.00    0.000000           0         1           arch_prctl
  0.00    0.000000           0         1           set_tid_address
  0.00    0.000000           0         9           openat
  0.00    0.000000           0         1           set_robust_list
  0.00    0.000000           0         1           prlimit64
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000                    93        10 total

С другой стороны, есть ltraceто, что отслеживает функции.

$>ltrace -c cd
Desktop  Documents  Downloads  examples.desktop  Music  Pictures  Public  Templates  Videos
% time     seconds  usecs/call     calls      function
------ ----------- ----------- --------- --------------------
 15.52    0.004946         329        15 memcpy
 13.34    0.004249          94        45 __ctype_get_mb_cur_max
 12.87    0.004099        2049         2 fclose
 12.12    0.003861          83        46 strlen
 10.96    0.003491         109        32 __errno_location
 10.37    0.003303         117        28 readdir
  8.41    0.002679         133        20 strcoll
  5.62    0.001791         111        16 __overflow
  3.24    0.001032         114         9 fwrite_unlocked
  1.26    0.000400         100         4 __freading
  1.17    0.000372          41         9 getenv
  0.70    0.000222         111         2 fflush
  0.67    0.000214         107         2 __fpending
  0.64    0.000203         101         2 fileno
  0.62    0.000196         196         1 closedir
  0.43    0.000138         138         1 setlocale
  0.36    0.000114         114         1 _setjmp
  0.31    0.000098          98         1 realloc
  0.25    0.000080          80         1 bindtextdomain
  0.21    0.000068          68         1 opendir
  0.19    0.000062          62         1 strrchr
  0.18    0.000056          56         1 isatty
  0.16    0.000051          51         1 ioctl
  0.15    0.000047          47         1 getopt_long
  0.14    0.000045          45         1 textdomain
  0.13    0.000042          42         1 __cxa_atexit
------ ----------- ----------- --------- --------------------
100.00    0.031859                   244 total

Хотя я проверил руководства несколько раз, я не нашел источника имени, straceно, скорее всего, это трассировка системных вызовов, поскольку это очевидно.

Есть три больших примечания, чтобы сказать о strace.

Примечание 1: обе эти функции straceи ltraceиспользуют системный вызов ptrace. Так что ptraceсистемный вызов эффективно straceработает.

Системный вызов ptrace () предоставляет средство, с помощью которого один процесс («трассировщик») может наблюдать и контролировать выполнение другого процесса («трассировщик»), а также проверять и изменять память и регистры трассировки. Он в основном используется для реализации отладки точек останова и трассировки системных вызовов.

Примечание 2: есть разные параметры, которые вы можете использовать strace, поскольку они straceмогут быть очень подробными. Мне нравится экспериментировать с -cчем-то вроде резюме вещей. Исходя из этого -cвы можете выбрать один системный вызов, например, -e trace=openгде вы увидите только этот вызов. Это может быть интересно, если вы изучаете, какие файлы будут открываться во время отслеживаемой вами команды. И, конечно, вы можете использовать grepдля той же цели, но обратите внимание, что вам нужно перенаправить, как это, 2>&1 | grep etcчтобы понять, что файлы конфигурации ссылаются, когда была выполнена команда.

Примечание 3: я нахожу это очень важное примечание. Вы не ограничены конкретной архитектурой. straceпоразит вас, так как он может проследить через двоичные файлы различных архитектур. введите описание изображения здесь

прости
источник