Search
Duplicate
📿

strace로 시스템콜 추적하기

간단소개
팔만코딩경 컨트리뷰터
ContributorNotionAccount
주제 / 분류
C
debug
minishell
Scrap
태그
잡지식
9 more properties
minishell을 위해 이것저것 알아보던 중, 실제 쉘과 시스템콜이 어떤 순서로 어떻게 작동하는지 궁금해졌다. 이를 strace를 이용해 실험해보았다.
strace는 시스템콜과 시그널을 추적해주는 쉘 명령어이다. open, close, dup2, pipe, execve, fork 등 다양한 시스템콜이 어떻게 호출되는지를 확인할 수 있다.
linux에만 있는 듯하며, 대신 macos에는 dtruss와 같은 명령어가 있지만 관리자 권한이 필요하기에 그냥 도커를 이용하는 게 편하다.
다음은 준비과정이다.
1.
클러스터 맥에서 docker를 이용하는 방법은 아래 링크를 따라하면 편하다.
2.
docker를 이용할 준비가 되었다면 아래와 같이 실행한다. (꼭 데비안일 필요는 없다)
docker run -it --rm --cap-add SYS_PTRACE debian
C
복사
(—rm 옵션은 종료시 자동으로 삭제해주는 옵션이기에 계속 이용할 것이라면 필요에 따라 제외하고 이용하자)
중요: docker 에서 strace를 이용하려면 —cap-add 옵션에 SYS_PTRACE를 추가해줘야한다.
3.
기타 필요한 패키지들을 깔아준다.
apt update && apt install -y man-db vim strace procps lsof
C
복사
사실 strace만 있으면 되지만 편의를 위해 이것저것 설치했다. 이제 정말로 strace를 써보자.
사용예시: 아래와 같이 test.sh 파일을 준비한다.
#!/bin/bash echo hello | cat -e >> test.txt
Bash
복사
부모프로세스는 1개의 pipe를 만들고, 포크를 2번 해 2개의 자식 프로세스를 만들 것이다. 또한 자식1은 shell builtin으로 실행되는 반면 자식2는 cat binary파일을 실행하며 test.txt파일을 열어서 출력을 쓸 것이라는 걸 예측해볼 수 있다. 이제 직접 확인해보자.
chmod로 실행 권한을 준 후 아래와 같이 실행한다.
strace -ff -o output -tt -e trace=openat,close,read,write,clone,pipe,dup2,execve ./test.sh
Bash
복사
많은 옵션이 있지만 특히 다음과 같은 것들이 유용해보였다.
-ff : child 프로세스들도 추적해준다. 각 프로세스별로 결과가 저장된다.
-f : child 프로세스들도 추적해준다. 결과가 하나의 파일로 저장된다.
-tt : 타임스탬프가 us 단위로 나온다.
-r : 각 시스템콜에 소요된 시간을 출력해준다.
-e : 추적할 시스템콜을 지정해준다 (없으면 모두 출력된다).
반대로 특정 시스템콜들만 제외하고 싶다면 -e trace=\!openat,close 와 같이 쓰면 된다.
-o : 결과를 파일로 저장한다. (지정하지 않으만면 표준 에러로 터미널에 나타난다. 2> 를 이용해 리다이렉션이 가능하다)
-p : 명령어나 실행파일 대신 특정 프로세스를 지정해주는 것도 가능하다. pid를 함께 써주면 된다.
시스템에 따라 openat으로 해야하는 경우도, open으로 해야 하는 경우도 있다고 하는데 해본 결과 debian, ubuntu 등에서는 openat으로 해야했다. fork 도 대신 clone으로 해야 나온다.
위와 같이 실행하면 output.pid의 형태로 파일이 3개가 생긴다.
6077은 부모프로세스이며, 6078과 6079는 각각 echo 와 cat을 실행하는 자식프로세스에 해당한다.
왼쪽 = 부모, 오른쪽 위 = 자식1, 오른쪽아래 = 자식2의 출력결과다. (부모의 결과는 앞부분은 조금 지워 생략했다)
실제로 부모에서 pipe 1번, clone이 2번 호출된 것을 볼 수 있고, echo는 execve가 호출되지 않지만 cat은 execve를 통해 바이너리파일을 실행하는 등 여러가지를 확인할 수 있다.
부모 프로세스에서 close를 2번씩 한다거나, fd 3을 바로 이용하지 않고 255를 이용하는 것과 같이 신기한 모습들도 볼 수 있다. 정확한 이유는 아직 잘 모르겠다.
그 외 참고자료:
docker 외부의 파일을 docker 내부로 복사해 이용하고 싶은 경우 아래를 참고하자