psの操作に慣れる

Linuxなどで実行中のプロセスを表示させるコマンドにpsというのがあります。
これまでこのコマンドをかなり適当に使ってきていて、オプションとかよくわかってなかったのでmanをちゃんと読んでいろいろやってみました。

psコマンドはprocpsというパッケージに含まれるコマンドです。
procpsには他にtop, vmstat, w, kill, free, slabtop, skillといったコマンドが含まれているようです。

ここではFedora Core 6で以下のバージョンを使っています。

$ ps --version
procps version 3.2.7

オプションの指定方法

オプションの指定方法にいくつかの方法があるので把握しておきます。

  1. UNIX オプション。まとめることが可能で、前にはダッシュを置かなければならない。
  2. BSD オプション。まとめることが可能で、ダッシュを使ってはならない。
  3. GNU ロングオプション。前に二つのダッシュを置く。

デフォルトの動作

まずはデフォルトの動作を知っておきます。

$ ps
  PID TTY          TIME CMD
 1731 pts/2    00:00:00 ps
24760 pts/2    00:00:00 zsh

デフォルトでは、ps はカレントユーザーと同じ実効 (effective) ユーザー ID (EUID) を持ち、かつ呼び出した端末と同じ端末に関連づけられている全てのプロセスを選択する。この場合、プロセス ID (PID)・プロセスに関連づけられている端末 (TTY)・ [dd-]hh:mm:ss という形式の累積 CPU 時間 (TIME)・実行ファイル名 (CMD) が表示される。出力はデフォルトではソートされない。

実効ユーザーを指定する

呼び出した端末以外の端末に関連づけられているプロセスも表示するには-uオプションで明示的に実効ユーザーを指定すればいいようです。

$ ps -u <ユーザー名>
  PID TTY          TIME CMD
  732 pts/1    00:00:00 man
  735 pts/1    00:00:00 sh
  736 pts/1    00:00:00 sh
  741 pts/1    00:00:00 less
 1719 pts/2    00:00:00 ps
 3177 ?        00:00:00 multilog
24627 ?        00:00:01 sshd
24628 pts/0    00:00:00 zsh
24742 pts/0    00:00:00 screen
24743 ?        00:00:01 screen
24744 pts/1    00:00:00 zsh
24760 pts/2    00:00:00 zsh
31318 pts/3    00:00:00 zsh
31331 pts/3    00:00:00 python
31343 pts/4    00:00:00 zsh

すべてのプロセスを表示する

-eオプションを使います。

$ ps -e

完全なフォーマット

-fオプションをつけると「完全なフォーマットでリスト」します。なにが「完全」なのかはよくわかりません。

$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
500       2237 24760  0 11:40 pts/2    00:00:00 ps -f
500      24760 24743  0 10:04 pts/2    00:00:00 /usr/local/bin/zsh

これと似たオプションに-lというのもあります。これは「長いフォーマット」です。これもよくわからないけど、「完全なフォーマット」よりたくさんのカラムが表示されます。

$ ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 R   500  2312 24760  0  76   0 -  1167 -      pts/2    00:00:00 ps
0 S   500 24760 24743  0  76   0 -  1917 rt_sig pts/2    00:00:00 zsh

コマンド名で選択

実効ユーザーではなくコマンド名で選択したい場合は-Cオプションを使います。たとえば実行中のApache HTTPサーバーを表示します。

$ ps -C httpd
  PID TTY          TIME CMD
 2016 ?        00:00:02 httpd
 4600 ?        00:00:19 httpd
22785 ?        00:00:00 httpd
22786 ?        00:00:56 httpd
22787 ?        00:00:31 httpd
22788 ?        00:00:37 httpd
22790 ?        00:00:41 httpd
22791 ?        00:00:32 httpd
22792 ?        00:00:33 httpd
22793 ?        00:00:32 httpd
22794 ?        00:00:38 httpd

スレッドも表示

たとえばNPTLなMySQLを使っている場合、コマンド名でmysqldを指定しても1個しか出てきません。スレッドも表示したい場合は-Lオプションを使います。

$ ps -C mysqld
  PID TTY          TIME CMD
 2613 ?        00:17:38 mysqld
$ ps -C mysqld -L
  PID   LWP TTY          TIME CMD
 2613  2613 ?        00:00:07 mysqld
 2613  2614 ?        00:00:00 mysqld
 2613  2615 ?        00:00:00 mysqld
 2613  2616 ?        00:00:00 mysqld
 2613  2617 ?        00:00:00 mysqld
 2613  2624 ?        00:00:11 mysqld
 2613  2625 ?        00:00:04 mysqld
 2613  2626 ?        00:00:02 mysqld
 2613  2627 ?        00:00:14 mysqld
 2613  2628 ?        00:00:00 mysqld

