5.3 シェル
オペレーティングシステムは,プログラムの実行を支えてくれる基本ソフトウェアですが,それ自体はユーザが直接使うようにはできていません.ユーザからの指示を受け取り,適切なプログラムを起動する仲介役が必要です.最近はメニューやアイコンを使用するのが一般的ですが,UNIX では伝統的なテキストベースのユーザインターフェースを持つシェル(shell)も使用できます.
対話的に使うシェルは,端末ウィンドウ一つについて一つ起動されています.端末ウィンドウの中に % が表示されているのは,シェルがユーザからのコマンド入力を待っている印です.
シェルの主な役割はユーザからのコマンド入力に従って,プログラムを起動することです.単に起動するだけでなく,入出力の繋がりを変えたり,プロセスの一旦停止や再開を指令したりできます.
標準入出力
プログラムがユーザと情報をやり取りする方法は,主に次の二つです.
- 標準入出力:端末ウィンドウでキーボード入力と文字の表示を行います.
- X ウィンドウ:独自のウィンドウを作り,文字以外にマウスやメニューによる入力,グラフィックスの表示ができます.
X ウィンドウの方が初心者には親切ですが,標準入出力には次のような利点があるため,熟練者には広く使われています.
- マウス操作よりキー操作の方が簡潔で効率的であることが多い.
- プログラムを簡単に作成できる.
- 次に説明するリダイレクションやパイプを使って,他のプログラムと組み合わせて使うことができる.
標準入出力とファイル引数の関係
X ウィンドウを使わないコマンドが必ず標準入出力を使うわけではありません.入力と出力のそれぞれについて,コマンドは次の3つのタイプに分けることができます.
- 標準入出力を使わない.ファイルや X ウィンドウやネットワークとデータのやり取りをする.
- 必ず標準入出力を使う.
- 引数でファイルが指定されると,そのファイルとデータのやり取りをする.引数が指定されないと,標準入出力を使う.
例えば,ls コマンドは入力がタイプ1で出力がタイプ2です.lpr コマンドは入力がタイプ3で出力がタイプ1です.
リダイレクション
標準入出力は,キーボード入力と端末ウィンドウに接続されているのが普通ですが,この接続をファイルに切り替えることができます.これをリダイレクション(redirection)と言います.
- 出力をファイルに切り替えるには,コマンドの後ろに「>」とファイル名を書きます.例えば, ls -l の結果を xxx というファイルに保存する場合は次のようにします.
% ls -l >xxx %
- 保存した結果は普通のテキストファイルなので,他のコマンドで使うことができます.
% more xxx total 813 drwx------ 4 hattori 512 Apr 15 17:50 Mail drwxrwxrwx 4 hattori 512 May 6 16:01 Wnn -rw-r--r-- 1 hattori 76 Apr 19 15:10 test %
- 入力をファイルに切り替えるには,コマンドの後ろに「<」とファイル名を書きます.more コマンドの入力はタイプ3なので,xxx の内容を見るのに次のようにすることもできます.
% more <xxx total 813 drwx------ 4 hattori 512 Apr 15 17:50 Mail drwxrwxrwx 4 hattori 512 May 6 16:01 Wnn -rw-r--r-- 1 hattori 76 Apr 19 15:10 test %
パイプ
あるコマンドの出力と,別のコマンドの入力を接続するには,二つのコマンドを「|」(縦棒)で区切って書きます.これをパイプ(pipe)と言います.
例えば,
% ls | more |
と入力すると,ls と more が並行して実行され,ls の出力が次々と more の入力に渡されていきます.
シェルのジョブ管理機能
フォアグラウンドとバックグラウンド
端末ウィンドウでコマンドを入力すると,シェルがそれを受け取り,コマンドを起動します.シェルはコマンドが終了するまで休止状態になるので,端末ウィンドウではコマンドだけが動いているように見えます.このようなコマンドの実行方法をフォアグラウンドジョブ(foreground job)と言います.
これに対して,コマンドの後に「&」を付けて実行すると,シェルが休止状態にならないので,続けて他のコマンドを実行できます.このようなコマンドの実行方法をバックグラウンドジョブ(background job)と言います.
- 標準出力を使うコマンドでもバックグラウンドで実行できますが,シェルのプロンプトや他のコマンドの出力と混ざって見づらくなります.
- 標準入力を使うコマンドをバックグラウンドで実行すると,入力が受け取れなくて停止します.
ジョブ管理
現在のシェルで実行しているバックグラウンドジョブは, jobs コマンドで知ることができます.
% jobs [2] + Running xdvi -expert -s 5 08.dvi [3] - Running netscape %
最初に書いてある数字がジョブ番号です.ジョブ番号を他のコマンドの引数として使う時は,前に「%」を付けます.
バックグラウンドジョブをフォアグラウンドに変更するには,fg コマンドで
とします.逆に,フォアグラウンドジョブを バックグラウンドにするためには, まず,C-z により,フォアグラウンドジョブを一時停止させる必要があります.
% fg %2 xdvi -expert -s 5 08.dvi
この状態ではジョブは停止しています.バックグラウンドにするには, bg コマンドを使って
^Z Suspended % jobs [2] + Suspended xdvi -expert -s 5 08.dvi [3] - Running netscape %
とします.fg コマンドおよび bg コマンドにおいてジョブ番号を省略すると, jobs コマンドの表示で + のついているジョブに対して操作が行われます.
% bg %2 [2] xdvi -expert -s 5 08.dvi %
ジョブ管理をまとめると,次のようになります.
- C-c:フォアグラウンドジョブを終了させます.
- C-z:フォアグラウンドジョブを一時停止させます.
- kill %ジョブ番号:ジョブを終了させます.
- fg %ジョブ番号:フォアグラウンドジョブにします.
- bg %ジョブ番号:バックグラウンドジョブにします.
練習問題
- 端末ウィンドウで emacs (& をつけない)を実行し,シェルのプロンプトが出ないことを確認しなさい.
- 上の emacs を一時停止させなさい.この状態で emacs のウィンドウを操作するとどうなりますか?
- 上の emacs をバックグラウンドジョブにしなさい.
複数のコマンド
1行に複数のコマンドを並べて書くこともできます.
% cd; ls |
これは,
% cd % ls |
と2回に分けて入力するのと同じことになります.パイプの | やバックグラウンドの & も同じように複数のコマンドをつなげることができますが,順に実行されるか,並行して実行されるかが違います.
コマンドをまとめて扱って欲しいとき(正確には別のシェルによって実行する)には,次のようにします.
% (date; hostname) |
シェルスクリプト
さらに,自分で新しいコマンドを作ることが出来ます.
ここでは,例として,pwd と ls -laF を一度に実行するような myls.sh というものを作ってみましょう.
まず,emacs を起動して,次のように入力してください.
pwd ls -laF |
入力できたら,ファイル名を myls.sh として保存しましょう.ファイル名に
.sh をつけるのを忘れないで下さい.
保存したら,端末ウィンドウをアクティブにします.
そして,先程作ったファイルのアクセス権を変更して実行可能にします.
% chmod +x myls.sh |
ここまでできたら
% myls.sh |
と入力してみると,ちゃんと自分の希望通りの結果が得られるはずです.
このように,ファイルの内容をシェルのコマンドとして実行するものをシェルスクリプト(shell script)といいます.
注意:シェルには何種類かあります.対話的に使うシェルと,シェルスクリプトを実行するシェルの種類が違うことが多く,書き方が多少異なることがあります.