UNIX入門:全ページ版
* 以下の各項が1ページ(約3k程)となっているスライド版もあります。内容やリンクに変化はありません。
目次
- 0. "Hello World!" --- 先ずは,プログラムを作って動かしてみよう ---
- 1. ユーザとコンピュータ
- 2. ファイルシステム (File System)
- 3. コマンドの入力形式と基本コマンドの操作
- 4. 正規表現 (Regular Expression)
- 5. 入出力とそのリダイレクト (I/0 & I/O Redirection)
- 6. ファイル管理
- 7. コマンドの省略:「エイリアス」
- 8. コマンドのパスと登録:
~/bin と rehash
- 8.1. コマンドのパス
- 8.2. パス(PATH)の通し方
- 8.3. コマンドの登録
- 付録:UNIX Hierarchy と歴史
0. "Hello World!" --- 先ずは,プログラムを作って動かしてみよう ---
UNIXでプログラミングをしてみましょう。「プログラミング?そんなのできるの?」といった疑問や不安は要りません。次の作業を順を追って,1つ1つ,丁寧にこなすだけです。面倒臭がらずやるか否かのみです。
ここで作成するプログラムは,ただ単に次を表示するという単純な作業をさせるプログラムです。
Hello World! Message
ですが,プログラミングの第一歩は,そのような簡単な作業をさせるか否かではなく,先ずはプログラムを書くか否かです。
0.0. 準備
プログラムを書くと,その内容を一つのファイルとして残します。その保存場所を作りましょう。UNIX のサーバーに接続した状態,あるいは UNIX のターミナルの画面から,太字部分を入力毎にリターンを押します。
% mkdir My_Programs (プログラムを保存するディレクトリ"My_Programs"を作成) % cd My_Programs (ディレクトリ"My_Programs"へ移動)
注) 次回 login
時は,"cd My_Programs
"と打てば,同じ状態になります。
「ディレクトリ」とは,Macintosh や Windows でいうフォルダ。
準備完了。
0.1. シェル
「シェル」は,UNIX のコマンド解釈装置でもあり,コンピュータの起動処理もシェルで書かれている程,UNIX を動かす上での基礎的要素。カーネル(kernel, 核)と呼ばれる中枢部分をあたかも覆う貝殻(shell)という意味合い。ここでは,そのようなシェルを使って,プログラムを作ってみます。
文字をファイルに書くために「エディタ」と呼ばれるソフトを利用します。UNIX には,"vi" や "emacs" といった有名なエディタがあります。ここでは,余り日本では使われていないエディタ"pico"を利用してみます。(pico は,私が Ph.D を取得した大学,University of Washington が作成したエディタ。機能は余りないが,単純明快で良い。)
pico を起動します。
% pico
すると,次のような画面になるでしょう。(現在は,GNU nano になっています。)
|
■pico 操作方法
^ (caret) は,「control (CTRL) キーを押しながら」という意味。
・pico 終了:^X
・ファイルの保存:^O
・カーソルがある文字の削除:^D
・カット:^K
・ペースト:^U
・文字列探し:^W
・マニュアル:^G
さあ,いよいよ,プログラミングです。次の青字部分を打ってください。(改行は,リターンキー。"Message" 部分には,好きなメッセージを。)
|
注意) 1行目にある /bin/sh
は,奥山研究室のサーバーの場合です。他のサーバーの利用者は,エディタを起動する前に,次を実行してください。
% which sh
その答えを /bin/sh
部分に入力します。
出来ましたか?それでは,ファイルを保存します。次の手順を踏んでください。
- pico におけるファイル保存
^O
(ファイル保存入力画面へ)- "
hello.sh
"と入力し,リターン。 (ファイル名 "hello.sh
" で保存) ^X
(pico 終了)
これで"hello.sh
"という「シェル・スクリプト」(プログラム)ができました。実行させましょう。
実行方法は,次の通りです。
% sh hello.sh
すると,次のようになるはずです。
% sh hello.sh Hello World! Message %
実行権を与えると,"./hello.sh
"と打つだけで動きます。
% chmod u+x hello.sh (あなた (user) だけに実行 (excute) の権限を与える (+)) % ./hello.sh (hello.sh を実行) Hello World! Message %
0.2. Perl
Perl は,インターネットでのチャットや掲示板,アクセス・カウンターなどの CGI で利用されているスクリプト言語です。シェルと次に扱うC言語の良い要素を使いやすくまとめたような言語で,CGI だけでなく,様々な用途に使用可能ですので,多くの方が利用しています。
早速,プログラミングしましょう。エディタを使って,次のように入力してください。
#!/usr/bin/perl print "Hello World!\n"; print "Message\n";
注意) 1行目にある /usr/bin/perl
は,奥山研究室のサーバーの場合です。他のサーバーの利用者は,エディタを起動する前に,次を実行してください。
% which perl
その答えを /usr/bin/perl
部分に入力します。
入力完了後,"hello.pl
"として,ファイル保存してください。これで"hello.pl
"という「Perl スクリプト」の完成です。
実行方法は次の通りです。
% perl hello.pl
シェル・スクリプトのときと同じように,実行権を与えれば,"./hello.pl
"と打つだけで動きます。実行権の与え方は,次の通り。
% chmod u+x hello.pl
0.3. C言語
シェルにしても Perl にしても,実行権を与える前は,次のように実行のためのコマンドを打つ必要がありました。
% sh hello.sh % perl hello.pl
これらの意味は,シェル・スクリプトの場合には「シェル (sh
) がスクリプト"hello.sh
"の中身を解釈し実行しなさい」,Perl スクリプトの場合には「Perl (perl
) がスクリプト"hello.pl
"の中身を解釈し実行しなさい」というものです。すなわち,「スクリプトの解釈 -> 実行」という手順を踏んでいる訳です。このような言語を「インタプリタ」と言います。
これに対し,実行ファイル用のソースを作成し,そのソース・ファイルから実行ファイルを生成する方法があります。このような言語を「コンパイラ」と呼びます。コンパイラの場合,「ソースの作成 -> 実行ファイルの生成 (コンパイル) -> 実行」という流れになります。当然,実行ファイルが既にあるということは,インタプリタに比べれば,「解釈」がないだけ実行速度が速くなることを意味します。
コンパイラで有名なのは,何と言っても,「C言語」です。付録に示しましたが,UNIX の OS を最初に作成した人が C言語の作者であり,UNIX の OS は C言語で書かれています。ここでは,C言語によるプログラミングを見ます。
(a) ソースファイルの作成
コンパイラの場合,「ソースの作成 -> 実行ファイルの生成 (コンパイル) -> 実行」という流れでした。ここでは,ソースを作成します。
エディタを起動し,次を入力し,"hello.c
"というファイル名で保存してください。
#include <stdio.h> int main (void) { printf ("Hello World! \n"); // \n の \ は,JISキーボードの場合,円マーク ¥ です。 printf ("Message \n"); return 0; }
これで "hello.c
" という「ソース・ファイル」の完成です。
(b) コンパイル
次は,コンパイルです。
% cc -o hello.out hello.c
エラーメッセージが何もでなければ,コンパイル成功です。"hello.out
" という実行ファイルが出来上がっています。
(c) 実行
実行には,"./hello.out
" のみです。実行権をわざわざ与える必要はありません。
% ./hello.out Hello World! Message %
1. ユーザとコンピュータ
UNIX上でプログラムを作成し,それを動かす方法を見ました。ここからは,UNIX の操作自体を1つ1つ見て行きましょう。
* UNIXの操作ではなく,シェル・プログラミングを学びたい方はB Shellに,C言語を学びたい方はC言語に進んでください。
先ずは,いつかの用語を確認しましょう。
- コマンド (Command)
ユーザが行いたい処理をキーワードのような形にしたもの。人間の言葉をコンピュータに理解させるための造語。
- ターミナル (Terminal)
コマンド入力のユーザインターフェイス (Command User Interface, CUI)。端末。UNIX のサーバーに ssh 接続 (ログイン,login) 後の画面もそうです。この画面にコマンドを入力し,処理させます。
- プロセス (Process)
実行中のプログラム。
- カーネル (Kernel)
CPU,プロセス,メモリなどを管理している中枢。まさに「核」。
- シェル (Shell)
カーネルとユーザ (ターミナル) の間を繋ぐコマンド解釈装置。ユーザが行いたい処理をコマンドの形で受け取り,それをカーネルに渡し,処理結果を出力。カーネル (核) を覆う「殻」というイメージ。シェルには,シェル・プログラミングで見るように,プログラミング言語としての一面もあります。
シェルには「Bシェル (Bourne Shell)」と「Cシェル (C Shell)」があります。Bシェルは,処理の速さと書式が洗練されているため,シェル・スクリプトに向くと言われています。Cシェル (csh) は,C言語の要素を取り入れたシェルで,ユーザインターフェースに優れているようです。
ターミナルに使われているシェルは,次のようにして確認できます。
% printenv SHELL % echo $SHELL
2. ファイルシステム (File System)
2.1. ファイルの種類
UNIX では,入出力がすべて「ファイル」間で行われていると考えます。しかしながら,便宜上,次の3種類に分けるのが慣例です。
- ファイル (File)
Macintosh や Windows でいうところのファイル。
- ディレクトリ (Directory)
Macintosh や Windows でいうところのフォルダ。ディレクトリは,他のファイルを包含できる特殊なファイル。
- 標準入力,標準出力 (Standard Input, Standard Output)
通常,ターミナル (キーボード) のこと。ターミナルも一つの「ファイル」と考えるわけす (これに従えば,すべてのデバイスもファイル)。各ファイルはディレクトリも含め,固有名をもちますが,入出力に際しファイル名を指定しない場合の入出力先になります。
今後は「ファイル」といった場合,ディレクトリや標準入出力以外の「通常の」ファイルとします。
* ディレクトリやターミナルを「ファイル」と考えるのは,ユーザの側からは屁理屈のようにも感じるかもしれませんね。ただ,開発者にはそういった発想が必要です。理想・理念とその理論の探究なくして,UNIX のような素晴らしい OS は出来上がらなかったかもしれません。
2.2. ディレクトリ構造
ディレクトリの中に他のディレクトリがあるといった具合に,ディレクトリは階層構造をなしています。各ファイルやディレクトリがその階層構造のどこに位置するのか,その表現方法を見ましょう。
- ルート・ディレクトリ (Root Directory)
ディレクトリの階層構造のトップに位置するディレクトリ。ルート・ディレクトリを起点にディレクトリの階層構造は「木」のようになっています。ルート・ディレクトリは,その「木」の「根」。
- パス (Passname)
あるディレクトリ,あるいはファイルが,ディレクトリの階層構造のどの位置にあるかの表現法。その方法は2種類。
- 絶対パス (Absolute Pathname)
ルート・ディレクトリからの位置。UNIX では,スラッシュ (
/
) を用いて階層を表現する。例えば,(ルート・ディレクトリ内の) ディレクトリdir1
内のディレクトリdir2
内のファイルfile
であれば,ファイルfile
の「絶対パス」は,次の通り。/dir1/dir2/file
ルート・ディレクトリの絶対パスは,スラッシュ (
/
) のみ。 - 相対パス (Relative Pathname)
現在作業中のディレクトリからの位置。作業中のディレクトリが上出の
dir1
ならば,先ほどのファイルfile
の「相対パス」は,次の通り。dir2/file
- 絶対パス (Absolute Pathname)
2.3. 作業ディレクトリと個人用のディレクトリ
UNIX はマルチユーザ型なので,各ユーザは個別のディレクトリをもち,その中で作業することになります。
- カレント・ディレクトリ (Current Directory)
作業中のディレクトリのこと。
- ホーム・ディレクトリ (Home Directory)
ログイン (接続) したときのカレント・ディレクトリ。各ユーザは,ログインしたとき,各々別個のディレクトリに入ります。
UNIX はマルチユーザ型なので,すべてのユーザが同じディレクトリ内でファイルやディレクトリを作成し,保存してはお互いに困ってしまいます。各ユーザは,基本的には,各自のホーム・ディレクトリ内で作業するわけです。
また,各ユーザが自らのホーム・ディレクトリ内で作成したファイルの読み込み権,書き込み権,実行権は,そのホーム・ディレクトリの所有者であるそのユーザが行います。
ホーム・ディレクトリは,tilde (
~
) で表現。次のターミナル内の表記(~
部分)は,現在ホームにいるという意味です。[hostname:~] username% ('~'部分が現在ホームにいるという意味)
3. コマンドの入力形式と基本コマンドの操作
コマンドの入力は「処理方法のオプションの下,入力ファイルを読み込み,処理の結果を出力する」という形式になっています。入力ファイルについては,指定必須のコマンドとそうでないものがあります。
入力形式:command [-option] [input]
コマンドが実行されると,一つのプロセスとなります。プロセスが完了せず,いつまでたってもプロンプト (%
) が戻らない場合,無限ループに陥っている可能性があります。この場合は,'^C'
(controlキー+ C) で強制終了します。
以下では,UNIX の操作に慣れることを目的に,実験例を示しましょう。
3.1. カレント・ディレクトリの変更と確認法
UNIX を利用する上で,カレント・ディレクトリ (作業中のディレクトリ) がどこなのか,自分のホーム・ディレクトリの外で作業はしていないか,すなわち,迷子にならない方法は何か,ここではそのための練習をしてみましょう。
- 例3.1.1 (太字部分を入力後リターン)
% cd # ホーム・ディレクトリに移動 % pwd # カレント・ディレクトリの絶対パス /Users/taro # ホーム・ディレクトリは,Users の中の taro % cd / # ルート・ディレクトリに移動 % pwd # カレント・ディレクトリの絶対パス / % ls # カレント・ディレクトリのファイル一覧 Users dev sbin usr bin etc tmp var % cd Users # カレント・ディレクトリ内のディレクトリ Users へ % pwd /Users % ls hanako taro % cd taro % pwd /Users/taro
- 例3.1.2 ホーム・ディレクトリ内のファイルを確認し,その中のディレクトリ
My_Programs
へ移動% cd # ホーム・ディレクトリに移動 % ls -l drw-r--r-- 1 taro staff 3 Feb 5 18:00 My_Programs # 頭の d は,ディレクトリの意 % cd My_Programs % pwd /Users/taro/My_Programs % ls -l -rw-r--r-- 1 taro staff 63 Feb 5 18:01 hello.c # 頭が - であればファイル -rwxr-xr-x 1 taro staff 12588 Feb 5 18:02 hello.out -rwxr--r-- 1 taro staff 68 Feb 5 17:57 hello.pl -rwxr--r-- 1 taro staff 31 Feb 5 17:46 hello.sh
- 例3.1.3 ホーム・ディレクトリ内にディレクトリ「
Jobs
」を作成% cd ~ # ホームへ。例3.1.2の続きなら,cd .. でもOK。ホームへは,いつでも cd のみでも。 # ~ はホームの意。 % pwd /Users/taro/ % mkdir Jobs % ls Jobs My_Programs
- 例3.1.4 そこから「
Jobs
」へ移動し,そして「My_Programs
」に移動% cd ./Jobs # cd Jobs でもOK。. でカレントを意味し,./ でカレント内となる。 % pwd /Users/taro/Jobs % cd ../My_Programs % pwd /Users/taro/My_Programs
[ノート] ディレクトリの省略表現
上記における ~
は,以下のようなディレクトリの省略表現を利用しています。
ホーム・ディレクトリ ~ ~/ で「ホーム内の」という意味に。 カレント・ディレクトリ . ./ で「カレント・ディレクトリ内の」という意味に。 その親ディレクトリ .. ../ で「親ディレクトリ内の」という意味に。
3.2. ファイル/ディレクトリのコピー
- 例3.2.1 ファイル「
hello.sh
」をコピー% pwd # カレント・ディレクトリの確認。前の例の続き。 /Users/taro/My_Programs % cp hello.sh benchmark.sh % ls -l # C.f. 例3.1.2 -rwxr--r-- 1 taro staff 31 Feb 21 18:05 benchmark.sh -rw-r--r-- 1 taro staff 63 Feb 5 18:01 hello.c -rwxr-xr-x 1 taro staff 12588 Feb 5 18:02 hello.out -rwxr--r-- 1 taro staff 68 Feb 5 17:57 hello.pl -rwxr--r-- 1 taro staff 31 Feb 5 17:46 hello.sh % cat hello.sh # hello.sh の中身を確認 #!/bin/sh echo "Hello World!" % cat benchmark.sh # benchmark.sh の中身を確認 #!/bin/sh echo "Hello World!" % diff hello.sh benchmark.sh # diff は2つのファイルの差を検査。 # man diff でマニュアルが参照可能。 % # ファイルの中身に差がないので, # メッセージなしでプロンプトが戻る。
- 例3.2.2 それを「
Jobs
」内にコピー% pwd # カレントの確認。前の例の続き。 /Users/taro/My_Programs % cp benchmark.sh ../Jobs % cd ../Jobs % ls -l -rwxr--r-- 1 taro staff 68 Feb 21 18:06 benchmark.sh
3.3. ファイル/ディレクトリの移動
- 例3.3.1 「
My_Programs
」内の「hello.sh
」を「Jobs
」内へ移動% pwd # 前の例の続き。 /Users/taro/Jobs/My_Programs % mv hello.sh ~/Jobs # ~/Jobs は .. では駄目。../Jobs はOK。 % ls -l -rw-r--r-- 1 taro staff 63 Feb 5 18:01 hello.c -rwxr-xr-x 1 taro staff 12588 Feb 5 18:02 hello.out -rwxr--r-- 1 taro staff 68 Feb 5 17:57 hello.pl -rwxr--r-- 1 taro staff 31 Feb 5 17:46 hello.sh % cd .. % ls -l -rwxr--r-- 1 taro staff 31 Feb 21 18:05 benchmark.sh -rwxr--r-- 1 taro staff 31 Feb 5 17:46 hello.sh
- 例3.3.2 「
Jobs
」を「My_Programs
」内へ移動% cd ../My_Programs # 前の例の続き。 % mv ../Jobs . % ls -l drwxr-xr-x 4 taro staff 126 Feb 21 17:28 Jobs -rwxr--r-- 1 taro staff 31 Feb 21 18:05 benchmark.sh -rw-r--r-- 1 taro staff 63 Feb 5 18:01 hello.c -rwxr-xr-x 1 taro staff 12588 Feb 5 18:02 hello.out -rwxr--r-- 1 taro staff 68 Feb 5 17:57 hello.pl
3.4. ファイル/ディレクトリのリネーム (名称変更)
- 例3.4.1 「
benchmark.sh
」を「hello.sh
」に名称変更% pwd # 前の例の続き。 /Users/taro/My_Programs % mv benchmark.sh hello.sh % ls -l drwxr-xr-x 4 taro staff 126 Feb 21 17:28 Jobs -rw-r--r-- 1 taro staff 63 Feb 5 18:01 hello.c -rwxr-xr-x 1 taro staff 12588 Feb 5 18:02 hello.out -rwxr--r-- 1 taro staff 68 Feb 5 17:57 hello.pl -rwxr--r-- 1 taro staff 31 Feb 21 18:05 hello.sh
- 例3.4.2 「
Jobs
」を「Temp
」に名称変更% pwd # 前の例の続き。 /Users/taro/My_Programs % mv Jobs Temp % ls -l drwxr-xr-x 4 taro staff 126 Feb 21 17:28 Temp -rw-r--r-- 1 taro staff 63 Feb 5 18:01 hello.c -rwxr-xr-x 1 taro staff 12588 Feb 5 18:02 hello.out -rwxr--r-- 1 taro staff 68 Feb 5 17:57 hello.pl -rwxr--r-- 1 taro staff 31 Feb 21 18:05 hello.sh
3.5. ファイル/ディレクトリの削除
- 例3.5.1 「
Temp
」内の「hello.sh
」を削除% cd Temp # 前の例の続き。 % ls -l -rwxr--r-- 1 taro staff 31 Feb 31 18:05 benchmark.sh -rwxr--r-- 1 taro staff 31 Feb 5 17:46 hello.sh % rm hello.sh % ls -l -rwxr--r-- 1 taro staff 31 Feb 31 18:05 benchmark.sh
- 例3.5.2 空のディレクトリを削除
% mkdir Jobs # 空ディレクトリを作成 % ls -l drwxr-xr-x 1 taro staff 14 Feb 21 18:15 Jobs -rwxr--r-- 1 taro staff 56 Feb 31 18:05 benchmark.sh % rmdir Jobs % ls -l -rwxr--r-- 1 taro staff 56 Feb 31 18:05 benchmark.sh
- 例3.5.3 空ではないディレクトリ「
Temp
」を削除% cd .. # 前の例の続き。 % rm -r Temp % ls -l -rw-r--r-- 1 taro staff 63 Feb 5 18:01 hello.c -rwxr-xr-x 1 taro staff 12588 Feb 5 18:02 hello.out -rwxr--r-- 1 taro staff 68 Feb 5 17:57 hello.pl -rwxr--r-- 1 taro staff 31 Feb 21 18:05 hello.sh *これで最初の状態に戻る。
4. 正規表現 (Regular Expression)
ディレクトリ「My_Programs
」に移動し,コマンド echo *
を実行してみよう。
% cd ~/My_Programs % echo * hello.c hello.out hello.pl hello.sh %
コマンド echo *
が,カレント・ディレクトリ (My_Programs
) のファイル一覧を表示することが分かります。実は,シェルは,カレント・ディレクトリ内のファイル一覧を読み込み,標準入力された文字 *
と照合し,合致したファイル名を標準出力へ出力しています。このような文字の検索とその置換のための表現を「正規表現」(Regular Expression) といいます。
(i) a*:a から始まる文字列すべて。
- 例4.1:
h
から始まるファイル% cp hello.sh sample.sh % echo * hello.c hello.out hello.pl hello.sh sample.sh % echo h* hello.c hello.out hello.pl hello.sh
(ii) *a:a で終わる文字列すべて。
- 例4.2
% echo *h hello.sh sample.sh
- 例4.3
p
を間にもつファイル% echo *p* hello.pl sample.sh
(iii) ?:その位置に任意の文字で検索。
- 例4.4
% echo he?lo.pl hello.pl
- 例4.5
% echo hello??? hello.pl hello.sh
(iv) [abc], [a-z], [A-Z], [0-9],...:その位置に
[ ]
内の文字で検索。
- 例4.6:
a-n
で終わるファイル% echo *[a-n] hello.c hello.pl hello.sh sample.sh
(iv) [^abc], [^a-z], [^A-Z], [^0-9],...:その位置に
^
以降以外の文字を検索。
- 例4.7:
h
以外で始まるファイル% echo [^h]* sample.sh
5. 入出力とそのリダイレクト (I/0 & I/O Redirection)
5.1. 「リダイレクト」とは?
UNIX では,入出力 (Input/Output, I/O) がすべてファイル間で行われているということでした (第2項参照)。上記で列挙したコマンドも,入力ファイルや出力ファイルを指定しなければ,すべて,標準入出力,すなわち,ターミナルからの入出力となります。UNIX では,入力ファイルや出力ファイルを標準以外に切り替える (redirect) ことができ,これを「入出力のリダイレクト」(I/0 Redirection) といいます。
5.2. 入出力ファイルのリダイレクト
出力ファイルのリダイレクト (上書き):>
出力ファイルのリダイレクト (加える):>>
入力ファイルのリダイレクト (ファイル全体):<
入力ファイルのリダイレクト (ストップ・ワードまで標準入力:「ヒア・ドキュメント」):<<
- 例5.2.1:出力のリダイレクト (
>
)新しいファイル「
message.txt
」に "Hello Hanako!
" と書き入れる。(message.txt
は,出力のリダイレクト>
の使用で自動で作成される。)% cd # ホームへ % mkdir Mail # 新しいディレクトリ「Mail」を作成 % cd Mail # そこへ移動 % echo "Hello Hanako!" > message.txt % cat message.txt # message.txt の中身を見る Hello Hanako! %
- 例5.2.2:出力のリダイレクト (
>>
)それに "
How are you?
" と書き加える。% echo "How are you?" >> message.txt % cat message.txt Hello Hanako! How are you? %
- 例5.2.3:入出力のリダイレクト(
<<, >>
)さらに文章を書き加える。(下記の場合,ストップワードは「
EOF
」。これが入力されるまで,cat
の入力へリダイレクトされる。)% cat << EOF >> message.txt -> I'm working on Unix. -> I'm gonna move on to B-Shell Programming. -> Here's mannual of sh. -> EOF % cat message.txt Hello Hanako! How are you? I'm working on Unix. I'm gonna move on to B-Shell Programming. Here's mannual of sh. %
- 例5.2.4:出力のリダイレクト (
>
)コマンド
sh
のマニュアルをファイル「man_sh.txt
」へ書き込む。% man sh > man_sh.txt man: Formatting manual page... %
- 例5.2.5:出力のリダイレクト (
>>
)それをファイル「
message.txt
」に書き加える。% cat man_sh.txt >> message.txt
- 例5.2.6:入力のリダイレクト (
<
)hanako
にタイトル "man sh
" でファイル「message.txt
」の中身すべてをメイル% mail -s 'man sh' hanako < message.txt
- 例5.2.7:入出力のリダイレクト (
<, >
)ファイル「
man_sh.txt
」内の文字「redirection
」すべてを文字「REDIRECTION
」に変換し,それをファイル「man_sh_REDIRECT.txt
」へ出力。% sed 's/redirection/REDIRECTION/g' < man_sh.txt > man_sh_REDIRECT.txt
5.3. パイプ (Pipes)
Thompson と Ritchie が UNIX を開発した直後から,コマンドの出力を他のコマンドに渡すことを考え,数年後に実現することになります。コマンド command1
の出力をコマンド command2
の入力へ切り替えることを「パイプで繋ぐ」(piping) といいます。UNIX の特徴的な操作ともいえるでしょう。
% command1 | command2
パイピングは何回でも可能。
% command1 | command2 | command3 | command4
また,I/O リダイレクトとパイピングを併用することも可能。
% command1 | command2 > file
- 例5.3.1
コマンド
ls -l
は,多数のファイルがある場合,ターミナルの一画面に収まりません。そこで,その出力をコマンドmore
の入力に切り替え,ファイルリストの一つ目から確認できるようにしてみます。% ls -l | more
- 例5.3.2
ログインしている人数 (ログインしている人数が少なければ,数えた方が速いが...)
% who | wc -l
- 例5.3.3
コマンド
sh
のマニュアルの中で「redirection
」または「Redirection
」と書いてある部分の前後5行を抜き出してみます。% man sh | grep -5 -e "redirection" -e "Redirection"
5.4. 標準エラー出力とそのリダイレクト
■標準エラー出力 (Standard Error Output)
コマンドは,その処理にエラーがあれば,エラー・メッセージを出力します。
% cd ~/Mail % ls man_sh.txt man_sh_REDIRECT.txt message.txt % cat xxx > temp.txt cat: xxx: No such file or directory %
この場合,ファイル xxx
が存在しないため,コマンド cat xxx
に対し "cat: xxx: No such file or directory
" というエラーが出力された訳です。
ここで注意したいのは,上記の例から分かるように,出力のリダイレクト (>
) を使っても,エラーメッセージ "cat: xxx: No such file or directory
" は,ファイル temp.txt
へ出力されず,そのまま標準出力(ターミナル)へ出力されていることです。すなわち,エラーは標準出力として出力されるのであり,更に,それは,パイピングを含め I/O Redirection の対象とはなっていないのです。このように,エラー出力は,通常の出力とは区別され,別途の出力対象として標準出力となっており,これを「標準エラー出力」(Standard Error Output) といいます。
それでも,標準エラー出力をファイルへ出力したい場合があるかもしれません。その方法が「標準エラー出力のリダイレクト」です。
■標準エラー出力のリダイレクト
% command >& file
- 例5.4.1:エラーを「ゴミ箱」に出力
% cat xxx >& /dev/null % 注) Macintosh や Windows と異なり,/dev/null へ出力されたものは, 消えて無くなります。「ゴミ箱」を空にする必要はありません。
6. ファイル管理
6.1. アクセス権とその確認法
UNIX では,各ファイルに対し「所有者」があり,その所有者が所有するファイルのアクセス権を設定します。各ユーザは,管理者グループ,WWW グループなど,必ず何かしらの「グループ」に所属しています。
■ファイルの所有者からみたユーザの区分
・u
:所有者 (user)
・g
:その所有者が属すグループ(group)
・o
:その他 (others)
ファイルに対するアクセスは,読み込み権,書き込み権,実行権があります。
■アクセスの区分
・r
:読み込み可 (readable)
・w
:書き込み可 (writable)
・x
:実行可 (executable)
したがって,各ファイルに対し「所有者 (u
)」「グループ (g
)」「その他 (o
)」の3つにユーザを区分し,各々の区分に対し読み込み権 (r
),書き込み権 (w
),実行権 (x
) を所有者が指定することになります。
以下の表における taro
はそのファイルの所有者 (u
),staff
はユーザ名 taro
が属すグループ (g
) です。
% ls -l drwxr-xr-x 1 taro staff 14 Feb 21 18:15 Jobs lrwxr-xr-x 1 taro staff 14 Feb 21 18:08 My_Programs -> ../My_Programs -rwxr--r-- 1 taro staff 56 Feb 21 18:05 benchmark.sh %
■drwxr-xr-x
部分の読み方
・1桁目:ファイルの種類
d:ディレクトリ
l:"->" 以下をオリジナルファイルにもつ「シンボリックリンク」 (6.3 を参照)
-:ファイル
・残り9桁
3分割して見る。
最初の3つ:所有者 (u
) のアクセス権
次の3つ:グループ (g
) のアクセス権
残り3つ:他の人 (o
) のアクセス権
- 例)
benchmark.sh
の場合所有者 (
u
) が読み込み (r
),書き込み (w
),実行 (x
) 可で,グループstaff
に属すユーザ (g
) と他のユーザ (o
) は読み込み (r
) のみ可能なファイル。
6.2. アクセス権の変更
ファイルのアクセス権の変更は,その所有者のみ可能です。その方法は次の通り。
■アクセス権の変更法
chmod [who][+/-][permission] file
[凡例]
who
u:ユーザ(所有者),g:グループ,o:その他
+/-
+:権限を与える,-:権限を奪う
permission
r:読み込み,w:書き込み,x:実行
- 例6.2.1:グループに読み込み権を与える
% chmod g+r hello.sh
- 例6.2.2:グループとその他から書き込み権を奪う
% chmod go-w hello.sh
- 例6.2.3:所有者のみに実行権を与える
% chmod u+x hello.sh
- 例6.2.4:すべてに実行権を与える
% chmod +x hello.sh % chmod a+x hello.sh
[ノート]アクセス権については,数字による指定のみしか受け付けない環境がある。次がその対応表になる。
r w x
4 2 1
例えば,rwxr--r--
であれば,u に 4+2+1=7,g に 4+0+0,o に 4+0+0 と計算して,次のようにアクセス権を与える。
chmod 744 ファイル名
6.3. ファイル/ディレクトリへのリンク:「シンボリック・リンク (Symbolic Link)」
シンボリック・リンクは,Macintosh でいうところの「エイリアス」,Windows でいうところの「ショートカット」に相当します。但し,UNIX で「エイリアス」といった場合,コマンドへのリンクをいい,「シンボリック・リンク」はあくまでもファイルやディレクトリをオリジナルとします (「エイリアス」については下記第7項を参照)。
シンボリック・リンクへのアクセス権は,オリジナルのアクセス権に従います。したがって,シンボリック・リンクのアクセス権を読み込み,書き込み,実行禁止にしても,オリジナルがそうでなければ読み書き,あるいは実行できます。
■シンボリック・リンクの作成
ファイル/ディレクトリ original にリンク名 symlink でリンク
% ln -s original symlink
- 例6.3.1:カレント・ディレクトリ内に,ホーム・ディレクトリ内のディレクトリ「
Mail
」のシンボリック・リンクを作成。% cd ~/My_Programs % ln -s ~/Mail lrwxr-xr-x 1 taro staff 19 Feb 24 03:35 Mail -> /Users/taro/Mail -rw-r--r-- 1 taro staff 94 Feb 5 18:01 hello.c -rwxr-xr-x 1 taro staff 9544 Feb 5 18:02 hello.out -rwxr--r-- 1 taro staff 68 Feb 5 17:57 hello.pl -rwxr--r-- 1 taro staff 56 Feb 21 18:05 hello.sh
[ノート] これは以下と同じ。
% ln -s ~/Mail .
.
や~
については,3 の「[ノート] ディレクトリの省略表現」を参照。また,リンク名を省略すれば,シンボリック・リンクの名称は,オリジナルと同じ。
■シンボリック・リンクの削除
% rm symlink
- 例6.3.2:前の例のシンボリック・リンク「
Mail
」を削除。% rm Mail % ls -l -rw-r--r-- 1 taro staff 94 Feb 5 18:01 hello.c -rwxr-xr-x 1 taro staff 9544 Feb 5 18:02 hello.out -rwxr--r-- 1 taro staff 68 Feb 5 17:57 hello.pl -rwxr--r-- 1 taro staff 56 Feb 21 18:05 hello.sh
7. コマンドの省略:「エイリアス」
コマンドもオプションやパイプ/リダイレクトなどを利用すれば,UNIX が今でもターミナルを操作画面に利用することが理解できよう。かなり作業が大掛かりになれば,シェル・スクリプトを書いた方が良いが,左程でもないがそれでも打ち込む量が多く,しかも,それをしばしば利用するのであれば,簡単な単語の入力で実行できる方が便利です。それが「エイリアス」です。
■コマンド command のエイリアス alias を作成
% alias alias "command" (tcsh)
$ alias alias="command" (bash)
- 例7.1:
./hello.out をファイル "output.txt" に書き出す作業のエイリアス
% alias hello "./hello.out > output.txt" % hello % cat output.txt Hello World! Message %
■エイリアス alias の削除
% unalias alias
- 例7.2:
エイリアス "hello" の削除
% unalias hello % hello hello: Command not found. %
■エイリアスの一覧を表示
% alias
次のファイルをホームディレクトリ内 ~/
に作成すれば,エイリアスをログイン時に読み込むことができます。
・ログインシェルが tcsh の場合:ファイル名 .tcshrc
- 例7.3:
.tcshrc
の作成% cd % echo "alias l 'ls -la'" > .tcshrc % cat .tcshrc alias l 'ls -la'
・ログインシェルが bash の場合:ファイル名 .profile
- 例7.4:
.profile
の作成$ cd $ echo "alias l='ls -la'" > .profile $ cat .profile alias l='ls -la' $ hexdump -c .profile 0000000 a l i a s l = ' l s - l a ' 0000010 \n $ hexdump -C .profile 00000000 61 6c 69 61 73 20 6c 3d 27 6c 73 20 2d 6c 61 27 |alias.l='ls -la'| 00000010 0a |.|
*
\n
は改行。C言語「付録 文字定数」参照。また,hexdump -C
の数値は,ASCIIコード(16進数)。
8. コマンドのパスと登録:~/bin
と rehash
8.1. コマンドのパス
コマンド command
がサーバーに備わっているか否かは,次のようにして確認できます。
■コマンドの絶対パス % which command
- 例8.1
% which ls /usr/bin/ls % which sh /bin/sh
この例から分かるように,コマンドは,/usr/bin
とか /bin
内にあります。実際,/bin
内の実行可能ファイルがシェル・コマンドです。
これに対し,自らが使用可能なコマンドがどこのディレクトリなのか,調べることもできます。
■コマンドのパス一覧 % echo $PATH
- 例8.2
% echo $PATH /bin:/sbin:/usr/bin:/usr/sbin
これは,コロン :
で区切って見ます。先ほどの ls
の絶対パスが /usr/bin/ls
でしたが,それは,ここでいうと3つ目の /usr/bin
内にあるコマンドです。
8.2. パス(PATH)の通し方
echo $PATH
にないパス path
にパスを通すには,次のファイルをホームディレクトリ ~/
内に作成しておけば,次のログインからは path
にパスが通ります。
・ログインシェルが tcsh の場合
:ファイル名 .tcshrc
setenv PATH ${PATH}:path
・ログインシェルが
bash
の場合:ファイル名 .profile
PATH=$PATH:path
- 例8.3:ログインシェルが
tcsh
のとき,自らのホームディレクトリ内のディレクトリbin
にパスを通す場合% echo $SHELL /bin/tcsh % cd % mkdir bin % echo $PATH /bin:/sbin:/usr/bin:/usr/sbin % echo "setenv PATH ${PATH}:$HOME/bin" >> .tcshrc
[ノート]$SHELL
や $PATH
,$HOME
の SHELL
,PATH
,HOME
を「環境変数」という。環境変数一覧の出し方は次の通り。
% printenv HOME=/Users/taro # ホームディレクトリ SHELL=/bin/tcsh # ログインシェル USER=taro # ユーザ名 PATH=/bin:/sbin:/usr/bin:/usr/sbin:/Users/taro/bin # パス ...
8.3. コマンドの登録
7 で見たエイリアスは,コマンドの省略であり,コマンドが本来存在するディレクトリにある訳ではありません。サーバーによっては,再起動するとエイリアスが消えたりします。したがって,シェル・スクリプトや C,Perl などで作成したプログラムをコマンドとして登録したいものです。ところが,/usr/bin
や /bin
は,root
が所有者であり,サーバーを利用するすべての人が使用するコマンドが格納されています。そこで,必要となるのが,各ユーザが個別に設定するコマンドです。
例8.3で自らのホーム・ディレクトリ内のディレクトリ ~/bin
にパスを通しました。そこで,~/bin
内に収めた実行可能ファイルをコマンドとして登録してみましょう。
■コマンドの登録方法 (コマンドのパスが,~/bin
に通っている場合)
実行ファイル executable をコマンド command として登録
% cd
% cp executable bin/command
% chmod u+x bin/command
% rehash
上記のコマンドの中で,最後の rehash
以外は既出。3行目は,実行ファイル executable
を自分のホーム内のディレクトリ bin
にコピー。但し,コピーの名称は command
。最後の rehash
は,新しく作成したコマンドを認識させるためのものです。
- 例8.4:シェルのプログラム・ファイル hello.sh を
hello
というコマンドとして登録% cd % cp My_Programs/hello.sh bin/hello % chmod u+x bin/hello % rehash 実行) % hello Hello World! %
[ノート] #!/bin/sh
の意味
シェル・スクリプトの先頭には,「#!/bin/sh
」を入れます。この一行をはずして,上記のようにコマンドとしてシェル・スクリプトを登録すると,どうなるのでしょうか?実は,動かないのです。その一行が,シェル(実行ファイル /bin/sh
)での実行を知らせています。
実行ファイルをコピーする上記の方法では,元の実行ファイルを編集すれば,再びコピーしないと,編集の効果はコマンドにいかされません。そこで,コピーではなく,シンボリック・リンクを使うと良いかもしれません。
■シンボリック・リンクでコマンドを登録 % cd % ln -s executable bin/command % chmod u+x executable % rehash
- 例8.5:例3のコマンドの登録をシンボリック・リンクで行う場合
% cd % ln -s My_Programs/hello.sh bin/hello % chmod u+x My_Programs/hello.sh % rehash 実行) % hello Hello World! %
付録:UNIX Hierarchy と歴史
UNIX Hierarchy
下記は,UNIX Hierarchy の中で,本サイトで学べる部分のみを抜粋。
[ノート]参考程度にしてください。あくまでも UNIX Hierarchy の部分訳です。
- 初心者(Beginner)
- ターミナルの概念に確信が持てない。
- ディレクトリの移動の仕方を説明できない。
- 入力後,リターンキーを打つのに手間どる。
- 入門者(Novice)
ls
が使える。- C言語のことを耳にしたことはあるが,使ったことはない。
rm
で初めて失敗する。
- 利用者(User)
- 正規表現のことを聞いたことはあるが,見たことはない。
- オプションに
-
が付くことを知っている。 - ディレクトリの削除ができない。
- 利き手,腕利き(Knowledgeable User)
mv
が使える。sed
を一度は使った。- C のプログラミングの仕方を学んだ。
make
は意気地なしのためにあると思っている。
- 専門家(Expert)
- 必要なときに
sed
を使う。 &&
と||
の意味が分かる。- C のプログラムを
vi
で書き,cc
でコンパイルする。
- 必要なときに
- ハッカー(Hacker)
- 環境変数について説明できる。
- Bourne Shell(Bシェル)のスクリプトを書く。
- C のプログラムを
cat >
で書き,cc
でないものでコンパイルする。
- グル(Guru)
- アセンブリ・コードを
cat >
で書く。 - パッチをあてカスタマイズする。
- UNIXのことなら,ほとんど直ぐさま答えられる。
make
を複数のコマンドアーカイブとして使う。
- アセンブリ・コードを
- ウィザード(Wizard)
- バイナリのパッチをあて,バグを修正する。
- Dennis,Bill,Ken とファーストネームで呼び合える。(ちなみに,Bill とは,ビル・ゲイツのことではありません。)
「UNIX」の由来とその始まり
「UNIX」とは?
「UNIX とは,X/Open Company の登録商標で "Uniplexed Information and Computing System" の略である。」
という説明が登録商標の観点からは必要であるが,下の「その始まり」でも述べるように,"Multics" を皮肉った造語であって,元来は略語ではない。現在,UNIX と言った場合,それは UNIX系 OS 全般を指す言葉として使われており,大きくは,BSD系と System V系に分けられる。前者は,FreeBSD,OpenBSD,NetBSD,Solaris,Darwin(Mac OS X)等が該当する。(図による詳細な系譜については UNIX History を。)
UNIX のソースは,C言語で書かれており,公開されている。
UNIX は,マルチタスク,マルチユーザ型の OS。
その始まり
1965 | MIT (Massachusetts Institute of Technology),GE,AT&Tベル研究所がマルチタスク,マルチユーザ,仮想メモリを実現したOS,「Multics」を共同開発。しかし,開発しても経済的な OS にはなかなかならず,AT&Tベル研究所 (現ベル研究所) は1969年に撤退(ベル研究所, 2000)。 |
1969 | AT&Tベル研究所の Ken Thompson が1969年,Multics 上のゲーム "Space Travel" を開発,それを GE の OS (GECOS) 用の Fortran に翻訳。このゲームは,太陽系の中を宇宙船を操作し,惑星に着陸させるようなものであったという。ところが,計算に75ドルもかかることがわかり,Dennis Ritchie と Thompson は,がらくた同然の(little-used) コンピュータ,PDP-7でこのゲームが走るようにしたという。このときに UNIX が生まれるのである。Ritchie (1993) によると,PDP-7は 8K 18-bit words of memory の機械であったという。二人の共同研究者だった Brian Kernighan が,撤退した「Multics=Multi+cs」を皮肉って「UNIX=Uni+cs」と名付けるよう示唆した(Ritchie, 1980)。 |
1971-74 | 1971年,Thompson が B言語を作る。Ritchie がそれから "New B",そして,C言語へ(Cの完成は1973年頃)。Thompson と Ritchie が,その C言語で UNIX のソースを書く。ハードウェアに依存しない,移植性のある世界初のOSが誕生することとなる。 |
1976-77 | Thompson が母校の UC Berkeley で1年間講義。このときの院生に Bill Joy がいる。Bill Joy は,79年に修士号を取り,Thompson が去った後,BSD (Berkeley Software Distributions) のメイン・デザイナーとなる(McCormick, 1997 参照。ちなみに,Bill Joy は,Sun Microsystems の共同設立者であり,エディター vi の作者)。 |
1983 | AT&T側が1月に System V を発表し本格的に商用版に乗り出し,UC Berkeley が9月に 4.2BSD を発表。4.2BSD は,仮想メモリや TCP/IP を内臓するなど,現在の UNIX のプロトタイプ。 |
Dennis Ritchie (standing) and Ken Thompson begin porting UNIX
to the PDP-11 via two Teletype 33 terminals. (Source: Bell Labs.)
参考文献
Bell Labs (2000), "The Creation of the UNIX* Operating System," mimeo.
Ritchie, Dennis M. (1980), "The Evolution of the UNIX Time-Sharing System," Lecture Notes in Computer Science #79: Language Design and Programming Methodology, Springer-Verlag, reprinted as AT&T Bell Laboratories Technical Journal 63 No. 6 Part 2, October 1984, pp. 1577-93.
Ritchie, Dennis M. (1993), "The Development of the C Language", mimeo.
McCormick, Gavin (1997), "The Berkeley Link," mimeo.