Linuxを使いこなしたいけれど,使い慣れたWindowsとは操作方法が違うので思うように操作できない。この壁を取り払うのが本コラムの目的です。Linuxやその上で動くソフトウエアを実際に使うために役立つ知識や操作方法を説明します。
今回は,プロセス管理やジョブ管理について紹介します。

 Linuxでは,複数のユーザーが複数のアプリケーションを同時に使用できます。例えば,あるユーザーは,Webブラウザでインターネットを閲覧しながら,テキスト・エディタで文書を編集することができます。また,その最中に,別のユーザーが同じシステムにログインして,メールを送信するといったことも可能です。このようにLinuxシステムでは通常,複数のアプリケーションが同時に動作しています。

 そこで今回は,複数のアプリケーションが動作している状況などを管理するプロセスやジョブの管理について解説します。

プロセス管理をマスターする

 Linuxでは,あらゆるアプリケーションは「プロセス」として管理されます。プロセスは次のような情報を保持します。


・ユーザー
・作業ディレクトリ
・環境変数
・使用中のファイル

 このような情報を保持することにより,同じアプリケーションを実行しても,「実行するユーザーによって結果が異なる」,「環境設定により表示される言語が異なる」といった結果が生まれます。

プロセスの起動

 プロセスは,アプリケーションを実行することによって生成されます。言い換えれば,「実行中のアプリケーションはプロセスとして管理される」となります。アプリケーションは次のような方法で実行します。


(1)メニューからアイコンを選択する
(2)デスクトップなどでアイコンをダブル・クリックする
(3)「アプリケーションの起動」からコマンド名を入力する
(4)シェル上でコマンド名を入力する

 (3)は,Windowsのスタート・メニューにある「ファイル名を指定して実行」とほぼ同じ手順で起動する方法です。Fedora Core 4ではデスクトップ・メニューから選択できましたが,Fedora Core 5ではメニューから削除されました。Alt+F2キー(Altを押しながらF2を押す)でコマンド名の入力画面が表示されます(写真1)。

写真1●「アプリケーションの起動」の画面
写真1●「アプリケーションの起動」の画面
GNOME環境であればAlt+F2キーで起動する。

 このほかにも,システムの起動と同時に起動されるプロセス(Webサーバーなど,デーモンあるいはサービスと呼ばれるプロセス)もありますが,今回は直接起動するプロセスについて見ていきます。

GUIでのプロセス管理ツール

 さまざまなアプリケーションが「プロセス」として動作していることは,GUIツールで簡単に確認できます。ここでは,Fedora Core 5のGNOME環境を例にとって,プロセスの管理ツールを紹介します。

 [デスクトップ]-[管理]-[システム・モニタ]を選択します。このツールのコマンド名は「gnome-system-monitor」ですので,前述の「アプリケーションの起動」やシェルからも起動できます。[プロセス]タブに,現在稼働中のプロセスが一覧表示されます(写真2)。ここにある「ID」はプロセス番号と呼ばれる数値で,Process IDentifier(プロセス識別子)を略して「PID」と表記されます。アプリケーションを実行すると自動的に割り当てられ,1つのLinuxシステムで稼働中のプロセスごとに異なるPIDが割り当てられます。数値の大小に優越はありません。

写真2●システム・モニタで稼働中のプロセスを確認できる
写真2●システム・モニタで稼働中のプロセスを確認できる

 システム・モニタには,次のような機能があります。順番に紹介していきます。

●負荷状況の表示機能

 画面の上部で過去1分,5分,15分のCPUの平均負荷を確認できます。写真2では「1,5,15分後の平均負荷」と表示されていますが,間違いです。数値は,CPUによる処理を待っているプロセスの数を表します。大きいほどシステム負荷が高くなっているということです。このツールでは,このほか[リソース]タブでメモリーの使用量やネットワーク使用量を含めたリアルタイム情報も確認できます。

●検索機能

 [プロセス]タブを表示している時にキー入力を行うと,「プロセス名」を検索できる窓が開きます。ここにプロセス名またはその一部を入力すると,検索ができます。

●表示項目の選択機能

 [編集]-[設定]の[プロセスタブ](写真3)から表示させる列を選択可能です。

