tips: プロセスのグループIDを調べる方法

# 概要

ps コマンドでグループIDを表示するには、-o オプションで表示項目を調整します。

```
$ ps -o user,group,pid,ppid,c,start_time,tty,time,comm
```

# どういうこと?

プロセスがどんな権限で実行されるのか、root 権限などの不要な権限を持ったままで実行されると、システム障害やセキュリティホールの原因になり得ます。
そのため、プロセス実行時の権限はきちんと確認する必要があります。

例えば httpd などのサービスプロセスが何のアカウント権限で動いているか、を確認するとき

```
$ ps -ef | grep httpd
```

などとやったりします。
が、これではプロセスのユーザー ID は表示されるけどグループ ID は表示されません。

「ユーザー ID は `apache` なんだけど、グループ ID は `root` で、root のグループ権限で変なところに変なファイル作られちゃった…」なんてことがあるかもしれません。

そこで、ps オプションで出力される項目を調整して、グループ ID も表示する方法を考えます。


# 環境

CentOS6 で、OS 標準の bash および ps コマンドで確認しました。

+ `CentOS release 6.5`
+ `bash-4.1.2-48.el6.x86_64`
+ `procps-3.2.8-30.el6.x86_64`


# 手法

まず、ps をオプション無しで実行したときの出力を確認することにしましょう。 

```
$ ps
  PID TTY          TIME CMD
 6911 pts/1    00:00:00 bash
16212 pts/1    00:00:00 ps
$
$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
501       6911  6900  0 14:49 pts/1    00:00:00 -bash
501      16239  6911  0 17:26 pts/1    00:00:00 ps -f
$
```

-f オプション(＝full-format listing)を指定しても、確かにグループ ID は出力されません。

さて、`man ps` すると、出力項目は -o オプションで調整できる、とあります。
よく使用される(だろう) -f オプションの出力項目を、-o オプションで明示指定すると

```
-o user,pid,ppid,c,start_time,tty,time,comm
```

となる(だろう)から、ここに、group を組み込んで

```
$ ps -o user,group,pid,ppid,c,start_time,tty,time,comm
```

とすれば、ps コマンドでユーザー ID のほかグループ ID も出力されます。

これを、shell に alias として登録しておくと便利だと思います。
~/.bashrc に、以下の指定を追加します。

```
alias ps='ps -o user,group,pid,ppid,c,start_time,tty,time,comm'
```

その後 `source ~/.bashrc` なり、再ログインすれば alias は有効になり、`ps` だけで -o オプションを指定したときの実行結果が得られます。

```
$ ps
USER     GROUP      PID  PPID  C START TT           TIME COMMAND
501      501       6911  6900  0 14:49 pts/1    00:00:00 bash
501      501      15177  6911  0 15:41 pts/1    00:00:00 ps
$

	→ オプション無しで GROUP が出力された。alias で -o オプションを指定しているため。
```

注:USER, GROUP が文字列でなく数字で出力されているのは、ユーザー名・グループ名が長くて ps コマンドが想定したカラム数を超えてしまっているためです。cf. man ps


# 注意点

ps の -o オプションは、同じく出力項目を調整するオプションである -f オプションと同時に指定すると、警告メッセージが出力されたり、

```
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ
```

オプションが効かなくなったりします。

```
$ ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0  2015 ?        00:00:02 init
root         2     1  0  2015 ?        00:00:00 [kthreadd/60830]
root         3     2  0  2015 ?        00:00:00 [khelper/60830]
root       122     1  0  2015 ?        00:00:00 /sbin/udevd -d
dbus       596     1  0  2015 ?        00:00:00 dbus-daemon --system

	…(以降略)…

$
$ ps -ef -o user,group,pid,ppid,c,start_time,tty,time,comm
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ
USER     GROUP      PID  PPID  C START TT           TIME COMMAND
501      501       6447  6446  0 14:13 pts/0    00:00:00 bash
501      501       6571  6447  0 14:20 pts/0    00:00:00  \_ ps
$

	→ -e オプションが効いていない
```

`ps -o …` を alias に登録しているときに `ps -ef` を実行すると、この症状が出ます。
その場合は、-f 等の出力調整オプションは使用を避けるなど注意しましょう。

## sh スクリプトへの影響

alias を `~/.bashrc` に設定したなら、他にややこしいことをしていない限りは sh スクリプトには影響しません(と思います)。`~/.bashrc` は対話型シェルで読み込まれる仕様であるし、sh スクリプトは対話型シェルとしては起動しないためです。

