IT pass HikiWiki - [itbase2021]プロセス・ジョブ Diff

  • Added parts are displayed like this.
  • Deleted parts are displayed like this.

{{toc}}

= ジョブ・プロセス

Unix/Linux ではたくさんの処理を並行して行うことができます.
それぞれの処理をジョブあるいはプロセスと呼びますが, それらの
管理の初歩について解説します.

== 前置き

下のコマンドを実行してみましょう.

  $ sleep 10

このコマンドは, 引数で与えた数字 (10) の秒数だけ, 停止します.
この停止中は, プロンプトが表示されず, コマンドを受け付けません.
これは, ターミナルが sleep による停止を処理していて,
他のコマンドを受け付けられないためです.
停止中に入力したコマンドは, 停止処理が終了した後に
実行されます.

  $ sleep 10
  ls                         <- 停止中のためすぐには実行されない
  $ ls                       <- 停止処理の終了後に実行される
  Document Movies ...                  

sleep を実行することで, 他のコマンドをすぐには受け付けないことを
確認してください.


== 強制終了

sleep を途中で強制終了してみましょう.
この時には, Ctrl/ctrl/Control/control ボタンを押しながら "c" を押します.
なお, Unix/Linux では, Ctrl/ctrl/Control/control ボタンを押しながら,
何か他のボタン, 例えば "c", を押す操作を

  C-c

のように表記します.

  C-x

であれば, Ctrl/ctrl/Control/control ボタンを押しながら "x" を押す
ことを意味します.
下のようにすることで, sleep が強制終了できることを確認してください.

  $ sleep 10
  ^C              <- C-c を押すと表示される
  $               <- プロンプトが表示され, 他のコマンドを受け付ける.

C-c は, sleep 以外にも, すべてのコマンドを強制終了する際に使えます.

例えば, 自分で作ったプログラムが, 間違いのために動き続けることがあります.
そんな時には C-c で強制終了させましょう.


== 一時停止/再開

sleep を一時停止してみましょう.

一時停止するための方法は, C-z です.

  $ sleep 1800
  ^Z                                 <- C-z を押すと表示される
  [1]+ Stopped          sleep 1800
  $

C-z を押すと, 上のように表示され, 1800 秒待たずにコマンドが
受け付けられます.

このとき, 実行した sleep コマンドは終了しているわけではなく,
一時停止して待っています.
この一時停止しているコマンドの状態を確認するためのコマンドが jobs です.

  $ jobs
  [1]+  Stopped                 sleep 1800

これは, sleep 1800 というコマンド, このような実行中のコマンドを
「ジョブ」あるいは「プロセス」と呼びますが, それが "1" という
ジョブの番号を付けて管理されていて, それが一時停止 (Stopped) の
状態にあることを示しています.

ここでさらに二つ sleep を実行し, C-z で一時停止すると三つの
ジョブが表示されます.

  $ sleep 600                        <- 新たに sleep を実行
  ^Z                                 <- すかさず C-z で一時停止
  [2]+  Stopped                 sleep 600
  $ sleep 3600                       <- 新たに sleep を実行
  ^Z                                 <- すかさず C-z で一時停止
  [3]+  Stopped                 sleep 3600
  $ jobs                             <- ジョブの状態を確認
  [1]   Stopped                 sleep 1800
  [2]-  Stopped                 sleep 600
  [3]+  Stopped                 sleep 3600

上の表示で分かるように, ジョブには順に番号がついて管理されます.

では, 一つ目のジョブ (sleep 1800) を *表(おもて)で* 再開してみましょう.
(「*表で*実行」の意味は, 下で「*裏で*実行」を体験するとわかるかもしれません.)
表で再開するためのコマンドは fg (foreground の略) です.

  $ fg %1
  sleep 1800                        <- 再開されたジョブが表示される

"%1" は 1 番のジョブを再開するための指定です.

このとき, 表で再開させたので, 1800 秒立たないとコマンドを入力
できません.
ここでは強制終了しましょう.
強制終了の方法は C-c でしたね.

  $ fg %1
  sleep 1800                        <- 再開されたジョブが表示される
  ^C                                <- 強制終了

