centos7
ps

psコマンドの使い方

1 環境

VMware Workstation 12 Player上のゲストマシンを使っています。

[root@admin ~]# cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)

[root@admin ~]# uname -r
3.10.0-514.el7.x86_64

2 プロセスの情報(CPU使用率等)を表示する方法

2.1 事前準備

2.1.1 テストプログラムの作成

テストプログラムを作成する。
[root@admin ~]# vi tp.c
[root@admin ~]# cat tp.c
#include <stdio.h>
#include <unistd.h>

int main()
{
    sleep(300);
    return 0;
}

テストプログラムをコンパイルする。
[root@admin ~]# gcc -Wall -o tp tp.c
[root@admin ~]# ls tp*
tp  tp.c

2.1.2 その他ツール

stressやtasksetについては、下記を参照ください。
stressコマンドの使い方
tasksetコマンドの使い方

2.2 コマンド名(COMM)を表示する方法

テストプログラムを実行する。
[root@admin ~]# ./tp &
[1] 1326

テストプログラムのコマンド名(comm)を表示する。"tp"と表示されたことが確認できる。
[root@admin ~]# ps -C tp -o comm
COMMAND
tp

あと始末をする。
[root@admin ~]# pkill tp
[1]+  Terminated              ./tp

2.3 プロセスのPID,PPIDを表示する方法(pid,ppid)

テストプログラムを実行する。
[root@admin ~]# ./tp &
[1] 1272

プロセス自身のPIDと親プロセスのPIDを表示する。
[root@admin ~]# ps -C tp -o comm,pid,ppid
COMMAND            PID   PPID
tp                1272    825

あと始末をする。
[root@admin ~]# pkill tp
[1]+  Terminated              ./tp

2.4 プロセスの仮想メモリサイズ、実メモリサイズを表示する方法(vsz,rss)

コマンドを実行する。
[root@admin ~]# ./tp &
[1] 1322

プロセスの仮想メモリサイズと実メモリサイズを表示する。
[root@admin ~]# ps -C tp -o comm,vsz,rss
COMMAND            VSZ   RSS
tp                4156   344

あと始末をする。
[root@admin ~]# pkill tp
[1]+  Terminated              ./tp

2.5 コマンドの実行開始時刻を表示する方法(lstart,bsdstart)

コマンドの実行開始時刻を表示するオプションとしては、lstartまたはbsdstartが使えるようです。

コマンドを実行する。
[root@admin ~]# date;./tp &
2017年  7月 25日 火曜日 16:46:51 JST
[1] 1331

しばらくしてからdateコマンドを実行する。
[root@admin ~]# date
2017年  7月 25日 火曜日 16:48:31 JST

コマンドの開始時刻を確認する。lstart,bsdstartは、コマンドの実行開始時刻を表していることがわかる。
[root@admin ~]# ps -C tp -o comm,lstart,bsdstart
COMMAND                          STARTED  START
tp              Tue Jul 25 16:46:50 2017  16:46

あと始末をする。
[root@admin ~]# pkill tp
[1]+  Terminated              ./tp

2.6 コマンド実行開始からの経過時間を表示する方法(etime,etimes)

経過時間を表示するオプションとしてetimeまたはetimesがあるようです。

コマンドを実行する。
[root@admin ~]# date;./tp &
2017年  7月 25日 火曜日 20:30:32 JST
[1] 1272

コマンドを実行してから、20秒経過していることがわかる。
[root@admin ~]# date;ps -C tp -o comm,etime,etimes
2017年  7月 25日 火曜日 20:30:52 JST
COMMAND             ELAPSED ELAPSED
tp                    00:20      20

あと始末をする。
[root@admin ~]# pkill tp
[1]+  Terminated              ./tp

2.7 CPU使用率を表示する方法(%cpu)

stressコマンドを実行する(CPU負荷をかける)
[root@admin ~]# stress -c 1 -q &
[1] 853

プロセスのCPU使用率を確認する。
[root@admin ~]# ps -C stress -o comm,pid,ppid,%cpu
COMMAND            PID   PPID %CPU
stress             853    789  0.0 ★親プロセス(wait()を実行して、子プロセスの終了待ち)
stress             854    853 97.2 ★子プロセス(sqrt()を実行して、CPU負荷をかける)

あと始末をする。
[root@admin ~]# pkill stress
[1]+  Terminated              stress -c 1 -q

