[Shell] シェル

UNIXのコマンドラインインターフェイスである「シェル」について説明している。シェルの機能と概念はUNIXを利用していく上でとても役に立つと思うので、がんばって習得してほしい。

「研究に使うUNIXとその機能」のページから独立(2000/8/2)

[back!] 研究に使うUNIXとその機能
[go!] バージョン管理


* はじめに

UNIXの対話的コマンドインタプリタはシェルと呼ばれる。基本機能はコマンドを実行することだが、プログラミング言語としても使われるほど、非常に高機能である。UNIXで利用できるシェルには何種類かあるが、以下では主にtcshを扱う。

UNIXの初心者で、まず何から学ぼうかと考えている人には、著者は何はともあれ、シェルの機能を試してみることを勧める。シェルの機能のうち、これだけ覚えておけばたいていは大丈夫である。

  1. コマンドの実行(コマンドを打ち込むだけ)
  2. 標準入出力とリダイレクト、パイプ
  3. ジョブ制御
  4. プログラミング機能(特に繰り返し処理)

はじめの3つは、その機能とともに概念も学んでほしい。将来、数値計算や実験データ処理のプログラムを書くとき、標準入力や標準出力を使うことを知っているのと知らないのとでは、プログラムを書く手間、利用する手間がまったく違う。UNIXの思想の一つに、小さくて簡単なプログラムをいくつか組み合わせて仕事をするという考え方がある。シェルのパイプとリダイレクトの機能は、その思想の根幹に関わる重要な機能である。(と言っても、実は簡単なんですけどね。)

最後のプログラミング機能は、知っているのと知らないのとでは、作業効率がまったく異なる。特に実験データを処理している過程で、たくさんあるファイルの全てを同じように処理する、あるいは全てのファイルの名前をつけかえる、などの処理を頻繁に行う。シェルのプログラミング機能を知っていると、これは数行のコマンドで済み、後は処理が終わるまでコーヒーを飲みながら待っていられる。知らないと…、ご苦労さまです。著者なら30秒で終わる仕事を、1 時間以上かかってエッチラオッチラやっているのを見るのは可哀想である。


* 標準入出力とリダイレクト、パイプ

最近気づいたことだが、上に書いた「著者なら30秒で終わる仕事を、1時間以上かかってエッチラオッチラやっているのを見るのは可哀想である。」を読んで、シェル・プログラミングについて勉強しようと思う学生は、結構いるらしい。日本人は損をすることを嫌う民族なのだと強く感じる。しかしその前にまずは標準入出力とリダイレクト、パイプについて理解するほうがはるかに基礎的で、重要な概念である。それに研究活動の多くの場面で、実際に何度も使うはずである。

ここでは、標準入出力とリダイレクト、パイプについて、ごく基礎的な概念のみを説明する。

* 標準入出力

標準入出力は、シェルの機能ではなくUNIXのすべてのプロセスに共通する機能であり、UNIXの思想、哲学の一端でもある。標準入出力については、この文書に書いてあることだけでなく、手元の参考書なども当たってきちんと理解しておくべきだろう。

UNIXのプロセスには、標準の入出力が3つ用意されている。

標準入出力の種類
名前 FORTRANの
ユニット番号
Cの
ファイル番号
Cの
高水準入出力
標準入力 5 0 stdin
標準出力 6 1 stdout
標準エラー出力 0 2 stderr

通常、これら3つの入出力はすべて「端末」に結び付けられている。つまり標準入力はキーボードからの入力、標準出力と標準エラー出力は、画面への出力となる。UNIXのコマンドのほとんどは、この標準入出力を利用している。

* リダイレクト

以下では流体研の標準的なシェルであるtcshの機能を説明する。これ以外のシェルも同等の機能を備えているが、コマンドの指定方法は異なる場合がある。

