htopがpsよりも多くのプロセスを表示するのはなぜですか
1. 概要
Linuxユーザーとして、システムで実行されているプロセスの総数を特定したいことがよくあります。 さらに、特定のプログラムまたはコマンドが何をしているのかを調査したい場合があります。 これを実現するには、htopやpsなどのさまざまなツールを利用できます。
このチュートリアルでは、プロセスとスレッドを監視しながら、これらのコマンドの出力を確認します。
2. htopのインストール方法
htop は、実行中のプロセスとスレッドをリアルタイムで表示および管理できるインタラクティブなツールです。 また、CPUやメモリの使用状況などのシステムリソースを監視するための非常に便利なコマンドです。
このユーティリティをUbuntu/DebianとCentOSにそれぞれインストールする方法を見てみましょう。
Ubuntu / Debianの場合:
$ sudo apt install htop
CentOSの場合:
$ yum install epel-release
$ yum install htop
$ htop -v
htop 2.2.0 - (C) 2004-2019 Hisham Muhammad
Released under the GNU GPL.
次のセクションでは、htopのバージョン2.2.0を使用します。
3. htopとpsの出力の比較
htopとpsはどちらもプロセスマネージャーです。 特定のプロセスに対してデフォルトで何が表示されるかを見てみましょう。
3.1. mysqldプロセスをhtopで確認してください
htopを使用すると、コマンドラインからの出力を特定のプロセスIDに制限できます。 手元の問題を説明するために、MariaDBサーバープロセスIDを値として-pidオプションに渡します。
$ htop --pid=$(pidof mysqld)
1 [|| 2.6%] Tasks: 51, 43 thr; 2 running
2 [ 0.0%] Load average: 0.00 0.02 0.05 Mem[||||||||||||||||||||||||||||||||||||||||||||| 397M/991M] Uptime: 04:45:44
Swp[ 0K/2.00G]
PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
17173 mysql 20 0 948M 88316 7108 S 0.7 8.7 0:00.73 /usr/libexec/mysqld --basedir=/usr --datadir=/data/lib/mysql --plugin-dir=/usr/lib64/mysql/
17184 mysql 20 0 948M 88316 7108 S 0.0 8.7 0:00.03 /usr/libexec/mysqld --basedir=/usr --datadir=/data/lib/mysql --plugin-dir=/usr/lib64/mysql/
17177 mysql 20 0 948M 88316 7108 S 0.0 8.7 0:00.03 /usr/libexec/mysqld --basedir=/usr --datadir=/data/lib/mysql --plugin-dir=/usr/lib64/mysql/
...
17193 mysql 20 0 948M 88316 7108 S 0.0 8.7 0:00.00 /usr/libexec/mysqld --basedir=/usr --datadir=/data/lib/mysql --plugin-dir=/usr/lib64/mysql/
17202 mysql 20 0 948M 88316 7108 S 0.0 8.7 0:00.00 /usr/libexec/mysqld --basedir=/usr --datadir=/data/lib/mysql --plugin-dir=/usr/lib64/mysql/
17203 mysql 20 0 948M 88316 7108 S 0.0 8.7 0:00.00 /usr/libexec/mysqld --basedir=/usr --datadir=/data/lib/mysql --plugin-dir=/usr/lib64/mysql/
F1Help F2Setup F3Search F4Filter F5Tree F6SortByF7Nice -F8Nice +F9Kill F10Quit
ここでは、 pidof コマンドを使用して、実行中のMariaDBプログラム名のPIDを検索します。 次に、コマンド置換を使用して、 pidofmysqldコマンドを実際の出力に置き換えます。
3.2. mysqldプロセスをpsで一覧表示します
一方、grepコマンドとpsを組み合わせて、mysqldプロセスIDに基づいて出力をフィルタリングしてみましょう。
$ ps -e -o pid,user,command | grep $(pidof mysqld) | grep -v grep
17173 mysql /usr/libexec/mysqld --basedir=/usr --datadir=/data/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --log-error=/data/lib/mysql/log/mariadb.log --pid-file=/data/lib/mysql/run/mariadb.pid --socket=/data/lib/mysql/mysql.sock
上記では、-eオプションをpsに渡してすべてのプロセスを選択し、-oオプションを渡して特定のフィールドのみを印刷します。 さらに、grepコマンドを-vオプションとともに使用して、grep自体を最終出力から除外します。
htopは、ps出力と比較してより多くのプロセスを表示します。 次のセクションでは、取得したばかりの出力について説明します。
4. プロセスの数が異なるのはなぜですか?
htopとpsの両方が、 /procファイルシステムから実行中のプロセスとスレッドの数に関する詳細を読み取ったことがわかりました。 より具体的には、 / proc /
下のサブディレクトリをリストして数えましょう / proc /
$ ls /proc/$(pidof mysqld)/task
17173 17177 17178 17179 17180 17181 17182 17183 17184 17185 17186 17188 17189 17190 17191 17192 17193 17202 17203
$ ls -1 /proc/$(pidof mysqld)/task | wc -l
19
上記の出力から、 ps とは異なり、htopコマンドは実行中のプロセスとそれに対応する個々のスレッドをデフォルトで表示すると推測します。
htop は、システムで何が起こっているかについて可能な限り多くの情報を提供するように設計されています。 その結果、ユーザースレッドを非表示にするのではなく、表示します。 たとえば、システム管理者は、関連するスレッドのCPU使用率を監視しながら、マルチスレッドアプリケーションの問題を見つけることができます。 ただし、一部のLinuxユーザーは、 htop 出力にすべてのスレッドを表示するのはあまり役に立たないため、この設定を無効にすることを好みます。
5. htopを使用するスレッド
Linuxには、ユーザースペースとカーネルスペーススレッドがあります。 ユーザースレッドはユーザーアプリケーションに関連付けられており、カーネルスレッドはOSによって作成および管理されます。
htopは、デフォルトで、ユーザースレッドを表示し、カーネルスレッドを非表示にします。 次に、この動作を変更する方法を確認しましょう。
5.1. ユーザースレッド
htop 構成をカスタマイズして、ユーザースレッドの可視性を無効にすることができます。 これを実証するために、 htop –pid = $(pidof mysqld)、を実行してから次のようにします。
- セットアップに移動します
- 表示オプション
- ユーザーランドプロセススレッドを非表示にするをチェックします
- F10を押す
同様に、 H を押すだけで、ユーザースレッドを非表示にできます。
上記の変更に続いて、出力をメインのMariaDBプロセスのみに制限します。
PPID PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
17007 17173 mysql 20 0 948M 88316 7108 S 0.7 8.7 0:01.07 /usr/libexec/mysqld --basedir=/usr --datadir=/data/lib/mysql --plugin-dir=/usr/lib64/
これで、psが示すのと同じプロセスが表示されます。 さらに、2つのプロセスマネージャー間の別の比較ポイントを調べてみましょう。
5.2. カーネルスレッド
バージョン2.2.0以降、 htopは、/proc/かどうかをチェックしてカーネルスレッドを識別します。
デフォルトで無効になっているカーネルスレッドを一覧表示できます。 まず、 htop を起動してから、新しい列を追加しましょう。
- セットアップに移動します
- 列
- 利用可能な列
- PPID列を選択します
次に、Kを押してみましょう。
PPID PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
2 20265 root 20 0 0 0 0 S 0.7 0.0 0:00.08 kworker/1:1
17007 17173 mysql 20 0 948M 88316 7108 S 0.0 8.7 0:01.17 /usr/libexec/mysqld --basedir=/usr --datadir=/data/lib/mysql --plugin-dir=/usr/lib64/
17007 17182 mysql 20 0 948M 88316 7108 S 0.0 8.7 0:00.06 /usr/libexec/mysqld --basedir=/usr --datadir=/data/lib/mysql --plugin-dir=/usr/lib64/
...
2 14 root 20 0 0 0 0 S 0.0 0.0 0:00.18 ksoftirqd/1
2 16 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/1:0H
2 18 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kdevtmpfs
上記から、カーネルスレッドもわかります。 たとえば、 kworker / 0:0H で、 PPID = 2( Kthreadd を親プロセスとして)。
さらに、 htop 出力の右上部分には、実行中のプロセス全体に関するいくつかの有用な情報が表示されます。
Tasks: 53, 43 thr, 78 kthr; 2 running
これは、 htop によると、合計53のプロセス、43のユーザースレッド、78のカーネルスレッド、および2つのタスクが実行状態にあることを意味します。 それをpsと比較してみましょう。
6. psでスレッドを一覧表示する方法
デフォルトのps出力を変更して、プロセスだけでなくスレッドの詳細を表示することができます。 すべてのプロセスを選択してスレッドを表示するには、-eLfフラグをpsコマンドに渡すことができます。
例として、ヘッダー名を保持したまま、出力を最初の5つのmysqldスレッドに制限しましょう。
$ ps -eLf | head -n 1 ; ps -eLf | grep $(pidof mysqld) | head -n 5
UID PID PPID LWP C NLWP STIME TTY TIME CMD
mysql 17173 17007 17173 0 19 13:30 ? 00:00:00 /usr/libexec/mysqld --basedir=/usr --datadir=/data/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --log-error=/data/lib/mysql/log/mariadb.log --pid-file=/data/lib/mysql/run/mariadb.pid --socket=/data/lib/mysql/mysql.sock
mysql 17173 17007 17177 0 19 13:30 ? 00:00:00 /usr/libexec/mysqld --basedir=/usr --datadir=/data/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --log-error=/data/lib/mysql/log/mariadb.log --pid-file=/data/lib/mysql/run/mariadb.pid --socket=/data/lib/mysql/mysql.sock
mysql 17173 17007 17178 0 19 13:30 ? 00:00:00 /usr/libexec/mysqld --basedir=/usr --datadir=/data/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --log-error=/data/lib/mysql/log/mariadb.log --pid-file=/data/lib/mysql/run/mariadb.pid --socket=/data/lib/mysql/mysql.sock
mysql 17173 17007 17179 0 19 13:30 ? 00:00:00 /usr/libexec/mysqld --basedir=/usr --datadir=/data/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --log-error=/data/lib/mysql/log/mariadb.log --pid-file=/data/lib/mysql/run/mariadb.pid --socket=/data/lib/mysql/mysql.sock
mysql 17173 17007 17180 0 19 13:30 ? 00:00:00 /usr/libexec/mysqld --basedir=/usr --datadir=/data/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --log-error=/data/lib/mysql/log/mariadb.log --pid-file=/data/lib/mysql/run/mariadb.pid --socket=/data/lib/mysql/mysql.sock
上記の例では、 -Lf オプションを組み合わせて、 LWP (スレッドID)列と NLWP (スレッド数)列を追加します。 NLWP列は、19個のmysqldスレッドがあることを示しています。
最後に、-ppidおよび-p オプションを渡して、それぞれ親プロセスIDおよびプロセスIDに基づいて選択することにより、カーネルスレッドの数を表示およびカウントできます。
$ ps --ppid 2 -p 2 --format pid,ppid,time,cmd
PID PPID TIME CMD
2 0 00:00:00 [kthreadd]
4 2 00:00:00 [kworker/0:0H]
6 2 00:00:00 [ksoftirqd/0]
7 2 00:00:00 [migration/0]
8 2 00:00:00 [rcu_bh]
9 2 00:00:01 [rcu_sched]
10 2 00:00:00 [lru-add-drain]
11 2 00:00:00 [watchdog/0]
...
6570 2 S 00:00:00 [kworker/1:0]
25359 2 S 00:00:00 [kworker/0:0]
25761 2 S 00:00:00 [kworker/1:2]
26957 2 S 00:00:00 [kworker/0:2]
この場合、-formatフラグを使用して列を指定します。
上記の出力から、カーネルスレッドkthreadd(PID = 2)とそのすべての子(PPID = 2)を一覧表示します。
最後に、 htop で行ったように、カーネルスレッドの総数を数えましょう。
$ ps --ppid 2 -p 2 --format pid,ppid,state,time,cmd | tail -n +2 | wc -l
78
tail コマンドを使用して、最初の列ヘッダーのカウントをスキップします。
上記のように、 ps コマンドで表示されるカーネルスレッドの数は、htopで表示されるkthrの数と同じです。
7. 結論
この記事では、htopコマンドとpsコマンドの両方について説明しました。 ただし、主にそれぞれの出力の比較に焦点を当てています。 主な質問に答えるために、両方のコマンドの出力を変更して同じ数のプロセスとスレッドを取得する方法を見てきました。