概要
(追記開始)
指摘をいただき、psコマンド単独で完結する方法を教わりました.
コメント欄をご参照ください.
なお本記事の目的は awk の使用例ですので、引き続き掲載を続けております.
(追記終了)
ps -ef の結果から、次のようにユーザ単位でプロセス個数を表示するプログラム.
用途よりも awk の練習に近い.1
略
postgres => 14 # ← 所有者 postgres のプロセスが 14個ある
root => 296 # ← 所有者 root のプロセスが 296個ある
rtkit => 1
syslog => 1
略
コード ps_cnt_per_user.sh
#!/bin/bash
# ps -ef コマンドの結果を書き出すための一時ファイルパスを定義する
TMPFILE=`mktemp -p /tmp`
# ps -ef の結果 (2〜最終行) を一時ファイルに書き出す (例: 563個のプロセス)
ps -ef | sed -n '2,$p' > $TMPFILE
# ps -ef に出現したユーザ名を抽出する (例: 23個のユーザ名)
USERS=`cut -d' ' -f 1 $TMPFILE | sort -u`
# $TMPFILE ファイルを読み込む.
# このとき、シェル変数 $USERS を awk の変数 users として渡す.
awk -v "users=$USERS" '
BEGIN {
# (空白文字区切りで) 変数 users を取り出して、配列 users_list に格納する. (例: 要素数 23)
# また、users_list の総個数 (ユーザ数) が TU に格納される. (例: TU の値は 23)
TU = split( users, users_list ) # TU: ユーザの総数(Total num Uses)
# 配列 encount の領域を、ユーザ数分だけ獲得する. (例: 要素数 23個)
encount[TU] = 0 # 該当ユーザの出現回数
}
{
# ユーザ数 x プロセス数 だけループさせる. 無駄になるが良い方法が思い浮ばず.
for( i = 1; i <= TU; i++ ) { # 1 オリジンに注意!
# 全プロセス数が記された TMPFILE ファイル (例: 563個のプロセス)を 1行ずつ読み出す.
# なお、下記で「$1 ~ users_list[i]」にしてしまうと部分マッチとなり、
# ユーザID が「9」の場合に「992」「993」などにもヒットしてしまうので注意すること.
if($1 == users_list[i]){
# プロセスが出現するたびに、ユーザ名をキーに持つハッシュ配列 encount の値を加算する
encount[i] = encount[i] + 1 # 出現回数を加算する
}
}
}
END {
ps_cnt = 0
# ユーザごとにプロセスの出現回数を表示する
for( i = 1; i <= TU; i++ ) {
printf("%s => %d\n", users_list[i], encount[i])
ps_cnt += encount[i]
}
printf("---------------\n")
printf("ps_cnt => %d\n", ps_cnt) # プロセス総数を表示する
}' $TMPFILE
rm -f $TMPFILE
結果
$ ps_cnt_per_user.sh
992 => 3
994 => 2
996 => 18
997 => 2
998 => 17
avahi => 2
colord => 1
dnsmasq => 1
gdm => 34
kernoops => 2
message+ => 1
mongodb => 1
robozushi10 => 113
netdata => 14
nobody => 1
postgres => 14
root => 296
rtkit => 1
syslog => 1
systemd+ => 10
www-data => 19
xrdp => 1
zabbix => 6
---------------
ps_cnt => 560
-
個人的には、この複雑さになってきたら Python、Ruby で実装する. ↩