リダイレクトとはシェルが持っている基本機能の一つで、実行するプログラムの標準入出力を、ある特定のファイルに切り替える機能である。たとえば標準出力をあるファイルにリダイレクトすると、今まで画面に表示されていた内容がファイルに保存される。実際に使ってみると、これが非常に便利な機能であることが分かると思う。

ファイルへのリダイレクト(>)を用いるときは要注意である。リダイレクト先のファイルがすでにあるときには、そのファイルの内容が書き換えられる。リダイレクト先を間違えて重要なファイルを消したりせぬよう、利用には気をつけてほしい。また利用しているシェルによっては、すでに存在するファイルへのリダイレクトに警告を促す機能がある。tcshもこの機能を持っている。

* パイプ

パイプもリダイレクトと同じくシェルの機能の一つで、あるコマンドの標準出力を、他のコマンドの標準入力につなぐ機能である。

たとえばホームディレクトリの容量を各ディレクトリごとに分けて計算し、その結果を大きい順に並べ替えて、上位25個を表示する、というコマンドは、次のようになる。

% du -ko ~ | sort -nr | head -25

du -ko ~というコマンドが、ホームディレクトリ以下の各ディレクトリの容量を、キロバイト単位で計算し出力する。sort -nrduの出力を入力として受け取り、数字ベースで降順で出力する。最後のhead -25sortの出力を入力として受け取り、その頭の部分25個を出力する。それぞれのコマンドの機能の詳細は、マニュアルを参照してほしい。

この出力をファイルに保存しておくには、上のリダイレクトを組み合わせて、次のようにする。

% du -ko ~ | sort -nr | head -25 > file

また結果を印刷するには、lp(1)コマンドを用いる。lpコマンドは引数を指定しなければ標準入力を読み込んで印刷するので、これをパイプの最後につなげるだけである。

% du -ko ~ | sort -nr | head -25 | lp

なお実際には間にa2psを挟んで、出力をPostScript形式に直す方が、読みやすい印刷結果が得られる。

% du -ko ~ | sort -nr | head -25 | a2ps | lp

この例のsortのように、標準入力を読んで何らかの処理をし、結果を標準出力に書き出すプログラムをフィルタプログラム 、あるいは単にフィルタと呼ぶ。UNIX上で利用できるコマンドの多くは、フィルタとしても使える。

UNIXの哲学の一つとして、一つ一つは小さな機能しか持たないコマンドをいくつか組み合わせて、いろいろな仕事を上手にこなそう、という考え方がある。フィルタプログラムとパイプの機能は、このような目的にピッタリなので、 UNIX上で多用される。


* ジョブ制御

UNIXの重要な特徴の一つに「マルチユーザー・マルチタスクOS」というのがある。つまり1台の計算機を複数の人が同時に使い、また同時に複数の仕事をさせることができる、という意味である。

この機構の詳細は参考書などを当たってもらうことにして、ここではこの機能をシェルから利用する方法をいくつか紹介する。

* プロセスの一時停止

たとえばemacsやmuleを用いて作業している途中で、シェルに戻って何かをしたくなったとしよう。方法はいくつかある。

  1. ウィンドウシステムを使っているなら、新しい端末エミュレータを起動 してそこで作業する。
  2. emacsのShellモードを用いて、emacsの中でシェルを使う。
  3. emacsを一時停止(サスペンド、suspend)しておいて シェルに戻る。

ここで紹介するのは、emacsを一時停止させる機能である。これはemacsに限らず、どのようなプロセスの実行中でも利用できる。プログラムを一時停止させるには、そのプロセスの実行中に"Control"+"z"キーを押す。(Controlキーを押し下げた状態で"z"キーを押す、という意味)

ただちに実行中のプロセスが停止してシェルに制御が戻る。

* ジョブコントロール

ここで気をつけてほしいのは、先ほどまで実行していたプロセスは一時停止しているだけで、終了していないということである。emacsを一時停止した状態でシェルプロンプトにもう一度"emacs"と打ち込むと、新しいプロセスが実行される。つまりemacsが2つ実行されることになる。

