strace 도구 고장 검사 5 가지 간단 한 방법
9363 단어 linux 의 유 틸 리 티 도구
본문 은 strace 를 사용 하여 문 제 를 해결 하 는 5 가지 간단 한 방법 에서 기원 되 었 다.
strace 는 실행 가능 한 프로그램의 시스템 호출(system call)을 추적 하 는 매우 간단 한 도구 입 니 다.가장 간단 한 사용 은 실행 가능 한 프로그램 이 실 행 될 때의 전체 생명 주 기 를 추적 하고 모든 시스템 에서 호출 된 이름,파라미터 와 반환 값 을 출력 하 는 것 이다. 하지만 더 많은 일 을 할 수 있다.
어떻게 사용 합 니까?
여 기 는 strace 를 어떻게 사용 하 는 지 간단하게 설명 할 뿐 이에 대해 깊이 분석 할 생각 은 없다.
$ strace php 2>&1 | grep php.ini open("/usr/local/bin/php.ini", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/local/lib/php.ini", O_RDONLY) = 4 lstat64("/usr/local/lib/php.ini", {st_mode=S_IFLNK|0777, st_size=27, ...}) = 0 readlink("/usr/local/lib/php.ini", "/usr/local/Zend/etc/php.ini", 4096) = 27 lstat64("/usr/local/Zend/etc/php.ini", {st_mode=S_IFREG|0664,st_size=40971, ...}) = 0
상기 phop 프로그램 은 /usr/local/bin/
에서 php.ini
파일 을 먼저 읽 습 니 다.아마도 당신 이 생각 하 는 것 이 아 닐 것 입 니 다.먼저 /usr/local/lib/
에서 읽 습 니 다.상기 출력 이 많 을 것 입 니 다.우 리 는 심지어 매개 변 수 를 통 해 우리 가 관심 을 가 지 는 시스템 호출 만 추적 할 수 있 습 니 다.예 를 들 어 다음 과 같 습 니 다. $ strace -e open php 2>&1 | grep php.ini open("/usr/local/bin/php.ini", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/local/lib/php.ini", O_RDONLY) = 4
$ strace -e open,access 2>&1 |grep your-filename
open()과 access()시스템 이 호출 한 출력 결 과 를 확인 하고 어떤 원인 인지 알 아 보 세 요. root@dev:~# strace -p 15427 Process 15427 attached - interrupt to quit futex(0x402f4900, FUTEX_WAIT, 2, NULL Process 15427 detached
추적 을 통 해 프로그램 이 끊 긴 이 유 는 futex()를 호출 하고 있 기 때 문 입 니 다. root@dev:~# strace -c -p 11084
Process 11084 attached - interrupt to quit
Process 11084 detached
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
94.59 0.001014 48 21 select
2.89 0.000031 1 21 getppid
2.52 0.000027 1 21 time
------ ----------- ----------- --------- --------- ----------------
100.00 0.001072 63 total
root@dev:~#
만약 당신 이 추적 하 는 백 엔 드 데 몬 이 라면 위의 명령 을 통 해 일정 시간 추적 한 다음 에 ctrl+c
을 누 르 면 strace 는 얻 은 정보 에 따라 위의 결 과 를 설명 할 수 있 습 니 다.상기 예 는 현재 프로 세 스(postmaster)가 select()
함 수 를 기다 리 는 데 가장 걸 리 는 시간 을 설명 합 니 다.select
함 수 를 호출 할 때마다 getpid
함수 와 time
함 수 를 호출 합 니 다.백 엔 드 데 몬 이 아니라면 strace 는 프로 세 스 의 시작 과 끝 을 추적 할 수 있 습 니 다.아래 와 같이: root@dev:~# strace -c >/dev/null ls
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
23.62 0.000205 103 2 getdents64
18.78 0.000163 15 11 1 open
15.09 0.000131 19 7 read
12.79 0.000111 7 16 old_mmap
7.03 0.000061 6 11 close
4.84 0.000042 11 4 munmap
4.84 0.000042 11 4 mmap2
4.03 0.000035 6 6 6 access
3.80 0.000033 3 11 fstat64
1.38 0.000012 3 4 brk
0.92 0.000008 3 3 3 ioctl
0.69 0.000006 6 1 uname
0.58 0.000005 5 1 set_thread_area
0.35 0.000003 3 1 write
0.35 0.000003 3 1 rt_sigaction
0.35 0.000003 3 1 fcntl64
0.23 0.000002 2 1 getrlimit
0.23 0.000002 2 1 set_tid_address
0.12 0.000001 1 1 rt_sigprocmask
------ ----------- ----------- --------- --------- ----------------
100.00 0.000868 87 10 total
ls
프로그램 은 디 렉 터 리 항목 을 읽 는 데 대부분의 시간 을 쓴다. $ strace -e poll,select,connect,recvfrom,sendto nc www.news.com 80
sendto(3, "\24\0\0\0\26\0\1\3\255\373NH\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20
connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("62.30.112.39")}, 28) = 0
poll([{fd=3, events=POLLOUT, revents=POLLOUT}], 1, 0) = 1
sendto(3, "\213\321\1\0\0\1\0\0\0\0\0\0\3www\4news\3com\0\0\34\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
poll([{fd=3, events=POLLIN, revents=POLLIN}], 1, 5000) = 1
recvfrom(3, "\213\321\201\200\0\1\0\1\0\1\0\0\3www\4news\3com\0\0\34\0\1\300\f"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("62.30.112.39")}, [16]) = 153
connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("62.30.112.39")}, 28) = 0
poll([{fd=3, events=POLLOUT, revents=POLLOUT}], 1, 0) = 1
sendto(3, "k\374\1\0\0\1\0\0\0\0\0\0\3www\4news\3com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
poll([{fd=3, events=POLLIN, revents=POLLIN}], 1, 5000) = 1
recvfrom(3, "k\374\201\200\0\1\0\2\0\0\0\0\3www\4news\3com\0\0\1\0\1\300\f"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("62.30.112.39")}, [16]) = 106
connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("62.30.112.39")}, 28) = 0
poll([{fd=3, events=POLLOUT, revents=POLLOUT}], 1, 0) = 1
sendto(3, "\\\2\1\0\0\1\0\0\0\0\0\0\3www\4news\3com\0\0\1\0\1", 30, MSG_NOSIGNAL, NULL, 0) = 30
poll([{fd=3, events=POLLIN, revents=POLLIN}], 1, 5000) = 1
recvfrom(3, "\\\2\201\200\0\1\0\2\0\0\0\0\3www\4news\3com\0\0\1\0\1\300\f"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("62.30.112.39")}, [16]) = 106
connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("216.239.122.102")}, 16) = -1 EINPROGRESS (Operation now in progress)
select(4, NULL, [3], NULL, NULL) = 1 (out [3])
그러면 상기 출력 은 프로 세 스 가 무슨 일이 일 어 났 는 지 설명 합 니까?이 프로 세 스 가 /var/run/nscd/socket
연결 을 시도 하 는 것 을 알 았 습 니까?이 는 nc
프로그램 이 먼저 NSCD-Name Service Cache Daemon-NIS,YP,LDAP 또는 디 렉 터 리 프로 토 콜 과 관련 된 도 메 인 이름 조회 설정 을 설정 하 는 데 사 용 됩 니 다.상기 예 에서 연결 이 실 패 했 습 니 다.다음 프로 세 스 가 DNS 에 연결 되 기 시작 했다 는 점 은 sin_port=htons(53)
출력 에서 알 수 있다.이 어 sendto()
호출 을 통 해 www.news.com
메 시 지 를 포함 한 DNS 패 키 지 를 보 낸 것 을 볼 수 있다.그리고 돌아 온 패키지 데 이 터 를 읽 습 니 다.무슨 이유 인지 세 번 이나 시 도 했 습 니 다.가능 한 이 유 는 www.news.com
이 CNAME 기록 이기 때문이다.여러 차례 요청 한 것 은 아마도 nc
프로그램 처리 의 한 방식 일 것 이다.마지막 으로 connect()
작업 을 시 작 했 습 니 다.이 작업 의 반환 결 과 는 EINPROGRESS
입 니 다.이것 은 이 연결 이 비 차단 식 이라는 것 을 의미 합 니 다.nc
이 계속 되 기 를 원 하기 때문에 select()
을 호출 했 습 니 다.read
,write
을 strace 추적 시스템 호출 목록 에 추가 하면 다음 과 같은 결 과 를 볼 수 있 습 니 다. read(0, "test
", 1024) = 5
write(3, "test
", 5) = 5
poll([{fd=3, events=POLLIN, revents=POLLIN}, {fd=0, events=POLLIN}], 2, -1) = 1
read(3, "
은'test'+표준 에서 입력 한 줄 의 정 보 를 읽 고 네트워크 연결 에 기록 한 다음 에 poll
을 호출 하여 응답 을 기다 린 다음 에 네트워크 피드백 정 보 를 읽 고 표준 출력 에 기록 합 니 다.