>       When an interactive shell that is not a login shell  is  started,  bash
>       reads  and executes commands from ~/.bashrc, if that file exists.  This
>       may be inhibited by using the --norc option.  The --rcfile file  option
>       will  force  bash  to  read  and  execute commands from file instead of
>       ~/.bashrc.
>
>  cf. man bash

これを検証してみました。こういうスクリプトを

```a.sh
#!/bin/sh
ps
```

`ps -o …` の alias を ~/.bashrc で設定している環境で実行し、sh スクリプトの中では alias が効かないことを確認しました。

```
$ alias
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias ps='ps -o user,group,pid,ppid,c,start_time,tty,time,comm'
alias vi='vim'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
$
$ ps
USER     GROUP      PID  PPID  C START TT           TIME COMMAND
501      501       6911  6900  0 14:49 pts/1    00:00:00 bash
501      501      16396  6911  0 17:41 pts/1    00:00:00 ps
$
	→ 対話型 shell では -o オプションが効いている(＝alias が効いている)

$ ./a.sh
  PID TTY          TIME CMD
 6911 pts/1    00:00:00 bash
16399 pts/1    00:00:00 a.sh
16400 pts/1    00:00:00 ps
$
	→ sh スクリプトでは -o オプションが効いていない(＝alias が効いていない)
```

# 資料
## ps -o オプションで指定できる出力項目

man ps : "STANDARD FORMAT SPECIFIERS" の記述から抜粋し、表にしたものです。