写真3●システム・モニタで確認できる項目の表示/非表示を設定
写真3●システム・モニタで確認できる項目の表示/非表示を設定

●並び替え機能

 各列の名前をマウスでドラッグ&ドラッグして,列名の並び替えが可能です。写真2では,ID列を一番左に移動しています。

 また,列名部分をクリックすると,プロセス名,状態,メモリーの常駐量(「Residentメモリ」)などを昇順,降順で並び替えできます。前述の表示項目の選択機能と組み合わせて使用すれば,CPU利用率が高いプロセスなどを見つけやすくなります。

●表示プロセスの選択機能

 [表示]をクリックすると,表示するプロセスを「全てのプロセス」「ユーザのプロセス(ユーザーが実行しているプロセス)」「実行中のプロセス」から選択できます(写真4)。

写真4●システム・モニタの[表示]メニュー
写真4●システム・モニタの[表示]メニュー
表示するプロセスを切り替えられる。

●優先度の変更機能

 プロセスのある行を右クリック,もしくはプロセスを選択後に[編集]をクリックして,[プロパティの変更]を選ぶと,優先度を変更できます。優先度とは,プロセスが複数稼働中に,そのプロセスがどれだけ優先的にCPUで処理されるかの設定です。-20(一番高い)~19(一番低い)の40段階で設定できます。優先度が高い方が低い数値になっています。

●使用ファイルの一覧機能

 プロセスのある行を右クリック,もしくはプロセスを選択後に[表示]をクリックして,[オープンしたファイル]を選ぶと,プロセスがアクセスしているファイルを一覧表示できます。写真5の例では,susumeというユーザーが起動しているWebブラウザ(Firefox)がアクセスしているファイルを表示しています。ホーム・ディレクトリ(/home/susume)以下のたくさんのファイルを使用していることが分かります。「FD」とは,ファイル・ディスクリプタと呼ばれる番号です。詳しくは後述します。

写真5●プロセスが使用しているファイルの一覧表示
写真5●プロセスが使用しているファイルの一覧表示
Firefoxの場合。

 さらに,プロセスを選択中に[メモリ・マップ]を選択すれば,そのプロセスがどのようなライブラリを使用しているのかが表示されます。

●プロセス管理機能

 プロセスのある行を右クリック,あるいはプロセスを選択後に[編集]をクリックすれば,プロセスの終了,強制終了,停止,再開ができます。

プロセスの親子関係

 あるプロセスから別のプロセスを実行すると,それらのプロセスに親子関係が生じます。

 [システム・モニタ]の[表示]メニューから[依存関係]をチェックすれば,子供のプロセスが親プロセスの真下に表示されます。写真2では,「GNOME端末」(gnome-terminal)プロセスの子プロセスとして,シェル(bash)・プロセスが動作していることが分かります。さらに,GNOME端末で実行したコマンドはbashの子プロセスとして実行されています。

 シェル上で次のように実行すれば,sleepプロセスがbashプロセスの子プロセスとして実行されることが分かります(写真6)。


$ sleep 10  ←何もしない
$ ←10秒後に表示される

写真6●シェル上でsleepを起動したときのシステム・モニタの例
写真6●シェル上でsleepを起動したときのシステム・モニタの例

 子プロセスが実行されると,親プロセスの環境が引き継がれます。環境とは,以前本コラムで紹介した変数などです。例えば,言語設定を表す変数LANGです。bashの設定が日本語であれば,bashから実行されるコマンドにもその環境設定がコピーされ,実行結果は日本語で表示されます。英語に変更すれば英語でメッセージが表示されます(図1)。

図1●言語設定(LANG変数)の変更例
図1●言語設定(LANG変数)の変更例

プロセスの終了

 アプリケーションに異常が発生し,通常の方法で終了ができなくなることがあります。この場合,システム・モニタから終了できることがあります。前述したように,終了させたいプロセスを選択し,右クリックして[プロセスの終了]をクリックします。これでも終了できない場合は,プロセスを選択した後,右クリックをして[プロセスの強制終了]を選択します。

 プロセスの終了,強制終了,停止,再開といった機能は,選択したプロセスに対して「シグナル」を送信することで実行されます。シグナルを受け取ったときの動作は,アプリケーションの作者が決めています。そのため,アプリケーションによっては,“停止”を送信しても何も変化しないことがあります。

 ただし,“強制終了”は特別なシグナルで,どのようなプロセスであっても終了するように動作します。

 なお,一般ユーザーは,他のユーザーが起動したプロセスを終了できません。