2.8 メモリ使用率を表示する方法(%mem)

初期状態の確認
仮想マシンの搭載メモリ量を確認する。
[root@admin ~]# free -k
              total        used        free      shared  buff/cache   available
Mem:         999964       90132      795636         632      114196      769760
Swap:       1048572           0     1048572
256Mのメモリを獲得した場合
stressコマンドを実行する。
[root@admin ~]# stress -m 1 --vm-bytes 268435456 --vm-hang 0 -q &
[1] 908

プロセスのメモリ使用量を確認する。
[root@admin ~]# ps -C stress -o comm,pid,ppid,%mem,rss
COMMAND            PID   PPID %MEM   RSS
stress             908    789  0.0   416
stress             909    908 26.2 ★262284

[root@admin ~]# bc -q
999964*0.262
261990.568 ★印とほぼ一致する。

あと始末をする。
[root@admin ~]# pkill stress
128Mのメモリを獲得した場合
stressコマンドを実行する。
[root@admin ~]# stress -m 1 --vm-bytes 134217728 --vm-hang 0 -q &
[1] 961

プロセスのメモリ使用量を確認する。
[root@admin ~]# ps -C stress -o comm,pid,ppid,%mem,rss
COMMAND            PID   PPID %MEM   RSS
stress             961    939  0.0   420
stress             962    961 13.1 ★131204

[root@admin ~]# bc -q
999964*0.131
130995.284 ★印とほぼ一致する。

あと始末をする。
[root@admin ~]# pkill stress
[1]+  Terminated              stress -m 1 --vm-bytes 134217728 --vm-hang 0 -q
64Mのメモリを獲得した場合
stressコマンドを実行する。
[root@admin ~]# stress -m 1 --vm-bytes 67108864 --vm-hang 0 -q &
[1] 983

プロセスのメモリ使用量を確認する。
[root@admin ~]# ps -C stress -o comm,pid,ppid,%mem,rss
COMMAND            PID   PPID %MEM   RSS
stress             983    939  0.0   420
stress             984    983  6.5 ★65536

[root@admin ~]# bc -q
999964*0.065
64997.660 ★印とほぼ一致する。

あと始末をする。
[root@admin ~]# pkill stress
[1]+  Terminated              stress -m 1 --vm-bytes 67108864 --vm-hang 0 -q

2.9 プロセスがスリープしている関数を表示する方法(wchan)

テストプログラムを実行する。
[root@admin ~]# ./tp &
[1] 1174

プロセスがhrtimer_nanosleep()でスリープしていることがわかる。
[root@admin ~]# ps -C tp -o comm,wchan
COMMAND         WCHAN
tp              hrtimer_nanosleep

あと始末をする。
[root@admin ~]# pkill tp
[1]+  Terminated              ./tp


参考までに抜粋したhrtimer_nanosleep()を以下に示します。ただし、3.10ではなく3.12のものです。
long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, const enum hrtimer_mode mode, const clockid_t clockid)
{
        struct restart_block *restart;
        struct hrtimer_sleeper t;
        int ret = 0;
        unsigned long slack;

        slack = current->timer_slack_ns;
        if (rt_task(current))
                slack = 0;

        hrtimer_init_on_stack(&t.timer, clockid, mode);
        hrtimer_set_expires_range_ns(&t.timer, timespec_to_ktime(*rqtp), slack);
        if (do_nanosleep(&t, mode))
                goto out;

        /* Absolute timers do not update the rmtp value and restart: */
        if (mode == HRTIMER_MODE_ABS) {
                ret = -ERESTARTNOHAND;
                goto out;
        }

        if (rmtp) {
                ret = update_rmtp(&t.timer, rmtp);
                if (ret <= 0)
                        goto out;
        }

        restart = &current_thread_info()->restart_block;
        restart->fn = hrtimer_nanosleep_restart;
        restart->nanosleep.clockid = t.timer.base->clockid;
        restart->nanosleep.rmtp = rmtp;
        restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer);

        ret = -ERESTART_RESTARTBLOCK;
out:
        destroy_hrtimer_on_stack(&t.timer);
        return ret;
}

2.10 プロセスが動作しているCPUを表示する方法(psr)

ゲストマシンの搭載CPU数を確認する。
[root@admin ~]# cat /proc/cpuinfo |grep processor
processor       : 0
processor       : 1

