Edited at

psコマンドでプロセスの一覧を見よう


Linuxでプロセスの一覧を見たい

Linux環境で、プロセスの一覧を見たい場合に出てくるのは、psコマンドだと思います。

「今動いてるプロセスを見たい」、「このプロセス、今いるっけ?」といった声が挙がる場で、よく使われるコマンドだと思います。

注)本投稿は、Ubuntu Linux 18.04 LTSで確認しております

$ lsb_release -a

No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.1 LTS
Release: 18.04
Codename: bionic

オプションって、どうしましょうか?自分の観測範囲だと、以下の2つが多い気がします。

$ ps aux

$ ps -ef

-がないのは、BSDスタイルオプションというやつですね。

出力例。

$ ps aux

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 225536 8684 ? Ss 08:56 0:05 /sbin/init splash
root 2 0.0 0.0 0 0 ? S 08:56 0:00 [kthreadd]
root 4 0.0 0.0 0 0 ? I< 08:56 0:00 [kworker/0:0H]
root 6 0.0 0.0 0 0 ? I< 08:56 0:00 [mm_percpu_wq]

〜省略〜

$ ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 08:56 ? 00:00:05 /sbin/init splash
root 2 0 0 08:56 ? 00:00:00 [kthreadd]
root 4 2 0 08:56 ? 00:00:00 [kworker/0:0H]
root 6 2 0 08:56 ? 00:00:00 [mm_percpu_wq]

〜省略〜

それぞれ、表示内容が異なりますね。

ps auxだと、CPU使用率やメモリに関する情報が取得できます。ざっと確認するなら、まずはこちらで。

ps -efだと、親プロセスのID(PPID)が表示されています。親プロセスが気になることもあるので、これはこれで便利です。

ちなみに、親子関係を見るだけならauxオプションでもfを足すと階層構造表示なら可能です。

$ ps auxf

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 2 0.0 0.0 0 0 ? S 08:56 0:00 [kthreadd]
root 4 0.0 0.0 0 0 ? I< 08:56 0:00 \_ [kworker/0:0H]
root 6 0.0 0.0 0 0 ? I< 08:56 0:00 \_ [mm_percpu_wq]
root 7 0.0 0.0 0 0 ? S 08:56 0:01 \_ [ksoftirqd/0]
root 8 0.0 0.0 0 0 ? I 08:56 0:08 \_ [rcu_sched]
root 9 0.0 0.0 0 0 ? I 08:56 0:00 \_ [rcu_bh]
root 10 0.0 0.0 0 0 ? S 08:56 0:00 \_ [migration/0]
root 11 0.0 0.0 0 0 ? S 08:56 0:00 \_ [watchdog/0]
root 12 0.0 0.0 0 0 ? S 08:56 0:00 \_ [cpuhp/0]

〜省略〜

各オプションの意味ですが、こちらを参照。

【 ps 】コマンド――実行中のプロセスを一覧表示する



  • a … 端末を持つ全てのプロセスを表示する


  • u … ユーザー指向のフォーマットで表示する


  • x … 端末を持たない全てのプロセスを表示する


  • -e … 全てのプロセスを表示する


  • f … 階層表示する


特定の項目でソートしたい

psコマンドの結果を、特定の項目でソートしたいことがあるかもしれません。

k(または--sort)オプションを使いましょう。

例えば、以下のコマンドでCPU使用率でソートできます。

$ ps aux k -pcpu

メモリなら。

$ ps aux k -pmem

$ ps aux k -rss

kの後に-フォーマットで指定するのは、manで見るか、以下のページを見たりするとよいでしょう。

PS / 標準フォーマット指定子


スレッドのIDを表示したい

psコマンドに、-Lオプションを付けると、表示内容にLWP(軽量プロセスまたはスレッドのID)と、NLWP(プロセスにおけるスレッドの数)が追加されます。

$ ps aux -L | head -n 5

USER PID LWP %CPU NLWP %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 1 0.0 1 0.0 225536 8700 ? Ss 08:56 0:05 /sbin/init splash
root 2 2 0.0 1 0.0 0 0 ? S 08:56 0:00 [kthreadd]
root 4 4 0.0 1 0.0 0 0 ? I< 08:56 0:00 [kworker/0:0H]
root 6 6 0.0 1 0.0 0 0 ? I< 08:56 0:00 [mm_percpu_wq]

これで、プロセスから1段掘り下げて、スレッド単位でCPUの情報を見ることができます。


Javaのスレッドダンプと紐付けよう

なんとなく、表示されたLWPの情報とJavaのスレッドダンプと紐付けてみます。

Apache Tomcatで試してみましょう。ダウンロードして、起動。

$ java -version

openjdk version "1.8.0_191"
OpenJDK Runtime Environment (build 1.8.0_191-8u191-b12-0ubuntu0.18.04.1-b12)
OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)

$ wget http://ftp.jaist.ac.jp/pub/apache/tomcat/tomcat-9/v9.0.14/bin/apache-tomcat-9.0.14.tar.gz
$ tar xf apache-tomcat-9.0.14.tar.gz
$ cd apache-tomcat-9.0.14
$ bin/startup.sh

jcmdでスレッドダンプの取得。

$ jcmd [PID] Thread.print

ここでは、PIDが21017のものを使って実例を見てみます。

nid=の部分が、スレッドのIDです。

$ jcmd 21017 Thread.print | grep nid=