あるシェルから起動され、現在実行中のプロセスや一時停止しているプロセスを調べるには、jobsというコマンドを打ち込む。

minnie@cobalt[43]~> jobs
[1]  + Suspended (signal)            emacs
minnie@cobalt[44]~>

上の例の場合は、emacsが一時停止している。

シェルで必要な作業を行った後、再びemacsに戻りたくなったら、 fgというコマンドを打ち込む。これで一時停止しているプロセスに戻る。

* フォアグラウンド、バックグラウンド

先ほどの"fg"は「フォアグラウンド」の意味で、一時停止しているプログラムを前面に持ってくる、というような意味合いである。これに対して「バックグラウンド」という概念がある。たとえばフォアグラウンドでemacsを使って作業している間に、その裏(バックグラウンド)で数値計算のプログラムを走らせておく、などができる。

あるプロセスをバックグラウンドで実行するには、プロセスの実行の際に "&"を付けておく。たとえば以下のようにする。

minnie@cobalt[44]~> ./calc_something &
minnie@cobalt[45]~>

計算が終了しないうちに、すぐシェルプロンプトが戻ってくる。計算が続行中かどうかは、先ほどと同様 "jobs" コマンドで調べる。

minnie@cobalt[45]~& jobs
[1]  + Suspended (signal)            emacs
[2]  - Running                       ./calc_something
minnie@cobalt[46]~&

この例の場合、emacsは一時停止しているが、calc_somethingはバックグラウンドで実行中である。ここで注意したいのは、calc_somethingが標準出力や標準エラー出力に何かを出力すると、たとえemacsの実行中でもそれが画面に表示されてしまう、ということである。これがうっとうしいから標準出力をファイルに落としたいときには、…前の節で説明しましたね。リダイレクトを使う。

この状態で"fg"を実行すると、emacsの方がフォアグラウンドになるであろう。emacsではなくcalc_somethingの方をフォアグラウンドにしたい場合には、fg %2と番号(ジョブ番号)を指定する。

現在フォアグラウンドで実行しているプロセスをバックグラウンドに回したいときには、まずそのプロセスをControl+zで一時停止してから、 "bg"コマンドを用いる。

* プロセスを殺す

プロセスが何らかの事情で正常に終了できなくなることがある。プログラムの書き間違いなどで無限ループに入ったり、停止したままになる場合が多い。このようなプロセスは強制終了させる。一般にこの作業を、物騒な言葉だがプロセスを「殺す」と表現する。

もう一度先ほどの例を挙げる。

minnie@cobalt[45]~& jobs
[1]  + Suspended (signal)            emacs
[2]  - Running                       ./calc_something
minnie@cobalt[46]~&

calc_somethingを強制終了させるには、次の方法がある。

* まとめ

ジョブ制御に関連して、以下のことを説明した。

すべてに精通する必要はないが、ジョブ制御はUNIXのマルチタスク機能に密接に関わる概念なので、少なくともその考え方と概要は理解してほしい。


* シェル・プログラミング

上でも述べたが、シェルはプログラミング言語としても使える。実験データの処理などで"パターン化された作業"があるなら、それをシェルで書いたプログラム「シェルスクリプト」に書いておき、それをコマンドとして利用すると便利である。

UNIXの機能の一つで、FORTRANで書いたプログラムも、Cで書いたものも、シェルで書いたプログラムも、スクリプト言語であるAwkやPerlで書いたプログラムも、すべて「コマンド」として同じように利用できる。詳細は説明しないので、手元の参考書を調べてほしい。

UNIXのシェルは非常に賢い。上手に使って楽をしよう。


<- トップページ
工学院大学機械工学科流体研

リンクはご自由に。でもメールをくれると嬉しいな。

金野 祥久  konno@researchers.jp

Last modified: Thu Aug 3 09:32:55 JST 2000