私は、自分のアプリケーションの1つによって作成された短期間のプロセスの動作について学習しようとしています。私はこのプロセスについて次のことを知っています。
理想的には、次のことを行います。
特定のプロセスが開始されたことをカーネルに通知して、何らかのアクションを実行できるようにする方法はありますか?
while true; do ps -ef | grep ${MY_PROCESS_NAME}; done
のようなものを実行することは、かさばり、悪いようです。力ずくで検索するのではなく、発生したときに通知を受け取ることができるようにしたいと思います。
または、親プロセスとすべての子プロセスに対してツールを実行し、後で出力をフィルタリングする必要がありますか?たとえば、strace -ff -o ./some.trace -p ${PARENT_PID}
です。
execsnoop を確認することをお勧めします(カーネルがCONFIG_FTRACEで構成されていると仮定します。これは通常の場合です)。これは、BrendanGreggトレースおよびパフォーマンスコレクションからの多くのスクリプトの1つです。引数がない場合、システムで起動するすべてのコマンドが表示されます。または、監視する正規表現を指定することもできます。
たとえば、既存または新規の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
をアタッチするのに十分な速度です。
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
フィルタリングとそれが生成する情報を構成するためのその他のオプションについては、 ユーザーガイド を参照してください。これにより、印刷内容をカスタマイズし、スクリプトにその出力を読み取らせてから、他の任意のツールを実行できます。