"Attach Listener" #44 daemon prio=9 os_prio=0 tid=0x00007f20bc001000 nid=0x5298 waiting on condition [0x0000000000000000]
"ajp-nio-8009-Acceptor-0" #42 daemon prio=5 os_prio=0 tid=0x00007f20fc7fa800 nid=0x5260 runnable [0x00007f206b0ef000]
"ajp-nio-8009-ClientPoller-1" #41 daemon prio=5 os_prio=0 tid=0x00007f20fc7f8800 nid=0x525f runnable [0x00007f206b1f0000]
"ajp-nio-8009-ClientPoller-0" #40 daemon prio=5 os_prio=0 tid=0x00007f20fc7dd800 nid=0x525e runnable [0x00007f206b2f1000]
"ajp-nio-8009-exec-10" #39 daemon prio=5 os_prio=0 tid=0x00007f20fc7c3000 nid=0x525d waiting on condition [0x00007f206b3f2000]
"ajp-nio-8009-exec-9" #38 daemon prio=5 os_prio=0 tid=0x00007f20fc7c1000 nid=0x525c waiting on condition [0x00007f206b4f3000]
"ajp-nio-8009-exec-8" #37 daemon prio=5 os_prio=0 tid=0x00007f20fc7bf000 nid=0x525b waiting on condition [0x00007f206b5f4000]
"ajp-nio-8009-exec-7" #36 daemon prio=5 os_prio=0 tid=0x00007f20fc7bd800 nid=0x525a waiting on condition [0x00007f206b6f5000]
"ajp-nio-8009-exec-6" #35 daemon prio=5 os_prio=0 tid=0x00007f20fc7bb800 nid=0x5259 waiting on condition [0x00007f206b7f6000]
"ajp-nio-8009-exec-5" #34 daemon prio=5 os_prio=0 tid=0x00007f20fc7ba000 nid=0x5258 waiting on condition [0x00007f206b8f7000]
"ajp-nio-8009-exec-4" #33 daemon prio=5 os_prio=0 tid=0x00007f20fc7b8800 nid=0x5257 waiting on condition [0x00007f206b9f8000]
"ajp-nio-8009-exec-3" #32 daemon prio=5 os_prio=0 tid=0x00007f20fc7b6800 nid=0x5256 waiting on condition [0x00007f206baf9000]
"ajp-nio-8009-exec-2" #31 daemon prio=5 os_prio=0 tid=0x00007f20fc770000 nid=0x5255 waiting on condition [0x00007f206bbfa000]
"ajp-nio-8009-exec-1" #30 daemon prio=5 os_prio=0 tid=0x00007f20fc76e000 nid=0x5254 waiting on condition [0x00007f206bcfb000]
"http-nio-8080-Acceptor-0" #29 daemon prio=5 os_prio=0 tid=0x00007f20fc76d000 nid=0x5253 runnable [0x00007f206bdfc000]
"http-nio-8080-ClientPoller-1" #28 daemon prio=5 os_prio=0 tid=0x00007f20fc76a000 nid=0x5252 runnable [0x00007f206befd000]
"http-nio-8080-ClientPoller-0" #27 daemon prio=5 os_prio=0 tid=0x00007f20fc768000 nid=0x5251 runnable [0x00007f206bffe000]
"http-nio-8080-exec-10" #26 daemon prio=5 os_prio=0 tid=0x00007f20fc765800 nid=0x5250 waiting on condition [0x00007f20d013b000]

-qで、対象のPIDに絞ってプロセスの情報を表示。

$ ps aux -L -q 21017

USER PID LWP %CPU NLWP %MEM VSZ RSS TTY STAT START TIME COMMAND
xxxxx 21017 21017 0.0 48 0.9 6979556 127592 pts/9 Sl 12:41 0:00 /usr/lib/jvm/java-8-openjdk-amd64/bin/java -Djava.util.logging.config.file=.....
xxxxx 21017 21018 0.4 48 0.9 6979556 127592 pts/9 Sl 12:41 0:01 /usr/lib/jvm/java-8-openjdk-amd64/bin/java -Djava.util.logging.config.file=.....
xxxxx 21017 21019 0.0 48 0.9 6979556 127592 pts/9 Sl 12:41 0:00 /usr/lib/jvm/java-8-openjdk-amd64/bin/java -Djava.util.logging.config.file=.....
xxxxx 21017 21020 0.0 48 0.9 6979556 127592 pts/9 Sl 12:41 0:00 /usr/lib/jvm/java-8-openjdk-amd64/bin/java -Djava.util.logging.config.file=.....
xxxxx 21017 21021 0.0 48 0.9 6979556 127592 pts/9 Sl 12:41 0:00 /usr/lib/jvm/java-8-openjdk-amd64/bin/java -Djava.util.logging.config.file=.....

〜省略〜

ここでは、LWPが21067のものを対象にしてみましょう。

jcmdの結果だと、スレッドのIDは16進数表示だったので、例えばprintfで表記変更します。

$ printf '%#x' 21067

0x524b

これをjcmdの結果と合わせて、絞り込めばよいわけですね。

$ jcmd 21017 Thread.print | grep `printf '%#x' 21067`

"http-nio-8080-exec-5" #21 daemon prio=5 os_prio=0 tid=0x00007f20fc75c800 nid=0x524b waiting on condition [0x00007f20d0640000]

nid=0x524bのスレッドがヒットしました。これを利用すると、CPUを消費しているスレッドを特定し、そのスタックトレースを見る、といったことができるようになります。

実際には、スタックトレースも一緒に見ると思うので、grepで表示情報も絞ることはしないと思いますが、紐付けの参考として。