カラムの意味を知る

そろそろ各カラムが何を表しているのか知りたくなってきました。想像がつくやつもあるけど「なにこれ?」みたいのもあります。
ここではこれまでで一番長いフォーマットで表示された-lオプションで表示されるカラムについて調べます。

F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
F

プロセスに関連づけられたフラグです。

プロセスフラグ
これらの値の合計は、flags 出力指定子で提供される "F" カラムに表示される。
1 fork されたが exec されていない。
4 スーパーユーザー権限を使っている。

S

プロセスの状態を1文字で表します。

プロセスの状態コード
s, stat, state 出力指定子 (ヘッダ "STAT" または "S") がプロセス状態の説明のために表示する値を以下に示す。
D 割り込み不可能なスリープ状態 (通常 IO 中)
R 実行中または実行可能状態 (実行キューにある)
S 割り込み可能なスリープ状態 (イベントの完了を待っている)
T ジョブ制御シグナルまたはトレースされているために停止中の状態
W ページング状態 (2.6.xx カーネルからは無効)
X 死んだ状態 (見えるべきではない)
Z 終了したが、親プロセスによって回収されなかった、消滅した (ゾンビ) プロセス

UID

実効ユーザーIDです。euidと同じ。

PID

プロセスID。

PPID

親プロセスID。

C

プロセッサ使用率。整数。

PRI

優先度(priotiry)だと思うけどよくわからない。

NI

nice値。19 (最も良い) から -20 (他のプロセスに対して良くない) の値を取る。

ADDR

よくわからない。

SZ

プロセスのコアイメージの物理ページサイズ。メモリ関連については後述する。

WCHAN

プロセスがスリープしているカーネル関数の名前。

TTY

制御端末。

TIME

累積したCPU時間。

CMD

文字列の引数がついたコマンド。

フォーマットの指定

表示するフォーマットは-oオプションで指定することができます。

たとえばプロセスIDとコマンド名(引数なし)だけ表示したい場合。

$ ps -o pid,comm
  PID CMD
 5417 ps
24760 zsh

-Oオプションを使うといくつかのデフォルトカラムを表示してくれます。「-o pid,format,state,tname,time,command または -opid,format,tname,time,cmd と等しい」そうです。

-fや-lで表示されないカラムはこのオプションを使って表示させましょう。

たとえばhttpdのCPU使用率やメモリ使用率を表示したいことがあります。

$ ps -C httpd -o pid,pcpu,pmem,comm
  PID %CPU %MEM COMMAND
 2016  0.0  1.8 httpd
 4600  0.1  5.7 httpd
22785  0.0  0.7 httpd
22786  0.2  5.6 httpd
22787  0.1  5.7 httpd
22788  0.1  6.2 httpd
22790  0.1  5.7 httpd
22791  0.1  5.6 httpd
22792  0.1  6.4 httpd
22793  0.1  6.0 httpd
22794  0.1  6.0 httpd

メモリ関連のカラム

メモリ関連のカラムにはいくつかあるようなので整理しておきます。

sz         SZ       プロセスのコアイメージの物理ページサイズ。これにはテキスト・データ・スタック空間が含まれる。デバイスマッピングは現在のところ除外されているが、これは変更される。 vsz と rssを参照。

rss        RSS      常駐セットの大きさ。タスクが使用しているスワップされていない物理メモリ (kB 単位)。 (別名rssiz, rsz)。

vsz        VSZ      プロセスの仮想メモリサイズ (KiB, 1024 バイト単位)。デバイスマッピンは現在のところ除外されているが、これは変更される。 (別名vsize)。

%mem       %MEM     マシンの物理メモリに対するプロセスの常駐セットサイズのパーセンテージ。 (別名 pme)。

topコマンドのRESに相当するのがここではRSSになるようです。試しに全部表示してみます。

$ ps -C httpd -o pid,pmem,sz,rss,vsz,comm
  PID %MEM    SZ   RSS    VSZ COMMAND
 2016  1.8  5136  9392  20544 httpd
 4600  5.7 10873 28408  43492 httpd
22785  0.7  4802  3588  19208 httpd
22786  5.6 10803 28220  43212 httpd
22787  5.7 11009 28860  44036 httpd
22788  6.2 11567 31120  46268 httpd
22790  5.7 10860 28672  43440 httpd
22791  5.6 10827 28244  43308 httpd
22792  6.4 11691 32076  46764 httpd
22793  6.0 11307 30100  45228 httpd
22794  6.0 11339 30180  45356 httpd