#補足:
#* 例えば, sleep 10 を実行後 1 秒以内に C-z によって一時停止した場合,
#  fg による再開後に約 9 秒分だけ sleep が実行されると期待されます.
#  しかし, sleep は一時停止している間の時間もカウントしているようです.
#  したがって, 一時停止してから 10 秒以上たってから fg とすると,
#  sleep はその時点で終了します.

次に, 二つ目のジョブ (sleep 600) を*裏で*再開してみましょう.
裏で再開するためのコマンドは bg (background の略) です.

  $ bg %2
  [2]- sleep 600 &         <- 裏で再開されたジョブが表示される. "&" が裏で実行されていることを示している
  $                        <- プロンプトが表示される

このとき, 裏で実行されているため, プロンプトが表示され, コマンドが
受け付けられます.
jobs でジョブの状態を確認してみましょう.

  $ jobs
  [2]-  Running                 sleep 600 &
  [3]+  Stopped                 sleep 3600
  $

sleep 600 のコマンドが裏で動いている (Running) ことがわかります.

では, 裏で動いているジョブ (sleep 600) と一時停止しているジョブ (sleep 3600) を強制終了してみましょう.
強制終了するための方法は二つあります.
一つは, ジョブを表で再開させ, C-c で強制終了する方法です.
つまり下のようにします.

  $ fg %2             <- sleep 600 を表で再開
  sleep 600
  ^C                  <- C-c で強制終了
  $

もう一つは, 表で再開させずに終了させます.

  $ kill %3           <- 3 番目のジョブ (sleep 3600) を強制終了
  $

== それ以外のジョブ・プロセス

jobs で表示されるのは, 現在使っているターミナル (シェル) から実行した
ジョブのみです.
しかし, ターミナルを複数を立ち上げたときには, ある一つのターミナルで
打った jobs では, すべてのターミナルのジョブを把握できません.
また, ユーザはあまり意識しませんが, ユーザがログインした段階で,
コンピュータ上では様々な仕事がユーザによって行われています.
例えば, 画面の下部に表示されている, アプリケーションのアイコンが
並んでいるバー (Dock) も, 気づかないうちにユーザが起動したジョブ/プロセスです.

(ターミナル (シェル) から起動された処理は
「ジョブ」と呼ばれ, その他のものは「プロセス」と呼ばれるようです.
その用語の意味に基づけば, Dock はターミナルから起動したものでは
ありませんので「プロセス」と呼ぶ方が適切なのでしょう.)

そのような多数のプロセスを管理するためのコマンドがあります.
それは ps です.
例えば, ps の結果は下のように表示されるでしょう.

  $ ps
  PID TTY          TIME CMD
  12020 pts/0    00:00:00 bash
  12511 pts/0    00:00:00 ps

ps にオプションや引数を付けずに実行すると, jobs とほぼ同じような
情報のみ表示されます.
最後の行には, 実行した ps コマンド自体のプロセスも表示されています.
jobs との違いは, ジョブの番号ではなく, PID (Process ID) で表示されて
います.
PID は, その計算機で動作しているすべてのプロセスに割り当てられた,
プロセス固有の番号です.

では, ps には多数のオプション・引数がありますが, 例を紹介します.

  $ ps x

とすると, 表示されるプロセスの数が増えます.

  $ ps x
  PID TTY      STAT   TIME COMMAND
  12008 ?        Ss     0:00 /lib/systemd/systemd --user
  12009 ?        S      0:00 (sd-pam)
  12020 pts/0    S      0:00 bash
  12517 pts/0    R+     0:00 ps x

これは, ターミナルから明示的に実行されたわけではないプロセスも
表示されているためです.
例えば, Dock もこれに含まれます.

ここでは詳しく述べませんが, 自分が作ったプログラムが,
自分の意図に反して終了しない (例えば, 無限ループしてしまう) ような
場合, ps で, そのプログラムの PID を調べ,

  $ kill <PID>          <- <PID> は実際には番号

とすることで強制終了させることがしばしばあります.

== 練習

ps に aux のオプションを付けて実行しなさい.

この時, 一番左の項目が, それぞれのプロセスを実行しているユーザです.
どのようなユーザのプロセスが実行されているか確認しなさい.
(結果は何行も表示されて, 画面がスクロールしてしまうでしょう.
このようなときにはどのようなコマンドを打つと 1 ページずつ結果を
見ることができるでしょうか?)


= 参考資料