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

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

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

Так,

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

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

strace -p <pid> расскажет вам, что сейчас происходит с вашей программой ..... быстрее и проще, чем GDB

ernesto 28.01.2014 18:06

Я лично считаю, что man strace действительно удобен для чтения и полезен. (P.S. не знал до вчерашнего дня о strace и не был экспертом по Linux)

Alexander Malakhov 27.02.2014 16:16

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

Pithikos 26.09.2014 15:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
280
3
283 931
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

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

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

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

dmckee --- ex-moderator kitten 06.10.2008 20:17

strace <prog_name> для отслеживания программы. strace -o <out_file> <prog_name> для вывода в файл

Jestin Joy 09.01.2011 12:05

strace prog 2> & 1 | grep ^ открыть \ (

eisbaw 03.07.2011 17:37

Или просто: strace -e open myprog ИЛИ для всех системных вызовов, связанных с файлами: strace -e file myprog

Amit Naidu 26.04.2013 12:21
Ответ принят как подходящий

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

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

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

Так что, если вы используете что-то ниже уровня, который отслеживает strace?

Pacerier 19.10.2014 04:13

В этом случае @Pacerier проверьте ltracestackoverflow.com/a/52012215/5884955

prosti 25.08.2018 01:09

Он отлично подходит для отладки низкоуровневых программ, которые существуют только / в основном для выполнения интересных системных вызовов, или для экспериментов с новыми параметрами системных вызовов, чтобы увидеть, что делает ваша ОС. Это в основном избавляет от необходимости писать код регистрации / проверки ошибок для разовых экспериментов. (Или если вы пишете в asm или что-то еще, где есть большая вероятность, что вы случайно передали неправильные аргументы или даже номер вызова.) Strace намного быстрее, чем GDB, потому что он ищет для вас коды ошибок, например -EFAULT (ой, буфер только для чтения) или -ENOENT (ой, запущен из неправильного каталога, где относительный путь не работает).)

Peter Cordes 09.04.2019 09:50

Проще говоря, 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

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

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

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

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

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

это очень точно.

prosti 25.08.2018 00:24

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

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

Пример анализа с помощью strace см. В моем ответе на этот вопрос.

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

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

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

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

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

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

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

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

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

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

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

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

Мне понравились некоторые ответы, в которых говорится, что 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.

The ptrace() system call provides a means by which one process (the "tracer") may observe and control the execution of another process (the "tracee"), and examine and change the tracee's memory and registers. It is primarily used to implement breakpoint debugging and system call tracing.

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

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

Минимальный запускаемый пример

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

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

привет.

.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: показывает сделанный нами системный вызов записи. 6 - это длина строки "hello\n".

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

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

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

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

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

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

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

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, как ни странно, использует системный вызов Linux write.

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

This system call is equivalent to exit(2) except that it terminates not only the calling thread, but all threads in the calling process's thread group.

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

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

Вот несколько примеров того, как я использую 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

Другие вопросы по теме