단기 프로세스 추적

단기 프로세스 추적

내 응용 프로그램 중 하나에서 생성된 단기 프로세스의 동작을 이해하려고 합니다. 제가 이해한 과정은 다음과 같습니다.

  1. 프로세스 이름의 일부입니다.
  2. 이 프로세스를 생성할 애플리케이션의 이름과 PID입니다.
  3. 대략 프로세스가 시작되는 시간입니다(5~10분 이내).
  4. 프로세스가 종료된 후 프로세스의 PID입니다.

이상적으로는 다음을 원합니다.

  1. 커널(또는 다른 것)이 프로세스가 시작되었음을 스크립트에 알리도록 합니다.
  2. 프로세스에 대해 여러 도구(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

straceon 과 함께 -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>

관련 정보