내 응용 프로그램 중 하나에서 생성된 단기 프로세스의 동작을 이해하려고 합니다. 제가 이해한 과정은 다음과 같습니다.
- 프로세스 이름의 일부입니다.
- 이 프로세스를 생성할 애플리케이션의 이름과 PID입니다.
- 대략 프로세스가 시작되는 시간입니다(5~10분 이내).
- 프로세스가 종료된 후 프로세스의 PID입니다.
이상적으로는 다음을 원합니다.
- 커널(또는 다른 것)이 프로세스가 시작되었음을 스크립트에 알리도록 합니다.
- 프로세스에 대해 여러 도구(iostat, strace 등)를 실행합니다.
프로세스가 시작되었음을 커널이 나에게 알리도록 하여 내가 이에 대한 조치를 취할 수 있도록 하는 방법이 있습니까?
그런 식으로 실행하는 것은 while true; do ps -ef | grep ${MY_PROCESS_NAME}; done
투박하고 끔찍해 보입니다. 무차별 대입 검색보다는 이런 일이 발생했을 때 알림을 받을 수 있었으면 좋겠습니다.
아니면 상위 프로세스와 모든 하위 프로세스에 대해 이러한 도구를 실행한 다음 나중에 출력을 필터링합니까? 예를 들어, strace -ff -o ./some.trace -p ${PARENT_PID}
.
답변1
한 번 살펴보고 싶을 수도 있습니다모니터링 실행(커널이 일반적으로 CONFIG_FTRACE로 구성되어 있다고 가정합니다.) 이것은 Brendan Gregg Tracking and Performance Collection의 많은 스크립트 중 하나입니다. 인수가 없으면 시작 시 시스템의 모든 명령을 표시하거나 정규식을 제공하여 감시할 수 있습니다.
zsh
예를 들어 시작될 수 있는 기존 명령이나 새 명령을 찾으려면 다음을 수행합니다.
sudo /opt/perf-tools-master/bin/execsnoop zsh
새 zsh를 시작하면 다음 출력이 표시됩니다.
Tracing exec()s issued by process name "zsh". Ctrl-C to end.
Instrumenting sys_execve
PID PPID ARGS
21920 21919 /usr/libexec/grepconf.sh -c
21923 21922 /usr/bin/tty -s
21922 21919 /usr/bin/tput colors
21924 21919 /usr/bin/dircolors --sh /etc/DIR_COLORS.256color
21925 21919 /usr/bin/grep -qi ^COLOR.*none /etc/DIR_COLORS.256color
21926 21919 /usr/libexec/grepconf.sh -c
21928 21919 /usr/libexec/grepconf.sh -c
21930 21919 uname -m
21932 21919 /bin/grep -q /usr/lib64/qt-3.3/bin
21934 21933 /usr/bin/id -u
실행 중인 프로그램의 전체 이름을 알고 나면 일반적으로 후크를 추가한 후 원래 프로그램을 실행하는 스크립트로 파일을 대체하게 됩니다. 이렇게 할 수 없는 경우 비슷한 방법을 사용하여 fanotify(7)
열려 있는 각 파일이 완료되기 전에 스누핑 프로그램이 개입하도록 할 수 있습니다. 아니면 프로세스에 inotifywatch
추가할 수 있을 만큼 충분히 빠를 수도 있습니다.strace
답변2
보세요sysdig
, 시스템 호출을 모니터링할 수 있는 도구입니다. 프로세스를 생성할 프로세스의 pid를 알고 있는 경우 다음을 수행할 수 있습니다.
$ sudo sysdig proc.ppid=<PID>
이는 주어진 PID를 가진 프로세스에 대해 상위 PID가 수행한 모든 시스템 호출에 대한 출력을 생성합니다. 대상 프로그램의 전체 이름을 알고 있는 경우 이를 필터에 포함할 수 있습니다.
$ sudo sysdig proc.ppid=<PID> and proc.name=<NAME>
이는 대체에 적합한 것을 제공할 것입니다 strace
. 예를 들어, 위 명령을 사용하여 쉘을 모니터링하고 다음 명령의 실행을 찾습니다 ls
.
$ sudo sysdig proc.ppid=18659 and proc.name=ls
9762 16:07:05.911583406 0 ls (20545) < execve res=0 exe=ls args=-F.--color=auto. tid=20545(ls) pid=20545(ls) ptid=18659(zsh) cwd= fdlimit=1024 pgft_maj=0 pgft_min=69 vm_size=452 vm_rss=16 vm_swap=0 comm=ls cgroups=cpuset=/.cpu=/.cpuacct=/.io=/.memory=/.devices=/.freezer=/.net_cls=/.perf_eve... env=LANG=en_US.utf8.USER=user.LOGNAME=user.HOME=/home/user.PATH=/usr/loc... tty=34818 pgid=20545(ls) loginuid=1000
9763 16:07:05.911608835 0 ls (20545) > brk addr=0
9764 16:07:05.911609493 0 ls (20545) < brk res=557E882FF000 vm_size=452 vm_rss=176 vm_swap=0
9765 16:07:05.911652583 0 ls (20545) > access mode=4(R_OK)
9766 16:07:05.911657425 0 ls (20545) < access res=-2(ENOENT) name=/etc/ld.so.preload
9767 16:07:05.911663159 0 ls (20545) > openat
9768 16:07:05.911686542 0 ls (20545) < openat fd=3(<f>/etc/ld.so.cache) dirfd=-100(AT_FDCWD) name=/etc/ld.so.cache flags=4097(O_RDONLY|O_CLOEXEC) mode=0 dev=800
9769 16:07:05.911688872 0 ls (20545) > fstat fd=3(<f>/etc/ld.so.cache)
9770 16:07:05.911690846 0 ls (20545) < fstat res=0
9771 16:07:05.911691850 0 ls (20545) > mmap addr=0 length=44827 prot=1(PROT_READ) flags=2(MAP_PRIVATE) fd=3(<f>/etc/ld.so.cache) offset=0
9772 16:07:05.911694436 0 ls (20545) < mmap res=7FD38EDE7000 vm_size=496 vm_rss=256 vm_swap=0
9773 16:07:05.911695345 0 ls (20545) > close fd=3(<f>/etc/ld.so.cache)
9774 16:07:05.911695808 0 ls (20545) < close res=0
...
11068 16:07:05.913562304 0 ls (20545) > close fd=1(<f>/dev/pts/2)
11069 16:07:05.913562881 0 ls (20545) < close res=0
11070 16:07:05.913564527 0 ls (20545) > close fd=2(<f>/dev/pts/2)
11071 16:07:05.913564857 0 ls (20545) < close res=0
11072 16:07:05.913572008 0 ls (20545) > exit_group
11073 16:07:05.913622981 0 ls (20545) > procexit status=0
너는 볼 수있어사용자 설명서필터링 및 필터링이 생성하는 정보를 구성하는 추가 옵션을 확인하세요. 이를 통해 인쇄 내용을 사용자 정의하고 스크립트에서 해당 출력을 읽은 다음 원하는 다른 도구를 실행할 수 있습니다.
답변3
strace
on 과 함께 -f
사용됩니다 bash
. 쉘에서 단기 프로그램을 시작하십시오.
실행하는 데 0.1초 이상 걸리는 시스템 호출의 출력을 필터링하는 방법은 다음과 같습니다. 32330은 내 쉘의 PID입니다. 나는 "read(0")을 무시합니다. 왜냐하면 이것이 내 쉘에서 나오고 쉘이 입력을 기다리고 있기 때문에 이미 오랜 시간이 걸리기 때문입니다.
$ strace -p 32330 -f -T -tt |&
awk '$2 != "read(0," {
elapsed=$(NF)
l=length(elapsed)
elapsed=substr(elapsed,2,l-2)+0
if (elapsed>0.1) {
print
}
}'
sleep 2
쉘에서 실행했을 때의 출력입니다.
[pid 28454] 17:09:34.271522 nanosleep({2, 0}, NULL) = 0 <2.000138>
17:09:36.271900 <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WSTOPPED|WCONTINUED, NULL) = 28454 <2.002035>