“pstree”を使ってあるプロセスの子プロセス・孫プロセスを確認する
はじめに
子プロセスをバックグラウンド起動して並列処理行うシェルスクリプトを作成したが以下の点を確認したいと思いました。
- 子プロセスが正しく立ち上がっているのか?
- 子プロセスが過剰に立ち上がっていないか?
- 子プロセスはどのぐらいの期間生存しているのか?
確認する方法を以下にまとめます。
検証環境
今回も検証環境として Docker を使いました。
もちろんDockerを使う必要はないのですが、クリーンな環境が欲しかったので利用しました。
$ docker run --rm -v $PWD:/mnt -it genzouw/centos-sandbox bash
$ uname -a
Linux 0869a1789807 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
$ bash -version
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
pstreeコマンド
pstree
は、現在動作しているプロセスをツリー形式で表示するコマンドです。
コマンド名のとおり、「どのプロセスからどのプロセスが起動しているのか」という ツリー構造 が分かりやすく表示されるので、プロセスの実行状況を確認するのに便利です。
pstree
コマンドのインストール
早速実行してみます。
$ pstree
bash: pstree: command not found
いきなりですが、「コマンドが見つからない」というエラーが発生しました。
普通にCD/DVDからインストールしたLinuxディストリビューションにはインストール済みかと思いますが、 Docker 環境は軽量化のために必要最低限のコマンドしかインストールされていないことが多いです。
インストールする場合は以下のコマンドを実行します。
$ yum install -y psmisc
出力される内容を見てみる
早速実行してみます。
いくつかの環境で試してみます。
Docker環境の場合
$ pstree
bash---pstree
なんだかよくわからない表示がされていますね。
CentOS7環境の場合
ちなみに「さくらのVPS」上のCentOS7で実行した結果は次のとおりです。
$ pstree
systemd─┬─NetworkManager───2*[{NetworkManager}]
├─abrt-dbus───2*[{abrt-dbus}]
├─abrt-watch-log
├─abrtd
├─agetty
├─anacron───run-parts─┬─awk
│ └─yum-cron
├─atd
├─auditd───{auditd}
├─containerd─┬─containerd-shim─┬─apache2───5*[apache2]
│ │ └─9*[{containerd-shim}]
│ └─14*[{containerd}]
├─crond
CentOS6環境の場合
また別環境のCentOS6で実行した結果は以下の通りです。
$ pstree
init─┬─atd
├─auditd───{auditd}
├─17*[bash]
├─2*[bash───awk]
├─bash───tail
├─cat
├─crond───crond───bash─┬─grep
│ ├─2*[sed]
│ └─ssh
├─cupsd
プロセスツリー
環境によって、出力されている内容が異なりますね。
ツリー上に表示された内容は「プロセスツリー」と呼ばれます。
Linux上の全てのプロセスは必ず他のプロセスの子プロセスとなります。
ただし、例外がいて、「すべてのプロセスの親」となるプロセスが存在し、これには「親プロセス」が存在しません。
Linuxだと大体 init
もしくは systemd
というプログラムが必ず1番目のプロセス(PID:1)となります。
Linux上で動くすべてのプログラムは、 init
または systemd
の子プロセス・孫プロセスであると言えます。
ユーザーが実行するプログラムはシェルから実行されますが、そのシェルも元をたどればinitから実行されたプログラムです。
本当に「プロセスツリー」のルートとなっているプロセスはPID=1となっているか確認してみましょう。
ps 1
でPID=1 のプロセスを確認できます。
Docker環境のルートプロセス
$ ps 1
PID TTY STAT TIME COMMAND
1 pts/0 Ss 0:00 bash
CentOS7環境のルートプロセス
$ ps 1
PID TTY STAT TIME COMMAND
1 ? Ss 135:10 /usr/lib/systemd/systemd --system --deserialize 21
CentOS6環境のルートプロセス
$ ps 1
PID TTY STAT TIME COMMAND
1 ? Ss 3:20 /sbin/init
Dockerのルートプロセスについて
Linux上で動くすべてのプログラムは、
init
またはsystemd
の子プロセス・孫プロセスであると言えます。
と断っていながら、Dockerは bash
となっていますね。
Dcokerの思想と関係がありますが、Dockerは基本的に割り当てられた環境内で「1つのことを行う」ためのソフトウェアです。
起動時に以下のようなコマンドを実行しましたが、コマンドの最終引数に指定されたコマンド(ここではbash
)がDockerのルートプロセスとなります。
$ docker run --rm -v $PWD:/mnt -it genzouw/centos-sandbox bash
もう少しpstree
を触ってみる
Docker環境内でもう少し触ってみます。
子プロセスを2つ立ち上げて、表示がどうなるかを見てみます。
$ bash -c 'while :; do date; done > list' &
[1] 17600
$ bash -c 'while :; do date; done > list' &
[2] 19762
$ pstree
bash-+-2*[bash---bash]
`-pstree
ノードが2つしか表示されていません。
同じコマンドのプロセスが複数実行されている場合には、マージされます。-c
オプションでマージさせないようにすることができます。
$ pstree -c
bash-+-bash---date
|-bash
`-pstree
$ pstree -c
bash-+-bash---date
|-bash---date
`-pstree
タイミングによって、bash
プロセスが date
コマンドを実行しておりツリーの表示内容が変わっています。
それぞれのプロセスIDも追加で表示したい場合は-p
オプションを指定します。
$ pstree -p
bash(1)-+-bash(17600)
|-bash(19762)---date(95091)
`-pstree(95086)
特定のプロセスをプロセスツリーのルートとして表示する場合は引数にプロセスIDを指定します。
$ pstree 19762
bash---date
Dcoker環境とその他の環境でpstree
の表示内容が異なっていましたが、同じ表示に合わせるためには-U
オプションを指定します。
$ pstree
bash-+-2*[bash]
`-pstree
$ pstree -U
bash─┬─bash───date
├─bash───bash
└─pstree
ひとこと
あまりトラブルシューティングの際に使わないですね。
デバッグのときぐらいかな。
ディスカッション
コメント一覧
まだ、コメントがありません