> |CODE   |HEADER |DESCRIPTION |
> |-------|-------|------------|
> |%cpu   |%CPU   |cpu utilization of the process in "##.#" format. |
> |%mem   |%MEM   |ratio of the process’s resident set size to the physical memory on the machine, expressed as a percentage.|
> |args   |COMMAND        |command with all its arguments as a string.|
> |blocked        |BLOCKED        |mask of the blocked signals, see signal(7).|
> |bsdstart       |START  |time the command started.|
> |bsdtime        |TIME   |accumulated cpu time, user + system.|
> |c      |C      |processor utilization.|
> |caught |CAUGHT |mask of the caught signals, see signal(7).|
> |cgroup |CGROUP |display control groups to which the process belonges. |
> |class  |CLS    |scheduling class of the process. (alias policy, cls). |
> |cls    |CLS    |scheduling class of the process. (alias policy, class). |
> |cmd    |CMD    |see args. (alias args, command). |
> |comm   |COMMAND        |command name (only the executable name).|
> |command        |COMMAND        |see args. (alias args, cmd). |
> |cp     |CP     |per-mill (tenths of a percent) CPU usage. (see %cpu). |
> |cputime        |TIME   |cumulative CPU time, "[dd-]hh:mm :ss" format. (alias time). |
> |egid   |EGID   |effective group ID number of the process as a decimal integer. (alias gid).|
> |egroup |EGROUP |effective group ID of the process.|
> |eip    |EIP    |instruction pointer. |
> |esp    |ESP    |stack pointer. |
> |etime  |ELAPSED        |elapsed time since the process was started, in the form [[dd-]hh:]mm:ss.|
> |euid   |EUID   |effective user ID. (alias uid). |
> |euser  |EUSER  |effective user name.|
> |f      |F      |flags associated with the process, see the PROCESS FLAGS  section. (alias flag, flags).|
> |fgid   |FGID   |filesystem access group ID. (alias fsgid). |
> |fgroup |FGROUP |filesystem access group ID.|
> |flag   |F      |see f. (alias f, flags). |
> |flags  |F      |see f. (alias f, flag). |
> |fname  |COMMAND        |first 8 bytes of the base name of the process’s executable |
> |fuid   |FUID   |filesystem access user ID. (alias fsuid). |
> |fuser  |FUSER  |filesystem access user ID.|
> |gid    |GID    |see egid. (alias egid). |
> |group  |GROUP  |see egroup. (alias egroup). |
> |ignored        |IGNORED        |mask of the ignored signals, see signal(7).|
> |label  |LABEL  |security label, most commonly used for SE Linux context data.|
> |lstart |STARTED        |time the command started.|
> |lwp    |LWP    |lwp (light weight process, or thread) ID of the lwp being reported. (alias spid, tid).|
> |ni     |NI     |nice value.|
> |nice   |NI     |see ni. (alias ni). |
> |nlwp   |NLWP   |number of lwps (threads) in the process. (alias thcount). |
> |nwchan |WCHAN  |address of the kernel function where the process is sleeping (use wchan if you want the kernel function name).|
> |pcpu   |%CPU   |see %cpu. (alias %cpu). |
> |pending        |PENDING        |mask of the pending signals. See signal(7).|
> |pgid   |PGID   |process group ID or, equivalently, the process ID of the process group leader. (alias pgrp). |
> |pgrp   |PGRP   |see pgid. (alias pgid). |
> |pid    |PID    |process ID number of the process. |
> |pmem   |%MEM   |see %mem. (alias %mem). |
> |policy |POL    |scheduling class of the process. (alias class, cls). |
> |ppid   |PPID   |parent process ID. |
> |psr    |PSR    |processor that process is currently assigned to. |
> |rgid   |RGID   |real group ID. |
> |rgroup |RGROUP |real group name.|
> |rip    |RIP    |64-bit instruction pointer. |
> |rsp    |RSP    |64-bit stack pointer. |
> |rss    |RSS    |resident set size, the non-swapped physical memory that a task has used (in kiloBytes).|
> |rssize |RSS    |see rss. (alias rss, rsz). |
> |rsz    |RSZ    |see rss. (alias rss, rssize). |
> |rtprio |RTPRIO |realtime priority. |
> |ruid   |RUID   |real user ID. |
> |ruser  |RUSER  |real user ID.|
> |s      |S      |minimal state display (one character). See section PROCESS task has used (in kiloBytes).|
> |sched  |SCH    |scheduling policy of the process.|
> |sess   |SESS   |session ID or, equivalently, the process ID of the session leader.|
> |sgi_p  |P      |processor that the process is currently executing on. |
> |sgid   |SGID   |saved group ID. (alias svgid). |
> |sgroup |SGROUP |saved group name.|
> |sid    |SID    |see sess. (alias sess, session). |
> |sig    |PENDING        |see pending. (alias pending, sig_pend). |
> |sigcatch       |CAUGHT |see caught. (alias caught, sig_catch). |
> |sigignore      |IGNORED        |see ignored. (alias ignored, sig_ignore). |
> |sigmask        |BLOCKED        |see blocked. (alias blocked, sig_block). |
> |size   |SZ     |approximate amount of swap space that would be required if the process were to dirty all writable pages and then be swapped out.|
> |spid   |SPID   |see lwp. (alias lwp, tid). |
> |stackp |STACKP |address of the bottom (start) of stack for the process. |
> |start  |STARTED        |time the command started.|
> |start_time     |START  |starting time or date of the process.|
> |stat   |STAT   |multi-character process state. See section PROCESS STATE CODES for the different values meaning.|
> |state  |S      |see s. (alias s). |
> |suid   |SUID   |saved user ID. (alias svuid). |
> |suser  |SUSER  |saved user name.|
> |svgid  |SVGID  |see sgid. (alias sgid). |
> |svuid  |SVUID  |see suid. (alias suid). |
> |sz     |SZ     |size in physical pages of the core image of the process. |
> |thcount        |THCNT  |see nlwp. (alias nlwp).|
> |tid    |TID    |see lwp. (alias lwp). |
> |time   |TIME   |cumulative CPU time, "[dd-]hh:mm :ss" format. |
> |tname  |TTY    |controlling tty (terminal). (alias tt, tty). |
> |tpgid  |TPGID  |ID of the foreground process group on the tty (terminal) that the process is connected to, or -1 if the process is not connected to a tty.|
> |tt     |TT     |controlling tty (terminal). (alias tname, tty). |
> |tty    |TT     |controlling tty (terminal). (alias tname, tt). |
> |ucmd   |CMD    |see comm. (alias comm, ucomm). |
> |ucomm  |COMMAND        |see comm. (alias comm, ucmd). |
> |uid    |UID    |see euid. (alias euid). |
> |uname  |USER   |see euser. (alias euser, user). |
> |user   |USER   |see euser. (alias euser, uname). |
> |vsize  |VSZ    |see vsz. (alias vsz). |
> |vsz    |VSZ    |virtual memory size of the process in KiB (1024-byte units).|
> |wchan  |WCHAN  |name of the kernel function in which the process is sleeping,|
> 
> cf. man ps

# 参考文献

- man ps
- man bash