シェル上のプロセス管理

 シェルのコマンドラインからプロセスを管理するための主なコマンドを,表1に示します。

表1●プロセス管理の主なコマンド
表1●プロセス管理の主なコマンド

 稼働中のプロセスをコマンドラインで一覧表示するには,psコマンドを使用します。


$ ps 
 PID TTY     TIME CMD
3208 pts/1  00:00:00 bash
5355 pts/1  00:00:00 ps

 シェル・プログラム(bash)と今起動したpsがプロセスとして稼働していることが分かります。

 TTYは使用しているターミナルを表し,ttyコマンドでも確認できます。


$ tty 
/dev/pts/1

 ターミナルを複数使用していると,「1」の部分が2や3になります。

 オプションを付けないでpsコマンドを実行すると,コマンドを実行したユーザーが起動したプロセスを表示します。すべてのプロセスを表示するには,axオプションを使用します(-は付けません)。

 ただし,このオプションを付けると多くのプロセスが表示されすぎて,必要な情報を確認しづらいことがあります。「 | grep (キーワード)」を付けて実行すれば,目的の情報が見つけやすくなります。例えば


$ ps ax | grep terminal 

 とすれば,terminalという文字を含むgnome-terminalなどのプロセス情報が表示されます。

 親子関係を確認したい場合は,psコマンドのfオプションを付けるか,pstreeコマンドを使用します(図2)。

図2●プロセスの親子関係を確認した例
図2●プロセスの親子関係を確認した例

 図2のinitプロセスは,Linuxシステムを起動後,最初に実行されるプロセスです。IDは必ず1になります。すべてのアプリケーションは,このinitプロセスの子プロセスです。

 稼働率の高いプロセスを調べたいのであれば,topコマンドが便利です。オプションを指定しなければ5秒間隔でCPU稼働率の高いプロセスを一覧表示します。実行時「-d 数値」オプションを指定するか,topコマンド実行後,「d 数値」を入力すれば,更新間隔を変更できます(図3)。一番最初の行にある「load average」は,GUIツールで紹介した過去1分,5分,15分のCPUの平均負荷です。uptimeコマンドでも確認できます。

図3●topコマンドの実行例
図3●topコマンドの実行例
1秒間隔でCPU稼働率が高いプロセスを一覧表示した。
[画像のクリックで拡大表示]

 プロセスが使用しているファイルは,lsofコマンドの-pオプションや-cオプションで確認できます。一般ユーザーでも実行できますが,標準的な一般ユーザーのPATH設定では登録されていない/usr/sbinディレクトリにあるコマンドです。-pオプションではIDを指定し,-cオプションではコマンド名を指定します(図4)。

図4●lsofコマンドを使ってプロセスがアクセスしているファイルを確認しているところ
図4●lsofコマンドを使ってプロセスがアクセスしているファイルを確認しているところ
[画像のクリックで拡大表示]

プロセスの終了

 プロセスの終了は,killコマンドを使用します。killコマンドでは,プロセスをプロセス番号(PID)で指定するため,事前にpsコマンドなどでPIDを調べておく必要があります。

 killという名前ですが,「プロセスに対して,シグナルを送信する」コマンドです。シグナルには多くの種類があり,「$ kill -l 」(オプションは小文字のエル)で確認ができます(図5)。主なシグナルについては,表2に示します。

図5●シグナルの一覧を表示
図5●シグナルの一覧を表示

表2●主なシグナル
表2●主なシグナル

 送信したいシグナルは,「-9」のように図5で表示された数値で指定しても,「-HUP」や「-SIGHUP」のような文字列で指定しても構いません。

 プロセスの終了で通常使用するのはSIGTERM(15番)とSIGKILL(9番)です。シグナルを省略すると,SIGTERMが送信されます。従って,プロセスを終了させたい時は次の順で試みてください。