CPU=0でプロセスを起動する。
[root@admin ~]# taskset -c 0 ./tp&
[1] 1224

プロセスが動作しているCPUを確認する。CPU=0(★印)で動作していることがわかる。
[root@admin ~]# ps -C tp -o comm,psr
COMMAND         PSR
tp              ★0

あと始末をする。
[root@admin ~]# pkill tp
[1]+  Terminated              taskset -c 0 ./tp

CPU=1でプロセスを起動する。
[root@admin ~]# taskset -c 1 ./tp&
[1] 1228

プロセスが動作しているCPUを確認する。CPU=1(★印)で動作していることがわかる。
[root@admin ~]# ps -C tp -o comm,psr
COMMAND         PSR
tp              ★1

あと始末をする。
[root@admin ~]# pkill tp
[1]+  Terminated              taskset -c 0 ./tp

2.11 スレッドIDを表示する方法(lwp,spid,tid)

スレッドIDを表示するためのオプションとして、lwp,spid,tidがあるようです。

テストプログラムを作成する。
[root@admin ~]# vi thread.c
[root@admin ~]# cat thread.c
#include <stdio.h>
#include <pthread.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>

void *threadFunc1(void)
{
    int fd;
    struct timespec req;
    char str[] = "0123456789";

    req.tv_sec = 300;
    req.tv_nsec = 0;

    for(;;) {
        fd = open("test.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666);

        write(fd, str, (size_t)sizeof(str));
        close(fd);

        nanosleep(&req, NULL);
    }
}

int main(int argc, char *argv[])
{
    pthread_t t1;
    void *res;

    pthread_create(&t1, NULL, (void *)&threadFunc1, NULL);

    pthread_join(t1, &res);
    _exit(0);
}

テストプログラムをコンパイルする。
[root@admin ~]# gcc -Wall -pthread -o thread thread.c
[root@admin ~]# ls thread*
thread  thread.c

テストプログラムを実行する。
[root@admin ~]# ./thread &
[1] 1617

プロセスの状態を確認する。1つのプロセスに2つスレッド存在することがわかる(同じPIDに異なるスレッドIDが存在する)
[root@admin ~]# ps -LC thread -o comm,pid,lwp,spid,tid,wchan
COMMAND            PID    LWP   SPID    TID WCHAN
thread            1699   1699   1699   1699 futex_wait_queue_me  ★ main()を実行しているスレッド
thread            1699   1700   1700   1700 hrtimer_nanosleep    ★ threadFunc1()を実行しているスレッド

3 プロセスの優先度,スケジューリングクラスを表示する方法

3.1 リアルタイムプロセスのテストプログラム作成

[root@admin ~]# vi rt.c
[root@admin ~]# cat rt.c
#include <stdio.h>
#include <sched.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    struct sched_param sp;
    int policy;

    if(argv[1][0] == 'r')
        policy = SCHED_RR ;
    else if (argv[1][0] == 'f')
        policy = SCHED_FIFO ;
    else {
        fprintf(stderr, "Error\n") ;
        exit(1);
    }

    sp.sched_priority = atoi(argv[2]);
    printf("policy=%d,priority=%d\n", policy,sp.sched_priority);

    sched_setscheduler(0, policy, &sp);
    sleep(60*10) ;

    return 0;
}

3.2 リアルタイムプロセスの優先度を表示する方法(rtprio)

SCHED_FIFOのプロセスを起動した場合
[root@admin ~]# gcc -Wall -o rt rt.c
[root@admin ~]# ./rt f 10
policy=1,priority=10

[root@admin ~]# ps -C rt -o comm,sched,cls,pri,rtprio,ni
COMMAND         SCH CLS PRI RTPRIO  NI
rt                1  FF  50     10   -
SCHED_RRのプロセスを起動した場合
[root@admin ~]# ./rt r 20
policy=2,priority=20

[root@admin ~]# ps -C rt -o comm,sched,cls,pri,rtprio,ni
COMMAND         SCH CLS PRI RTPRIO  NI
rt                2  RR  60     20   -
SCHED_RRのプロセスを起動した場合(その2)
[root@admin ~]# ./rt r 99
policy=2,priority=99

[root@admin ~]# ps -C rt -o comm,sched,cls,pri,rtprio,ni
COMMAND         SCH CLS PRI RTPRIO  NI
rt                2  RR 139     99   -
watchdogプロセスの優先度確認
[root@admin ~]# ps -C watchdog/0 -o comm,sched,cls,pri,rtprio,ni
COMMAND         SCH CLS PRI RTPRIO  NI
watchdog/0        1  FF 139     99   -

