UNIX が稼働する計算機にログイン (login) してからログアウト (logout) するまでの間,利用者と UNIX との間を仲介するプログラム *1 が動いている.このプログラムを UNIXではシェル (shell) と呼ぶ.本節では,Linux の標準シェルである bash (Bourne again shell) について,その概略を述べる.*1 コマンド・インタープリタ (command language interpreter).すなわち,「利用者がキーボード (keyboard) から入力した文字を集め,それを解釈して何をすればよいのかを判断し,そして実行する」動作を繰り返すプログラム.利用しているシェルの種類は,
$ echo $shell $SHELL![]()
で調べることができる.
UNIXで仕事をするにはコマンドを入力する.コマンドとは,あるまとまった仕事を計算機に依頼するためについた一連の命令文のことである.コマンドの一般形は,次のようになる.
$ コマンド名 [オプション] [引数]![]()
コマンド名は,実行する UNIX の命令またはプログラムの名前である.オプションは,そのコマンドが実行する条件を記述する.引数は,コマンドが用いるデータの入ったファイルの名前である.
コマンド名,オプションおよび引数は,1 つ以上の空白で区切る.「[ ]」 は,コマンドにより必要ではない場合もあることを示す.
コマンドを解釈実行するものをコマンドインタープリタ(シェル)と呼ぶ.コマンドの実行は,UNIXのプロンプトにつづいてコマンドを入力し,コマンド行の終りを示すを入力する.コマンドの実行が終了するとシェルがプロンプトを表示する.
コマンドの実行を例をあげて説明する.引数をつけないコマンドとして date をあげる.
$ dateTue Apr 11 13:39:29 JST 2000
ここでシェルは,date コマンドを実行し,その後 「$」 で表されるプロンプトを表示して次の入力を待つ.このプロンプト 「$」 が表示されている状態で入力・実行できるコマンドがシェルコマンドである.Emacs 等のエディタのコマンドとは区別してほしい.
次の例は引数を 2 つもつ.
$ ls -la /home![]()
この場合 「-la」 と 「/home」 がそれぞれオプションとファイル名であり,その間は一つ以上の空白で区切られている.この場合の 「l」 と 「a」 の順番は,入れ換えても同じ結果が得られるが,間には空白を入れてはいけない. UNIXにはオンラインマニュアルがあり,コマンドの使い方やオプションについて知ることができる.オンラインマニュアルを表示するコマンドが man である.man は次の形式で使用する.
$ man [セクション] 知りたいコマンド![]()
ここで [セクション] はオプションであり, man のセクションを数字(1から8)で指定する.man ページは複数のセクションに分けて納められている.一般的な利用者向けのコマンドはセクション 1 にあり,この他,セクション 3 には C 言語のライブラリ関数の説明がある.セクションの指定を省くと,最も最初に現われる項目が表示される.コマンドと C の関数名と同じことはよくあるので,セクションが違うと説明の内容が異なって来るので注意すること(例えば 「man printf」 と 「man 3 printf」 では表示される内容が異なる.試してみよ).
オンラインマニュアルは基本的には英語で書かれているが,日本語版が存在すれば日本語で表示される. man コマンドの使い方は,次のように表示することができる.英和辞典を利用してでも man だけは読んでおくことをすすめる.さらに,本書では説明しない各種コマンドの使用法や便利なオプションを自ら探求することを期待する.
$ man manman(1) man(1) NAME man - format and display the on-line manual pages manpath - determine user's search path for man pages SYNOPSIS man [-acdfhkKtwW] [-m system] [-p string] [-C config_file] [-M path] [-P pager] [-S section_list] [section] name ... DESCRIPTION (省略)
SYNOPSIS はコマンドの形式を表し,[ ] の中は省略可能なものを示す.マニュアルの続きを読みたければ「スペースキー」を押す.一回押すごとに一画面ずつスクロールする.途中で終了したければ小文字の 「q」 を入力する.いきなり一画面分スクロールしたのでは読めない人は,「
」 を逐一入力して読めばよい.
どのようなコマンドがあるか知らないうちは,キーワードを用いる.これは英単語のつづりの一部分だけでコマンドを検索してくれる便利な機能である.ディレクトリに関するコマンドを調べたければ,
$ man -k directory![]()
とする.directory と打つのが長ければ,direct でも dir でもよい.キーワードは大文字,小文字を区別しないので,DirectorYでもよい.
なお,man の他にも皆さんのシステムには多くのドキュメントが用意されている.詳しくは /usr/share/doc/ 以下の OS 付属の文書を参照して欲しい.
■課題 man を使う
man コマンドを使って,bash や ls などこれまでに出て来たコマンドおよび C 言語の関数(たとえば fgets など)について調べてみよ.
UNIX上で動作するコマンドは,標準入力 (stdin),標準出力 (stdout),標準エラー出力 (stderr) を持つ(図 3.3).特に何もしなければ,標準入力はキーボード,標準出力,標準エラー出力はディスプレイになっており,図 3.4 のように標準入力から標準出力へという流れになっている.
図 3.3: コマンドと,標準入力,標準出力,標準エラー出力の関係
図 3.4: 標準入力から標準出力までの流れ
この統一された概念は極めて簡潔で,かつ十分な能力を与えてくれる.以下に挙げるリダイレクション,パイプラインも組み合わせることで,コマンドを組み合わせて便利に利用することができる.
(1) リダイレクション
UNIX には標準入力,標準出力という考え方がある.3.2で説明したように,ディスク上のプログラムだけでなく,キーボードやプリンタといった入出力機器もファイルとして扱える.
$ ls -las /home![]()
標準入出力の先は,水道の蛇口のようにパイプで自由に継ぎ換えることができる.上記の例の出力は,標準出力すなわちディスプレイに表示される.
この先を切り換えて,この出力をファイルに書き込みたければ次のようにすればよい.
$ ls -las /home > kekka![]()
これをリダイレクション (redirection) という.
図 3.5: 出力のリダイレクション
このコマンドの結果は kekka という名前のファイルに書き 込まれ,ディスプレイには表示されない.つまり,標準出力がディスプレイからファイル kekka に切り換わったのである(図 3.5).なお「>」を「>>」にかえると,現在あるファイルの最後に追加してくれる.
この逆に,標準入力をキーボードからファイルに変更することも可能である.反対向きの不等号「<」を使って,上で作った kekka を入力として,コマンド sort で並べ換えてみる.
$ sort < kekka![]()
図 3.6: 入力のリダイレクション
キーボードからデータを入力しないのに,ディスプレイには,kekkaの内容が小さい順に並んで出力されているはずである.これは「<」によって*2 sort コマンドの標準入力がキーボードから,kekkaに切り換ったためである(図 3.6).
*2 これらの「>」をイケ,「<」のことをコイと読む人もいる.同様にして,入力と出力の両方をリダイレクションすることもできる.標準出力をファイルに切り換えただけでは,エラーメッセージはファイルに書き込まれず,ディスプレイに表示されてしまう.これは標準エラー出力がディスプレイのままになっているからである.エラーメッセージもファイルに出力させたいのなら,
$ コマンド >& ファイル![]()
とする.これでエラー出力もファイルにつなぎ換えることができる.
(2) パイプライン
bash には,標準出力をファイルに書かないで,直接コマンド同士を結合するパイプライン (pipeline) 機能がある.
$ ls -las /home | sort![]()
と打てば,「ls -las /home」 の結果を自動的に sort コマンドが小さい順に並べて,画面に表示してくれる.「|」はパイプ (pipe) と呼ばれ,コマンドの標準出力を次のコマンドの標準入力につなげる機能をもつ.このパイプはいくつもつなげることができる.前項の例では,ls の結果を一旦ファイル 「kekka」 に書き,その後 sort にリダイレクトした.パイプを使えば,「kekka」 のような作業ファイルを作成しなくても同じ処理を行なうことができる.
図 3.7: パイプラインこの例では,コマンド lsの標準出力を,次のコマンド sortの標準入力にパイプでつなげている(図 3.7).このような sort,grep,awk や漢字コードの変換をおこなう nkfのように,標準入力からの入力を処理をして,結果を標準出力に出すように設計されたプログラムをフィルタ (filter) と呼ぶ.パイプは,フィルタを上手に使うためのメカニズムを提供してくれる.
■課題 リダイレクション
リダイレクション・パイプに関する本文中の例を実際に実行してみよ.途中で作成されるファイル kekka は cat コマンドで中身を確認せよ.【例】
$ cd (まず自分のホームディレクトリに戻る) $ ls -las /home > kekka $ ls $ cat kekka $ sort kekka $ ls -las /home | sort
通常,ファイル名は英数字と 「.」(dot, period) から成る.この「.」は,主にファイルの種類を示す拡張子を表すためによく用いる.たとえば,
$ lsa.out sample sample.c sample.o sample.p sample.pl sample.tex
この例では,「a.out」 と,「sample」 までは同じ名前で拡張子が異なっている 6 つのファイルがある.では,これらのファイルから同時にいくつかを操作したいことが起きたしよう.これには 「*」が便利である.「*」 は 0 文字以上の任意の文字列を表すので,
$ ls sample.*sample.c sample.o sample.p sample.pl sample.tex
このコマンドの意味は「sample.」 で始まるファイルを全て表示せよ」となる.全てでは困るときのために,任意の一文字を表す「?」がある.
$ ls sample.?sample.c sample.o sample.p
これならば,「pl」と 「tex」 という拡張子のついたファイルは表示されずにすむ.
その他の例を下にあげる.
* 0 文字以上の任意の文字列 ? 任意の 1 文字(??とすれば任意の 2 文字) [ ] [ ] の中のどれか 1 文字,-はその範囲 sam* sam ではじまるもの.sam 自身も含む. s??? s ではじまり,4 文字 s[1-5] s1, s2, s3, s4, s5 を示す これらの便利な文字をメタ文字 (meta-character) と呼ぶ.
これらのメタ文字を利用すると便利だが,初心者のうちは意図しないことが発生することが多い.例えば,引数をエコー表示するコマンドに echo がある.「*」 の一文字を echo を使って表示しようとした場合はどうだろう.
$ echo *a.out sample.c sample.o sample.p sample.pl sample.tex
「*」はシェルによってファイル名に展開され,結果は現作業ディレクトリにあるファイル名が表示される.これでは lsと同じである.では 「*」という文字を表示させたい場合はどうすればよいか.これには引用符「'」で囲むか,「\」 (backslash) を前につければよい.「\」 もまたメタ文字であるので,「\」 という文字自身を指定する場合は 「\\」 でよい.
$ echo '*'*
または
$ echo \**
メタ文字の持つ意味を消去して,その文字自身を表すことをエスケープ (escape) という.また,そのために使われる文字(ここでは 「\」)をエスケープ文字 (escape character) という.「\」 は,1文字のエスケープに使用する.文字列のエスケープには「'」(シングルクオート)または「"」(ダブルクオート)で文字列を囲む.
「'」は,「|」,「\」,「'」 を除く全ての特殊記号の意味をなくす.また「"」は,空白,「$」, 「`」, 「!」, 「\」,「'」,「"」 を除く全ての特殊記号の意味をなくす.
■課題 ワイルドカードの使用
touch コマンドを使うと中身のないファイルを作成することができる(本来はファイルの修正時刻を書き換えるために使うコマンドである).以下のようにすると本文中の例にある 「sample.c, sample.o, sample.p, sample.pl, sample.tex」 というファイルを作成できるので,例にあげられていたコマンドを実際に自分で実行しなさい.
$ touch sample.c sample.o sample.p sample.pl sample.tex $ ls sample.* (など)
bash では,Emacs と同じキーバインドで,コマンド行の編集ができる.たとえば,「+f」と「
+b」でコマンド行内でカーソルを動かしたり,「
+k」でカーソル以降の文字を消去する等が可能である.
bash は以前に入力(実行)したコマンドを履歴として保存し,それを再び実行することができる.この機能により,以前に入力した長いコマンドや,直前のコマンドを簡単に再実行することができる.「
+p」 と 「
+n」 および「↑」,「↓」キーで前のコマンド,後のコマンドを次々に呼び出すことができる(Emacs と同じキーバインドである).
現在の履歴を表示するには,history コマンドを用いる.
$ history1 ls sample.? 2 echo * 3 echo '*' 4 echo \* 5 history
ここで左端に表示された1〜5の番号は,コマンドの入力された順番である.直前のコマンドをもう一度打つ代りに !!と打つとシェルは直前に入力されたコマンド(この場合5番のコマンド)が,再び入力されたと解釈し実行する.
$ !!2 echo * 3 echo '*' 4 echo \* 5 history 6 history
履歴リストには最新のコマンドが保存数だけ記録される.ここで今度は 4 番目に実行した「echo \*」 を再実行してみる.これには二通りの指定方法がある.
$ !ececho \* * $ !4
echo \* *
上の 「!ec」 は 「ec」 で始まる最後に実行したコマンドを再実行する.下の 「!4」は4番目に入力したコマンドを再実行することになる.
ログアウトするとこの履歴リストは消去されてしまう.しかし,シェル変数 savehist を設定しておくと,ログアウト時に ~/.bash_historyファイルに履歴リストが保存され,次回のログイン以降でも,この履歴リストを利用できるようになる.
■課題 ヒストリ機能の使用
「+p」 と 「
+n」 および「↑」,「↓」キーを使って,実際に自分が使ったコマンドの履歴を呼び出してみよ.
bash では,コマンドやコマンド列に別名 (alias) を付けることができる.つけた別名はコマンドと同じように利用できる.別名を定義するには,
$ alias 別名=定義![]()
とすればよい.別名の後には 「=」に続けて定義を書く.これには 2 つ以上のコマンドを指定したり,すでに定義した別名を指定したりできる.定義の中にメタ文字がある場合は,引用符で囲む.「=」 の前後に空白をいれてはいけない.
$ alias h=history![]()
こうしておけば「h」と打つだけで history と同じ結果が得られる.
$ alias xx='clear; date'![]()
これは xxの 2 文字で 2 つのコマンドを順に実行するように定義している.この中で 「;」 は「clear コマンドを終了した後に続けて date コマンドを実行せよ」の意味で,連続実行を示している.
alias で指定した別名は,ログアウトするまでの間しか有効でないので,常にその別名を使いたければ,3.4.3で示すように 「~/.alias」ファイル中に定義しておくとよい.
■課題 alias の設定
本文中の alias の例を実際に設定し,実行してみよ.
$ alias h=history $ h $ alias xx='clear; date' $ xx
コマンドを実行した後,プロンプトが出力されるまでの状態を考えよう.たとえば,C のコンパイラ gcc を実行する.
$ gcc sample.c![]()
この仕事をフォアグラウンドジョブ (foreground job) と呼ぶ.bash はフォアグラウンドジョブが終了するまで次のプロンプトを表示しないので,利用者は次の仕事にとりかかることができない.この例のように,実行時間がかかるのがわかっている場合は 「&」 を後につけて,バックグラウンドジョブ (background job) として実行する.バックグラウンドジョブを発行すると,ジョブの終了を待ちあわせずにただちにプロンプトが返ってくるので,次の仕事にとりかかることができる.
$ gcc sample.c &[1] 1239
bashは,この C プログラムをコンパイルするバックグラウンドジョブに,ジョブ番号 「1」 を与える.「1239」 はプロセス識別番号 (PID) (これについては本書の範囲を越えるのでここでは特にふれない)である.
現在バックグラウンドで動いているジョブの状態を知るには,jobsコマンドを用いる.
$ jobs -l[1]- 1239 Running gcc sample.c &
ジョブの状態には,次のものがある.
状態 意味 Running 実行中 Stopped 一時停止中 Done 終了 Terminated 強制終了 Exit 異常終了 プログラムに文法的な誤りがなければ,しばらくした後に,以下のメッセージがでる.
[1] Done gcc sample.cフォアグラウンドジョブおよびバックグラウンドジョブを制御するコマンドとして 次のものが用意されている.
^Z フォアグラウンドのジョブを一時停止させる ^C フォアグラウンドのジョブを強制終了させる bg 一時停止中のジョブをバックグラウンドジョブとして再開する fg 一時停止中のジョブをフォアグラウンドジョブとして再開させる kill ジョブを強制終了させる ジョブを終了させるには,jobs コマンドで調べたときの [ ] で囲まれたジョブ番号を用いる.
$ kill %1![]()
以上の関係を図 3.8 に要約する.
図 3.8: ジョブの状態遷移
■課題 バックグラウンドジョブの実行
前の課題で作成した C のソースプログラム 「kuku.c」 を 「gcc kuku.c &」 としてバックグラウンドでコンパイルした場合と,「gcc kuku.c」 としてフォアグラウンドで実行した場合に画面上どのような違いがあるかを確かめよ.
$ gcc kuku.c $ gcc kuku.c &なお,gcc で 「-o」 を使ってコンパイル・リンク後の実行ファイル名を指定しなかった場合,実行ファイルは 「a.out」 という名前になる.これを実行するには 「$ ./a.out
」 とすればよい.
UNIXでは利用者が各人の好みに合わせて専用の環境を設定し,作業環境を向上させることができる.このためにつぎで説明する環境変数およびシェル変数があり,これらを環境設定用ファイルで記述する.
環境変数
環境変数では,システム全体の動作環境を設定する.この変数はプロセスが参照し,ログイン時にシェル変数から引き継ぐものとシステムで決められているものがある.それぞれの変数は,利用者が設定できる.環境変数の参照,設定および解除は,つぎのように行なう.環境変数は,シェル変数と区別するために大文字を使用する.
環境変数の参照 env 環境変数の設定 export 環境変数名=値 環境変数の解除 unset 環境変数名 シェル変数
シェル変数は,シェルがコマンドを解析し実行する時に参照する変数である.設定されているシェル変数は,現在動作しているシェルの中でのみ有効である.シェル変数は,環境変数と区別するために小文字を使用する.シェル変数の参照,設定および解除は,つぎのように行なう.
シェル変数の参照 set シェル変数の設定 変数名=値 シェル変数の解除 unset 変数名
環境設定ファイルには,シェル変数,エイリアス,コマンドの検索パスなどの設定を記述する.よく使用される環境設定ファイルをつぎに示す.これらのファイルは,各利用者のホームディレクトリに置き,ファイル名の先頭に「.」を付け他のファイルと区別する.
.profile ログイン時の設定情報を記述する.ログインした時に一度実行されログアウトまで参照されない. .bashrc bash の設定情報を記述する.bash 起動時に参照される. .alias aliasの設定を記述する.bash 起動時に,.bashrc から参照される. .emacs エディタ emacs の設定情報を記述する.emacs 起動時に参照される.設定を間違えるとemacsが満足に動かなくなるので,設定を変えるときは,SuSE Linuxの場合,.gnu-emacs-customのほうを書き換える. .gnu-emacs-custom エディタ emacs の設定情報を記述する.個人的に emacsの設定をいろいろ変えたいときには,こちらに書いておくとよい. これらのファイルは,シェルやコマンドにより参照される.また,UNIXの種類によっては,これら以外に,「.login」,「.logout」,「.xinitrc」,「.xsession」 などの他の設定ファイルが利用されることもある.
シェルはログイン時に自動的に起動される.シェルはその際に,各利用者のホームディレクトリにある 「.profile」 ファイルと 「.bashrc」 ファイルを順に参照し,その利用者の利用環境を設定する.最後にプロンプト 「$」 を表示する.以下に代表的な例をあげてみよう.
$ cat .profile...
$ cat .bashrc...
シェルからのログアウト(終了)には exit を用いる. 「.profile」と 「.bashrc」 をエディタで編集した場合は,必ず下のように source コマンドを利用して,所望の結果が得られるか確認しなければならない.もしこの確認をせず,設定に致命的な誤りがあるのに気がつかなかった場合,最悪,次回ログイン時にログインできなくて困ってしまうこともあるので注意してほしい.
$ source .profile![]()
または
$ source .bashrc![]()
通常改めてログインしなおしても設定は反映されるが,sourceコマンドによって一旦ログアウトして改めてログインしなくても,ファイルに書き込んだ新しい環境に変更することができ便利である.
■課題 設定ファイルを見てみよう
皆さんの環境では実際にはログイン時に 「~/.bashrc」,「~/.profile」 が実行される前に 「/etc/profile」や「/etc/bash.bashrc」 などが実行されている.実際にcatやlessコマンドを使ってこれらのファイルを表示し,どんな設定が行われているのかを確認せよ.