strace는 어떻게 사용해야 하나요?
문제
한 동료는 Linux에서 모든 것이 디버깅에 실패했을 때 마지막 옵션은 다음을 사용하는 것이라고 말했습니다. 스트레이스.
나는 이 이상한 도구 뒤에 숨은 과학을 배우려고 노력했지만 시스템 관리 전문가가 아니어서 실제로 결과를 얻지 못했습니다.
그래서,
- 정확히 무엇이며 어떤 역할을 합니까?
- 어떤 경우에 어떻게 사용해야 하나요?
- 출력을 어떻게 이해하고 처리해야 합니까?
간단히 말해서, 간단한 말로, 이 물건은 어떻게 작동하나요?
해결책
Strace 개요
Strace는 가벼운 무게 디버거로 볼 수 있습니다. 프로그래머 / 사용자는 프로그램이 OS와 어떻게 상호 작용하는지 빠르게 찾을 수 있습니다. 시스템 호출 및 신호를 모니터링하여이를 수행합니다.
용도
소스 코드가 없거나 실제로 그것을 겪고 싶지 않은 경우에 좋습니다.
또한 GDB를 열고 싶지 않지만 외부 상호 작용을 이해하는 데 관심이있는 경우 자신의 코드에 유용합니다.
좋은 작은 소개
나는 다른 날 에이 소개를 Strace 사용으로 만났습니다. Strace Hello World
다른 팁
간단히 말해서, 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 출력에서 OS와의 마지막 상호 작용이 무엇인지 확인할 수 있습니다.
더 많은 정보는 다음을 통해 얻을 수 있습니다:
man strace
Strace는 모두 나열됩니다 시스템 호출 적용되는 프로세스에 의해 수행됩니다. 시스템 호출이 어떤 의미인지 모른다면 많은 마일리지를 얻을 수 없습니다.
그럼에도 불구하고 문제가 파일 또는 경로 또는 환경 값과 관련이있는 경우 문제가있는 프로그램에서 Strace를 실행하고 출력을 파일로 리디렉션 한 다음 Path/File/Env String에 대한 해당 파일을 greping습니다. 프로그램이 무엇인지 확인할 수 있습니다. 실제로 당신이 기대했던 것과 구별되는 것으로 시도합니다.
Strace는 디버거 아래에서 이러한 프로그램을 실행할 여유가없는 생산 시스템을 조사하기위한 도구로 두드러집니다. 특히, 우리는 다음 두 가지 상황에서 Strace를 사용했습니다.
- 프로그램 Foo는 교착 상태에 빠졌고 응답이 없어졌습니다. 이것은 GDB의 대상이 될 수 있습니다. 그러나 우리는 항상 소스 코드를 가지고 있지 않았거나 때로는 디버거 아래에서 실행되기에 직접적으로 진행되지 않은 스크립트 언어를 다루고있었습니다. 이 경우 이미 실행중인 프로그램에서 Strace를 실행하면 시스템 통화 목록이 작성됩니다. 클라이언트/서버 응용 프로그램 또는 데이터베이스와 상호 작용하는 응용 프로그램을 조사하는 경우 특히 유용합니다.
- 프로그램이 느린 이유를 조사합니다. 특히, 우리는 방금 새로운 분산 파일 시스템으로 이동했으며 시스템의 새로운 처리량은 매우 느 렸습니다. 각 시스템 호출에 소요 된 시간을 알려주는 '-t'옵션으로 Strace를 지정할 수 있습니다. 이것은 파일 시스템이 왜 속도를 늦추는지를 결정하는 데 도움이되었습니다.
Strace를 사용하여 분석하는 예는 내 답변을 참조하십시오. 이 질문.
권한 문제를 디버그하기 위해 Strace를 항상 사용합니다. 기술은 다음과 같습니다.
$ strace -e trace=open,stat,read,write gnome-calculator
어디에 gnome-calculator
실행하려는 명령입니다.
Strace -tfp PID는 PID 프로세스의 시스템 호출을 모니터링하므로 프로세스/프로그램 상태를 디버그/모니터링 할 수 있습니다.
Strace는 디버깅 도구 또는 기본 프로파일러로 사용할 수 있습니다.
디버거로서 주어진 시스템 호출이 어떻게 호출되고 실행되었으며 무엇을 반환하는지 확인할 수 있습니다.이는 프로그램이 실패했다는 사실뿐 아니라 프로그램이 실패한 이유도 확인할 수 있으므로 매우 중요합니다.일반적으로 이는 프로그램의 가능한 모든 결과를 포착하지 못하는 형편없는 코딩의 결과일 뿐입니다.다른 경우에는 파일 경로가 하드코딩되어 있을 뿐입니다.추적이 없으면 어디서, 어떻게 문제가 발생했는지 추측할 수 있습니다.strace를 사용하면 syscall의 분석을 얻을 수 있으며 일반적으로 반환 값을 보는 것만으로도 많은 것을 알 수 있습니다.
프로파일링은 또 다른 용도입니다.이를 사용하여 각 syscall의 실행 시간을 개별적으로 또는 전체적으로 측정할 수 있습니다.이것이 문제를 해결하는 데 충분하지 않을 수도 있지만 적어도 잠재적인 용의자 목록을 크게 좁힐 수 있습니다.단일 파일에 fopen/close 쌍이 많이 표시되면 루프 외부에서 파일을 열고 닫는 대신 루프를 실행할 때마다 불필요하게 파일을 열고 닫는 것일 수 있습니다.
Ltrace는 strace의 가까운 사촌이며 매우 유용합니다.병목 현상이 발생하는 위치를 구별하는 방법을 배워야 합니다.총 실행 시간이 8초이고 시스템 호출에 0.05초만 소비한다면 프로그램을 추적하는 것이 별로 도움이 되지 않을 것입니다. 문제는 코드에 있거나 일반적으로 논리 문제이거나 프로그램에 실제로 필요한 것입니다. 실행하는 데 시간이 오래 걸립니다.
strace/ltrace의 가장 큰 문제는 출력을 읽는 것입니다.호출 방법을 모르거나 최소한 시스템 호출/함수의 이름을 모른다면 의미를 해독하기 어려울 것입니다.함수가 반환하는 내용을 아는 것도 특히 다양한 오류 코드의 경우 매우 유용할 수 있습니다.해독하는 것은 고통스러운 일이지만 때로는 실제로 지식의 진주를 반환합니다.inode가 부족하지만 여유 공간이 부족하지 않은 상황을 본 후에는 모든 일반 유틸리티에서 경고를 표시하지 않았으므로 새 파일을 만들 수 없었습니다.strace의 출력에서 오류 코드를 읽으면 올바른 방향을 알 수 있습니다.
Strace는 응용 프로그램이 운영 체제와 어떻게 상호 작용하는지 알려주는 도구입니다.
OS 시스템이 애플리케이션이 사용하는 OS 시스템과 어떤 매개 변수를 호출하는지 알려줍니다.
예를 들어 프로그램이 열려있는 파일을 열고 날씨가 성공합니다.
이 도구의 모든 종류의 문제를 디버깅 할 수 있습니다. 예를 들어, 응용 프로그램에 귀하가 설치 한 라이브러리를 찾을 수 없다고 말하면 Strace는 응용 프로그램이 해당 파일을 찾고있는 위치를 알려줄 것입니다.
그리고 그것은 빙산의 일각 일뿐입니다.
Strace는 프로그램이 다양한 시스템 호출 (커널에 대한 요청)을 만드는 방법을 배우는 좋은 도구이며 해당 실패와 관련된 오류 값과 함께 실패한 것들을보고합니다. 모든 실패가 버그가 아닙니다. 예를 들어, 파일을 검색하려는 코드는 ENOENT (파일 또는 디렉토리) 오류가 발생할 수 있지만 코드의 논리에서 허용 가능한 시나리오 일 수 있습니다.
Strace를 사용하는 좋은 사용 사례 중 하나는 임시 파일 생성 중에 레이스 조건을 디버그하는 것입니다. 예를 들어 프로세스 ID (PID)를 일부 미리 조정 된 문자열에 추가하여 파일을 만들 수있는 프로그램은 다중 스레드 시나리오에서 문제에 직면 할 수 있습니다. [PID + TID (프로세스 ID + 스레드 ID) 또는 MKSTEMM과 같은 더 나은 시스템 호출 이이 문제를 해결합니다.
또한 사고를 디버깅하는 데 좋습니다. 당신은 찾을 수 있습니다 Strace 및 디버깅 충돌에 관한이 기사 (내) 기사 유용한.
나는 그것이 읽는 곳에 답을 좋아했다 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
다른 아키텍처의 바이너리를 추적 할 수 있기 때문에 마음을 날려 버릴 것입니다.
최소한의 실행 가능한 예
개념이 명확하지 않으면 설명하지 않은 더 간단한 예가 있습니다.
이 경우,이 예제는 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
조립 및 실행 :
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
우리는 사용:
env -i ASDF=qwer
환경 변수를 제어하려면 : https://unix.stackexchange.com/questions/48994/how-to-run-a-program-in-nlevironment-in-bash-s999 -v
로그에 더 많은 정보를 표시합니다
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
메인을위한 멋진 환경을 설정합니다.
이는 이제 우리가 독립형 프로그램을 사용하지 않고보다 일반적인 GLIBC 프로그램을 사용하여 LIBC 기능을 허용하기 때문입니다.
그런 다음 모든 끝에서 strace.log
포함
write(1, "hello\n", 6) = 6
exit_group(0) = ?
+++ exited with 0 +++
그래서 우리는 write
Posix 기능은 Linux를 사용합니다 write
시스템 호출.
우리는 또한 그것을 관찰합니다 return 0
in로 연결됩니다 exit_group
대신 전화하십시오 exit
. 하, 나는 이것에 대해 몰랐다! 이는 이유 strace
너무 멋지다. man exit_group
그런 다음 설명합니다.
이 시스템 호출은 통화 스레드뿐만 아니라 호출 프로세스의 스레드 그룹의 모든 스레드를 종료한다는 점을 제외하고는 종료 (2)와 동일합니다.
그리고 여기 내가 어떤 시스템 호출을 공부 한 또 다른 예가 있습니다. dlopen
사용 : https://unix.stackexchange.com/questions/226524/what-system-call-is-used-to-libraries-in-linux/462710#462710
우분투 16.04, GCC 6.4.0, Linux 커널 4.4.0에서 테스트.