・アプリケーションを正規の手続きで終了
・「$ kill (PID) 」で正常終了
・「$ kill -9 (PID) 」で強制終了

 killの代わりにkillallコマンドを使えば,PIDでなくプロセス名で指定できます。ただし,同じプロセス名で稼動しているプロセスが複数あれば,すべてにシグナルが送信されます。必要以上に終了しないように,事前にどのプロセスが該当するのかを確認しておいた方が無難です。

 また,デスクトップ環境上で動作しているGUIアプリケーションを終了するのであれば,xkillコマンドが使用できます。


$ xkill 

 実行後にマウス・カーソルの形が変わるので,終了させたいウインドウをクリックします。キャンセルするにはCtrl+cキーを入力します。

関連ファイルの内容を表示

 システム・モニタやpsなどのコマンドは,/procディレクトリの中にあるファイルに従って実行結果を表示しています。/procは「プロセス・ファイル・システム」と呼ばれる特殊なディレクトリで,実際はハード・ディスク内にはなく,Linuxシステムのメモリー内部をファイルやディレクトリに見せかけて表示します。

 プロセス情報は,/procディレクトリ以下の数値ディレクトリに格納されます。数値は動作中のプロセス番号と一致するので,


$ ls -d /proc/[0-9]* 

とすれば稼働しているプロセス番号が分かります。

 このディレクトリの中には今まで見てきたプロセス情報が,多くのファイルやディレクトリとして入っています。直接見る必要はないのですが,catやlsで一度は眺めておくと良いでしょう。

ジョブの操作方法

 デスクトップ環境からマウス操作で起動されるアプリケーションもコマンド名を指定すればコマンドラインから起動できます。例えば先ほどのシステム・モニタであれば,


$ gnome-system-monitor 

で起動できます。ただ,上記の通りに実行したのであれば,システム・モニタを終了するまでコマンドライン上ではプロンプトが表示されません。

 コマンド名の後に&を付けて実行することで対処できるのですが,その仕組みを理解するには,「ジョブ」という考え方を知っておく必要があります。

 ジョブとは,コマンドライン1行で実行した複数のコマンド(プロセス)をまとめる概念です。

 通常のコマンド実行においては,1つのジョブが1つのプロセスに対応することが多くなります。ただし,次のように実行した場合は1つのジョブには複数のコマンド(プロセス)が含まれます。


$ コマンドA ; コマンドB 
 (コマンドを続けて実行)

$ コマンドA | コマンドB 
 (コマンドAの実行結果を
  コマンドBの入力として実行)

$ コマンドA && コマンドB 
 (コマンドAが正常に実行でき
  たらコマンドBを実行)

$ コマンドA || コマンドB 
 (コマンドAが正常に実行でき
  なかったらコマンドBを実行)

上記の例では,「コマンドA ; コマンドB 」が一つのジョブになります。このジョブは,コマンドAとコマンドBという2つのプロセスで成り立つわけです。

バックグラウンド・ジョブ

 &を付けない通常の実行方法を「フォアグラウンド・ジョブ」と呼び,&を付けた実行を「バックグラウンド・ジョブ」と呼びます。ジョブ管理用のコマンド操作を表3に示します。

表3●ジョブ管理のコマンド,操作
表3●ジョブ管理のコマンド,操作

 フォアグラウンドでコマンドを実行した場合,実行が終了になるまでbashは待ち状態になります。従って他のコマンド実行はできません。

 この場合,ターミナル上でCtrl+zキーを入力すると次のように表示されます。


[1]+ Stopped gnome-system-monitor

 フォアグラウンドで実行していたプロセスは停止状態になりました。このキー操作は,フォアグラウンドで動作しているプロセスに対して停止(SIGTSTP,20番)のシグナルを送信したことになります。

 この後,


$ bg 
[1]+ gnome-system-monitor 
&
$ ←プロンプトが表示される

とすれば,バックグラウンド・ジョブとして動作します。「$ fg 」とすればフォアグラウンド実行になります。

 バックグラウンドで実行した場合は,シェルはジョブ番号を表示した後にプロンプトを表示するので,違うコマンドの実行が可能です。

 プロセス番号はシステムの中で一意に決まる番号ですが,ジョブ番号は各シェルごとに1から発番される番号です。

 バックグラウンドで実行されているジョブはjobsコマンドで確認できます。