3.3 タイムスライスプロセスの優先度を表示する方法(pri,ni)

[root@admin ~]#  cat tp.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/resource.h>

int main(int argc, char *argv[])
{
    int nice;

    printf("Initial nice value is %d\n", getpriority(0, 0)) ;

    setpriority(0, 0, atoi(argv[1]));
    nice = getpriority(0, 0) ;
    printf("nice value is %d\n", nice) ;

    sleep(60*10) ;
    return 0;
}
[root@admin ps]# gcc -Wall -o tp tp.c

------------------------
1. NICE値=-20(最高優先度)
------------------------
[root@admin ~]# ./tp -20
Initial nice value is 0
nice value is -20

[root@admin ~]# ps -C tp -o comm,sched,cls,pri,rtprio,ni
COMMAND         SCH CLS PRI RTPRIO  NI
tp                0  TS  39      - -20

------------------------
2. NICE値=0(デフォルト)
------------------------
[root@admin ~]# ./tp 0
Initial nice value is 0
nice value is 0

[root@admin ~]# ps -C tp -o comm,sched,cls,pri,rtprio,ni
COMMAND         SCH CLS PRI RTPRIO  NI
tp                0  TS  19      -   0

------------------------
3. NICE値=19(最低優先度)
------------------------
[root@admin ~]# ./tp 19
Initial nice value is 0
nice value is 19

[root@admin ~]# ps -C tp -o comm,sched,cls,pri,rtprio,ni
COMMAND         SCH CLS PRI RTPRIO  NI
tp                0  TS   0      -  19

4 ソートする方法(--sort Keyword)

--sortオプションを使うことで、プロセスのCPU使用率やメモリ使用量(rss)等を
昇順、降順に並べ替えることができます。

4.1 CPU使用率を昇順、降順に表示する方法

テストプログラムを実行する。実行するとCPU使用率が100%程度までに上昇します。
[root@admin ~]# stress -c 1 -q &
[1] 1378

CPU使用率を昇順に表示する。
[root@admin ~]# ps ax -o comm,%cpu --sort %cpu |head -n 5
COMMAND         %CPU
systemd          0.0
kthreadd         0.0
ksoftirqd/0      0.0
kworker/0:0H     0.0

CPU使用率を降順に表示する。テストプログラムのCPU使用率が100%程度になることが確認できる。
[root@admin ~]# ps ax -o comm,%cpu --sort -%cpu |head -n 5
COMMAND         %CPU
stress          97.5
vmtoolsd         0.2
kworker/0:2      0.1
kworker/1:2      0.1

4.2 メモリ使用量を昇順、降順に表示する方法

stressコマンドを実行する。プロセスが獲得する実メモリサイズは128Mを指定する。
[root@admin ~]# stress -m 1 --vm-bytes 134217728 --vm-hang 0 -q &
[2] 1403

もう1つstressコマンドを実行する。プロセスが獲得する実メモリサイズは64Mを指定する。
[root@admin ~]# stress -m 1 --vm-bytes 67108864 --vm-hang 0 -q &
[3] 1405

[root@admin ~]# ps ax -o command,rss --sort rss|head -n 5
COMMAND                       RSS
[kthreadd]                      0
[ksoftirqd/0]                   0
[kworker/0:0H]                  0
[kworker/u256:0]                0

[root@admin ~]# ps ax -o command,rss --sort -rss|head -n 5
COMMAND                       RSS
stress -m 1 --vm-bytes 1342 131208 ★1つ目に起動したstressのプロセス
stress -m 1 --vm-bytes 6710 65536  ★2つ目に起動したstressのプロセス
/usr/bin/python -Es /usr/sb 18436
/usr/lib/polkit-1/polkitd - 12864

4.3 PIDを昇順、降順に表示する方法

PIDを昇順に表示した場合
[root@admin ~]# ps ax -o comm,pid --sort pid |head -n 5
COMMAND            PID
systemd              1
kthreadd             2
ksoftirqd/0          3
kworker/0:0H         5
PIDを降順に表示した場合
[root@admin ~]# ps ax -o comm,pid --sort -pid |head -n 5
COMMAND            PID
head              1359
ps                1358
kworker/1:2H      1340
kworker/1:0       1335