| シェル | リダイレクション | パイプ | ヒストリ | ジョブ管理 | シェルスクリプト | 環境設定 |
UNIX / Linux でターミナルソフト (kterm など)を利用する場合、ユーザはプロンプトで操作目的のコマンドを入力し、そこで表示される結果を見てまた次のコマンド入力を行う、というサイクルで対話的な作業を行います。本当は UNIX / Linux の中核(kernel: カーネル)が管理している機能を用いて、ユーザは様々な処理を行っているのですが、カーネル自身はユーザと直接対話する能力を持っていません。そこで、ユーザと対話する能力を持ち、カーネルに対して操作のお伺いを立てる仲介役のプログラムが、ユーザとカーネルの間に存在してユーザは操作を行います。この仲介役プログラムは、ユーザから見てカーネルの周りをすっぽり覆っている「殻」(shell) のように見えることからシェルと呼ばれます(図1参照)。簡単に言えば、シェルは、ユーザが入力したコマンドを解釈してカーネルに処理を依頼し、その結果やメッセージなどを画面に表示する機能を持っているのです。
実際には、ユーザがログインしてターミナルソフトを起動している間、そのターミナル内でシェルは動き続け、常に対話的な処理の仲介役を担っています。シェルの動作を図示すると図2のようになります。
![]() 図1. シェルとカーネルの関係 |
![]() 図2. シェルの動作 |
最近のコンピュータは GUI で利用することが多く、ログインすると GUI の環境が利用できます。 CUI のためのターミナルを起動せずともマウス操作で様々な処理を行えますが、このマウスによる操作も実はカーネルに伺いを立てています。そう考えると、GUI の環境もカーネルの周りを覆っているシェルと言えます。ですが、この授業では従来の UNIX / Linux の操作を説明することに主眼を置いているので、特に説明がない限り「シェル」と言えばプロンプトでコマンドを入力する CUI のシェルのことを指します。
シェルは大別すると、B-Shell (Bourne-Shell) 系、C-Shell系のシェルに分けられます。本学の cc環境の Linux では、C-Shell系の1つである tcsh が標準のシェルとして設定されています。この授業では tcsh の使用を前提に話を進めます。
Bourne-Shell 系のシェルの例には、sh, bash, zsh, ksh などが挙げられます。sh はシェルスクリプトでよく利用されるもので、ユーザとの対話的な処理には bash がよく利用されています(最近の Linux や Mac OS X などでは bash がシェルの標準環境となっています)。
シェル(ここでは tcsh)には、以下のような機能があります。
シェルの一番基本的な機能として、コマンドインタプリタの機能があります。これには、次の動作が含まれます。
このようなコマンドの逐次解釈を行うプログラムをコマンドインタプリタ (command interpreter) と言います。この機能は tcsh に限らずどのシェルも持っています。
ls コマンドや cp コマンドなどは、C言語で書かれコンパイルされたプログラムです。プロンプトで ls と打てば、ls というプログラムファイル(実体は /bin/ls )を検索して起動します。中には pwd コマンドや cd コマンドのように、独立したファイルでなくシェル内部に組み込まれたコマンド(シェルコマンド)もあります。それらはインタプリタの解釈の時点で組み込みのコマンドとして認識して対応する処理を行います。
シェルは入力・実行されたコマンドの履歴を記録する機能を持っており、過去に実行したコマンドとその実行時刻を後で確認することができます。その確認には history コマンド(シェルコマンド)を利用します。
書式: history [整数]
整数を指定すると、それまでに実行した指定個数分のコマンドを表示します。整数を指定しない場合は、80個分のコマンドを表示します。
シェルのヒストリ機能を利用して、以前に実行したコマンドを特定のキーバインド (key binding) によってコマンドライン上に再度呼び出すことができます。
これにより、過去に入力した長いファイル名などを再度入力する手間が省けます。
コマンドライン上の文字の編集には、テキストエディタで利用するカーソル移動や編集のキーバインドがそのまま利用できます。Linux では標準的に Emacs のキーバインドが適用されており、cc環境でも同様に Emacs のキーバインド(下表参照)が有効です。
カーソル上の一文字を消去 | Ctrl-d | カーソルより右側を消去 | Ctrl-k |
カーソルを左に移動 | Ctrl-b | カーソルを右に移動 | Ctrl-f |
カーソルを1単語左に移動 | Esc-b | カーソルを1単語右に移動 | Esc-f |
カーソルを行頭に移動 | Ctrl-a | カーソルを行末に移動 | Ctrl-e |
コマンド入力時に、コマンド名やファイル・ディレクトリ名を表す文字列の途中までキー入力した状態で Tab キーを押せば、残りの文字列が自動補完して表示されます。この機能は、入力途中の文字列の以降が唯一特定される場合に限り補完されます。長いファイル名やディレクトリ名のすべてをいちいちキー入力する手間が省けるので、作業効率アップには欠かせない機能です。具体例を示せば、ホームディレクトリにて、
cc2000(145)% cd D
とだけ入力して、Tab キーを押せば、
cc2000(145)% cd Desktop
と自動的にディレクトリ名 Desktop を補完してくれます。ここではホームディレクトリ下に D で始まるファイル名やディレクトリ名が Desktop しかないことから補完が有効です。仮にホームディレクトリ下に Destroy という名のファイルがあれば、Desk まで入力してからでないと Destroy と区別できないので補完できません。そういう時には Ctrl-D を押すことで、その時点での複数の候補を表示してくれます。
alias コマンドを用れば、既存のコマンドの略称や複数のコマンドを組み合わせたものを別名 (alias) として定義することができます。
書式: alias 別名 正式なコマンド名
ただ単に alias とだけ書いて実行すると、今まで定義した別名の一覧を表示します。
また、unalias コマンドは設定した別名 (alias)
を破棄するものです。
書式: unalias 別名
alias を利用して、非常によく利用するコマンドやオプション・引数の組み合わせを、より短い文字列(略称)として別名を定義しておけば、ユーザは同じ操作でもキータイプ数を少なくすることができます。(例えば、ls -l を ll と定義するなど)
「過去のコマンドの再呼び出し」と「コマンドライン上の編集」を合わせれば、キーバインドは Emacs の基本編集操作とまったく同じです。ですのでカーソルキーを使わない Emacs の編集操作に慣れてしまえば、コマンドライン上の入力編集操作も同一の操作感で利用できることになります。そうすると、手はキーボードの標準位置から移動させる必要がなくなり、様々な CUI の操作場面で作業効率アップに繋がります。さらに「コマンド補完」「別名定義」の機能を有効に利用できるようになれば、もっと作業効率が上がることになるでしょう。また、それらの操作をマスターすることが UNIX / Linux らしい使い方をマスターすることの基本でもあるのです。コマンドライン上ではなるべくこれらの機能や操作方法を使うよう心がけましょう。
UNIX / Linux の標準的なコマンドには、標準入力と標準出力と呼ばれる入出力を処理対象としているものが、数多くあります。普通にシェルを使っている時は、標準入力はキーボードからの入力、標準出力はデイスプレイへの出力が割り当てられています。
実際にいろいろ UNIX / Linux を利用していると、標準出力(ディスプレイ)に表示される結果をファイルに保存したり、あらかじめテキストファイルに書いてあるデータをキーボードの代わりに入力として利用した方が都合よい場合があります。また、あるコマンドの結果を次の別のコマンドの入力にしたい時もあります。これらを実現するための機能が、リダイレクションとパイプの概念になっています。
以下にリダイレクションとパイプの利用方法について簡単に説明しますが、標準入出力の話も含めた詳しい内容は別資料 (PDF) を参照して下さい。
あるコマンドが画面に表示する結果を直接ファイルに書き出したり、既にあるファイルに書いてある内容をキーボード入力の代わりに利用することをリダイレクションと言います。
書式: コマンド < ファイル名
書式: コマンド > ファイル名 新しくファイルを作成してコマンドの表示結果を保存
書式: コマンド >> ファイル名 既存のファイルの末尾にコマンドの実行結果を追加
(秋学期のプログラミングの授業で、C言語を使ってリダイレクションと起動時引数についての説明を行います)
あるコマンドからの出力を別のコマンドに入力する仕組みをパイプライン(パイプ:pipeline / pipe)と言います。 このパイプラインを利用することで、複数のコマンドを組み合わせた処理を簡単に行えます。
書式: コマンド1 | コマンド2
コマンド1とコマンド2をパイプラインでつないで、 コマンド1の標準出力をコマンド2の標準入力とします。パイプを複数使えば、幾つものコマンドを連携させて実行させることも可能です。次の図は、2つのパイプを使って、3つのコマンドを連携させる場合の動作イメージです。
シェルでは * と ? は特殊文字として扱われ、特定の文字ではなく「任意の文字」という意味を持つ「メタキャラクタ」として解釈されます。
* は任意の長さ(長さ0を含む)を持つ文字列に適合します。文字列の長さも文字の種類も不問なので、あらゆる文字列に適合します。例えば、a* と書けば「a で始まる文字列(a のみを含む)」と解釈されます。また、k*.gz とすれば、「k で始まり、.gz で終わる文字列」と解釈されます。この * は特別に「ワイルドカード」(wild card) と呼ばれます。たくさんのファイル名を一度で扱いたい場合などに有効な機能です。
? は任意の1文字を表します。文字列ではなく1文字にのみ適合します。* が文字列の長さを制限しないのに対し、適合させる文字数を制限・特定させたい場合に利用します。例えば、a??.txt と書けば、「aで始まって2文字続いた後に.txt で終わる文字列」と解釈されます。
シェル変数や環境変数を用いてユーザ独自の環境を設定できます。これについては、コンピュータ・リテラシでは詳しく扱いませんが、set コマンドや env コマンドで環境設定に関する情報を閲覧することができます。興味ある人は man tcsh や man env などでシェル変数や環境変数の設定についていろいろ調べてみましょう。
UNIX / Linux (UNIX) では、現在行っている処理以外の処理を同時に実行させることができます。これをバックグラウンドジョブ (background job) と言います。コマンド行の後に&を入力すると、バックグラウンドジョブとなります。これをうまく利用することで、効率よく作業することができます。ジョブとは、コマンド行より1行で入力された処理のことで、それぞれのコマンドで起動されるプログラムは「プロセス」(process) と言います。
書式: コマンド1; コマンド2 ;コマンド3
コマンド1が終了したら、コマンド2実行され、コマンド2が実行されたらコマンド3というように、コマンドが連続に処理されます。ただしパイプとは違い、コマンド1の結果をコマンド2に渡すわけではありません。
例: hello.c の翻訳と実行を連続で行う cc2000(80)% gcc hello.c; ./a.out ... cc2000(81)%
コマンドファイルは一連のコマンドを書き込んだファイルであり、それを呼び出すと一連の操作をキーボードから入力する代わりに、ファイルの記述内容を順次解釈して実行します。コマンドファイルの実行は tcsh コマンドで行います。
また、if 文や while 文など制御文が利用でき、C言語で行うような複雑な処理もプログラムとして作成することが可能です。実際、UNIX / Linux 自体には起動には多くのシェルスクリプトが利用されています。
皆さんの身近なところで存在しているシェルスクリプトの例には、ホームディレクトリ下の .login や .cshrc が挙げられます。これらのファイルの中身を辿っていくと、各ユーザのプロンプトの表示内容を設定したり、コマンドを検索するパスを設定したり、様々な環境変数を設定したり、などシェルの動作に関する情報がたくさん書き込まれています。UNIX / Linux の動作の仕組みをより深く知りたい人はこれらのファイルの解析を行ってみましょう。