ちょっと計算してみます。

  PID %MEM    SZ   RSS    VSZ COMMAND
22794  6.0 11339 30180  45356 httpd

このマシンには512MBの物理メモリが搭載されているので、それの6%がRSSになるはずです。

>>> 512 * 0.06
30.719999999999999

おー、ほぼ正しいですね。

ちなみに、-fでも-lでもRSSは表示されませんが、-yを-lと組み合わせることでRSSが表示されるようになります。

$ ps -ly
S   UID   PID  PPID  C PRI  NI   RSS    SZ WCHAN  TTY          TIME CMD
R   500  9676 24760  0  77   0   756  1167 -      pts/2    00:00:00 ps
R   500 24760 24743  0  77   0  3436  1917 -      pts/2    00:00:01 zsh

psで特定プロセスのメモリサイズを知りたいときに簡単に使えそうです。

ソート

特定のカラムでソートすることもできます。

RSSの昇順で表示します。

$ ps -C httpd -o pid,pmem,sz,rss,vsz,comm --sort rss
  PID %MEM    SZ   RSS    VSZ COMMAND
22785  0.7  4802  3588  19208 httpd
 2016  1.8  5136  9392  20544 httpd
22786  5.6 10803 28220  43212 httpd
22791  5.6 10827 28244  43308 httpd
 4600  5.7 10873 28424  43492 httpd
22790  5.7 10860 28672  43440 httpd
22787  5.7 11009 28860  44036 httpd
22793  6.0 11307 30100  45228 httpd
22794  6.0 11339 30180  45356 httpd
22788  6.2 11567 31120  46268 httpd
22792  6.4 11691 32076  46764 httpd

降順にするにはマイナスをつけます。

$ ps -C httpd -o pid,pmem,sz,rss,vsz,comm --sort -rss
  PID %MEM    SZ   RSS    VSZ COMMAND
22792  6.4 11691 32076  46764 httpd
22788  6.2 11567 31120  46268 httpd
22794  6.0 11339 30180  45356 httpd
22793  6.0 11307 30100  45228 httpd
22787  5.7 11009 28860  44036 httpd
22790  5.7 10860 28672  43440 httpd
 4600  5.7 10873 28424  43492 httpd
22791  5.6 10827 28244  43308 httpd
22786  5.6 10803 28220  43212 httpd
 2016  1.8  5136  9392  20544 httpd
22785  0.7  4802  3588  19208 httpd

ソートに使えないカラムもいくつかあるようです。

プロセスツリーを表示する

fオプション(-fではない!)を使うとプロセスをツリー上に表示できるようです。

でもプロセスツリーを表示するだけならpstreeコマンドを使った方がいいかもしれません。

ヘッダ行を繰り返す

-eオプションですべてのプロセスを表示したりするとリストが長くなり、どれがどのカラムかわからなくなります。
そんなときは--headersオプションを使ってヘッダ行が繰り返し表示されるようにするといいかもしれません。

$ ps -ef --headers

いろんなuid

uidにもいろいろあります。

euid
実効ユーザーID
ruid
実ユーザーID
fuid
ファイルシステムアクセスユーザーID
suid
保存ユーザーID

単にuidといった場合はeuidのことを指すようです。

ps auxとか

実はpsのことをよく知らない頃(つい数時間前まで)は、特に意味も知らず以下のように打ってました。

$ ps auxwww

これどういう意味?

manにずばり書いてありました。

"ps -aux" は "ps aux" とは異なることに注意すること。 POSIXUNIX 標準では、"ps -aux" は "x" という名前のユーザーが所有する全てのプロセスを表示し、かつ -a オプションで選択される全てのプロセスを表示する。 "x" という名前のユーザーが存在しない場合、この ps は代わりに "ps aux" というコマンドとして解釈され、警告を表示する。この動作は昔のスクリプトと慣習からの移行の助けになることを意図している。これは脆くて変更される可能性があるので、これに依存すべきではない。

wオプションは出力幅を拡げるために使います。2つ指定すると幅の制限がなくなります。

-aオプションは以下の意味です。

-a セッションリーダ (getsid(2) を参照) と端末を持たないプロセスを除く、全てのプロセスを表示する。

スッキリ。

まとめ

man重要。

これからはpsコマンドをもっと駆使していきたいと思います。

また、Mac OS XのpsはBSD系のコマンドなのでここで調べたものとはだいぶ違うようです。