$ jobs 

[1]+ Running gnome-system-monitor &

 []の中の数値がジョブ番号です。+の記号はパラメータなしでfgコマンドやbgコマンドを実行したときの対象とするジョブを表します。

 ジョブ番号を指定して実行するには,「$ fg %ジョブ番号 」のようにジョブ番号の前に%を付けます。killコマンドでも「%ジョブ番号」での指定が可能です。

 また,フォアグラウンド実行中,Ctrl+cキーとすれば終了(SIGINT,2番)のシグナルを送信できます。

実行結果のステータス

 すべてのコマンドは正常に実行できたかどうかを示すステータス(状態)を持ちます。このステータスは「$ echo $? 」で確認できます。0が正常に実行できたことを表し,0以外は正常に実行できなかった(エラーなどがあった)ことを表します(図6)。

図6●実行したコマンドのステータスを確認した例
図6●実行したコマンドのステータスを確認した例

実行時の出力先

 コマンドの通常メッセージの出力先とエラー・メッセージの出力先は,別々に管理されています。それぞれの出力先のことを「標準出力」,「標準エラー出力」と呼びます。内部的な数値では標準出力は1番,標準エラー出力は2番と決められています。この番号はファイル・ディスクリプタと呼ばれる番号で,0,1,2は決められています(0番は「標準入力」と言い,通常はキーボードからの入力を表します)。

 この状況は,写真5で示した「オープンしたファイル」や図4のlsofコマンド,/proc/プロセス番号/fdディレクトリの中のシンボリック・リンクなどで確認できます。


$ ps | grep bash ←PID確認 
2703 pts/1 00:00:00 bash
$ ls -l /proc/2703/fd/ 
合計 4
l (略) 0 -›/dev/pts/1
l (略) 1 -›/dev/pts/1
l (略) 2 -›/dev/pts/1
l (略) 255 -›/dev/pts/1

 通常のコマンド実行であれば標準出力,標準エラー出力共にコマンドを実行しているターミナル(上記だと/dev/pts/1)に対して表示されるため,実行結果をファイルに保存(リダイレクト)をすると,違いが分かります。

 例えば,作業ディレクトリにfileという名前のファイルは存在するが,xxxという名前のファイルは存在しないときに,次のように実行するとよく分かります。


$ ls file xxx 
ls: xxx: そのようなファイルやディレクトリはありません
file

 ここで表示されている「ls: xxx: そのようなファイルやディレクトリはありません」は標準エラー出力に対して出力され,「file」は標準出力に対して出力されています。従って,


$ ls file xxx ›result
ls: xxx: そのようなファイルやディレクトリはありません

 上記のように実行結果をresultというファイルに保存しようとしても標準エラー出力はそのままターミナル画面に表示されます。「>の前に2(標準エラー出力の番号)を指定すると,標準エラー出力をファイルに保存できます。逆に今まで使用していた「>の前に1(標準出力の番号)を指定しても同じ動作となります。数値を指定しない「>は標準出力の保存先を指定したことになります。


$ ls file xxx 2›err 

file

 標準出力も標準エラー出力も同じファイルに保存したい場合は次のように記述します。


$ ls file xxx ›result 2›&1 

 これは,「標準出力は『result』というファイルに保存し,標準エラー出力は標準出力と同じファイルに保存する」,という意味になります。

「どこにも出力しない」出力先

 前述のようにシステム・モニタをコマンドラインからバックグラウンドで実行すると,bashの環境を引き継ぐので,そのままでは標準出力や標準エラー出力のメッセージはコマンド入力をしたターミナル画面に表示されてしまいます。これらの出力が突然出てくるのが邪魔であれば「/dev/null」という特殊なファイルに保存します。nullとは「何もない,空(から)」という意味で,ハード・ディスク上に存在しない仮想的な空のファイルです。


$ gnome-sysytem-monitor ›/dev/null 2›&1 & 

とすればバックグラウンドで実行しているシステム・モニタが何かメッセージを出したとしても,気にせず別のコマンドが実行できます。