ここで学ぶのはシェルについてです.
レクチャーで学んだとおり,
 シェルは人間と計算機の仲介をするソフトウェアで, 
我々はこのソフトウェアを介して計算機に対して作業を要求することになります.
実習では, 皆さんがメインで使うことになるシェル「bash」の使い方や機能について
実際に使いながら学んでいきます. 
2 章のセクションは2-1 から2-3 (2-4 は付録, 時間があればやってください.) まであります. 全員が同じことをやる時間はないので, 各セクションが終わったら交代しながら実技を進めましょう. 時間に余裕がある場合は全員がやってもかまいません.  
  まずは自分が今どのシェルを使っているかを確認してみましょう. 
  方法は様々ですが, ここでは echo コマンドを用います. 
  ここで表示された /bin/bash というのがそのユーザのログインシェルになります. 
  正確には, シェルというソフトウェアもファイルとして扱われているため, ここに書かれているのはそのファイルのパスになります.
ログインシェルとは?
  ユーザがログインした際に自動的に起動されるシェルです. 
  とくに設定を変えない限り, デフォルトではこのログインシェルがシェルとして起動されます. 
  chsh コマンドを用いて変更することもできます. 
  一口にシェルと言っても, その設計思想や開発時期によって各シェルには多くの相違点があります. 
  その中で bash は, ユーザが計算機とやりとりをする上で便利になるように各種の機能を備えています. 
  ここでは, それらの機能を学んでいきましょう. 
[2-2-1] ファイル, コマンド名の補完機能
    bash には, 途中まで打ち込まれた内容を元に, ファイルやコマンドを補完する機能が備わっています. 
    具体的には, 目的の文字列を何文字か入力し, Tab キーを押します. 
    複数候補が存在する場合は, Tab キーを2回押すことで, その一覧を表示させることが出来ます. 
    この機能は他にも, シェル変数, ユーザー名, ホスト名なども補完してくれます. 
| 
$ ls /[Tab][Tab]
bin          etc          lost+found  proc         srv     var
boot         home         media       root         sys     vmlinuz
cdrom        initrd.img   mnt         sbin         tmp
dev          lib          opt         selinux      usr     
$ ls /h[Tab]
$ ls /home/
 | 
<-- [Tab] は Tab キーを表します. ここでは二回叩きましょう. 
--> 「/」以下のファイルは複数あるので候補リストが表示されます
--> /h で始まるディレクトリは /home しかないため, 
    [Tab]を一回押すだけで「/home/」が補完されます
 | 
[2-2-2] ヒストリ機能
  bash には便利なヒストリ(入力履歴)機能が存在します.
  この機能によって以前に入力したコマンドを簡単に呼び出すことができます.
| 
$ cat .bashrc
# ~/.bashrc: executed by bash(1) for non-login shells.
---------
中略
---------
# sources /etc/bash.bashrc).
if [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
fi
$ [↑]
$ cat .bashrc
 | 
<-- .bashrc (bash の設定ファイル)を見る
--> .bashrc ファイルの内容が表示される
<-- [↑], または Ctrl-p を押すと以前に入力したコマンドを呼び出すことができる.
 | 
 history コマンド 
  [↑]キーを用いると直前に入力したコマンドから遡るように履歴を追うことができますが, history コマンドを用いると今までに入力したコマンドが一覧表示されます.
  これらの情報は ~/.bash_history に格納されています.
例)
| 
$ history
   33  cd etc/
   34  ls
---------
中略
---------
  509  cat .bashrc
  510  history 
 | 
<-- history コマンドを入力
--> 過去にそのアカウントで入力したコマンドの履歴が表示される
 | 
  各コマンドの横に表示されるのは履歴番号で, 以下のように入力すると該当するコマンドを呼び出すことができます.
例)
| 
$ !509
cat .bashrc
# ~/.bashrc: executed by bash(1) for non-login shells.
---------
以下略
---------
 | 
<-- 履歴番号509のコマンドを呼び出す
--> cat .bashrc と解釈される
 | 
[2-2-3] メタキャラクタ(ワイルドカード)
  コマンド入力の際に, 複数のファイル名を「ある規則にしたがってまとめて表す」ために用いられる文字のことを "メタキャラクタ"(ワイルドカード)と言います. 
  メタキャラクタを用いるとタイプする文字数を減らすことができるので, 効率的に入力が行えます. 
  代表的なメタキャラクタ
  
    | メタキャラクタ | 意味 | 
  
    | * | 任意の文字列を表す. | 
  
    | ? | 任意の1文字を表す. ?? は任意の2文字になる. | 
  
    | [ ] | [ ] 内に含まれる文字にマッチする. 
      例えば [a-c]* は abc のいずれかで始まる任意の文字列を表す. | 
  
    | { } | { }内に含まれる文字列にマッチする.
      例えば test.{pl,gif,f} は, test.pl test.gif test.f と入力したことになる. | 
  例えば以下のような使い方ができます. 
| 
$ mkdir work/
$ cp *.txt work/
$ rm *.txt
 | 
<-- カレントディレクトリ内で末尾が .txt という
    ファイルを work 以下にコピーする. 
<-- カレントディレクトリ内で末尾が .txt という
    ファイルを消去する. 
 | 
  ただし, いくら便利だからといって以下のようなコマンドを実行する時には十分に注意しましょう. 
  今は昔, 以下のコマンドで卒論の原稿を半分消してしまった人がいます!
  Linux では基本的に, 一度削除したファイルは二度と復元できません(Windows の「ゴミ箱」のようなものが存在しない). 
[2-2-4] リダイレクション
  リダイレクションとは入力元や出力先を変更できる機能です.
  通常,cat, echo, date などのコマンドを入力すると, 結果が表示されます.
  これらの結果をファイルに書き込みたい場合はリダイレクション機能を使います.
| 
$ echo "hello world"
hello world
$ echo "hello world" > hello.txt
$ cat hello.txt
hello world
$ cat hello.txt > world.txt
$ cat world.txt
hello world
$ date >> world.txt
$ cat hello.txt >> world.txt
$ cat world.txt
hello world
Mon Apr 18 13:52:46 JST 2016
hello world
 | 
<-- 「>」が echo "hello world"
    の結果を hello.txt に書き込む.
<-- hello.txt の中身を表示させる
--> 表示
<-- 次にhello.txtの中身をworld.txtにリダイレクト
<-- world.txt の中身を表示させる
--> 表示
<-- 「>>」を使うと上書きされずに下の行に追加される.
<-- world.txt の中身を表示させる
--> 表示
 | 
[2-2-5] パイプ
  
    上記のリダイレクションでは表示される結果をファイルに書き出しました.
    これに対し, パイプ「|」を使用すると結果をコマンドに送ることができます.
  
  | 
$ ls -la /dev 
           :
$ ls -la /dev | less
           :
$ ls -la /dev | grep "sda" | less
 | 
<-- /dev 以下のファイルを表示
--> 大量の情報が表示される
<-- パイプ「|」で結果をコマンド「less」に送る
--> 結果を less で見ることができる. q で終了.
<-- パイプを連続で使うことで複数のコマンドを連結して使うこともできる.
    (「grep」コマンドで "sda" という文字列を含む行のみを抽出し, 結果を less で見る)
 | 
[2-2-6] シェル変数
  
  bashは, シェル自身の動作を定義する変数を持っています. 
  この, シェルが内部で保持している変数を, "シェル変数"と言います. 
  シェルスクリプトや, コマンドの入力の際に, 
  値を一時的に格納して後で再利用できるようにするための変数でもあります. 
  後述の環境変数と違い, シェル以外のプログラムからは参照できません. 
  
  
  基本的に, 変数名をつける際は, 好きなようにつけて構わないのですが, 
  環境変数やすでに定義されているシェル変数とは重ならないように指定した方が無難です. 
  
  
    - 現在設定されているシェル変数を見るには, set と打ち込みます. 
    
- シェル変数の設定と変更は, "="を使います. (シェル変数名=シェル変数の値)
    
- シェル変数の値を調べるには, echo $変数名 と打ち込みます. 
    
- シェル変数の削除は, unset コマンドを使います. (unset シェル変数名)
  
シェル変数に値を代入して, そのシェル変数を表示させて見ましょう.
| 
$ set
略
$ var='Hello?'
$ echo $var
Hello?
$ set |grep "var='Hello?'"
var='Hello?'
$ unset var
$ echo $var
 | 
<-- シェル変数の一覧表示
<-- シェル変数 var に Hello! を代入
<-- シェル変数 var を表示
--> シェル変数 var 内の値が表示されます
<-- シェル変数一覧の中のvar を検索して表示
<-- シェル変数 var を削除
--> なにも表示されません
 | 
  
  もう一つの例として, プロンプトの表示を変えてみましょう.
  プロンプトの表示は, シェル変数"PS1"を用いて設定することが出来ます
  (\ マークはバックスラッシュに読み替えて下さい). 
  
| 
$ PS1="\u% "
user%
user% PS1="\d$ "
Fri May 7$
Fri May 7$ PS1="\s-\v\$ "
bash-3.2$ 
bash-3.2$ PS1="\u@\h:\w\$ "
user@joho:~$ 
 | 
<-- プロンプト表示を"ユーザ名%"にする
    (詳細は以下の表を参照)
--> userは自分のユーザ名
<-- プロンプト表示を"日付%"にする
<-- プロンプト表示を"シェルの名前-バージョン"にする
<-- プロンプト表示を"ユーザ名@ホスト名:作業ディレクトリ"にする
 | 
  プロンプト表示の特殊文字
  
    | 特殊文字 | 意味 | 
  
    | \d | 日付 | 
  
    | \H | ホスト名 | 
  
    | \h | 最初の"."までのホスト名 | 
  
    | \n | 改行 | 
  
    | \s | シェルの名前 | 
  
    | \u | 現在のユーザ名 | 
  
    | \v | bash のバージョン | 
  
    | \w | 現在の作業ディレクトリ | 
  
    | \! | 現在のコマンドのヒストリ番号 | 
  ※特殊文字: 特殊な機能を持つ文字列
  
  以上が bash の主な機能になります. 他にも付録にあるエイリアス(別名)機能 とジョブ制御という機能もあります.
  時間があれば,付録の機能もたしかめてみると良いでしょう.
  これらの機能を使いこなせるかどうかがスキルの指標と言えるでしょう. 
  後述するシェルスクリプトでもこれらの機能が大きな役目を果たすことになりますので, 必要に応じてしっかり復習してください. 
  環境変数とは, アプリケーションやコマンドなどの動作を統一的に制御するためにユーザーが設定する変数です. 
  シェル上で実行される各種のアプリケーションは, 必要に応じてこの環境変数を参照します. 
  主な環境変数
  
    | 環境変数名 | 意味 | 
  
    | USER | ユーザ名 | 
  
    | HOST | ホスト名 | 
  
    | LC_ALLLANG
 LANGUAGE
 
 | 言語環境. 日本語ならば ja_JP.UTF-8, 英語ならば C. 
 LC_ALLによる言語設定は
      ほぼ全てのアプリケーションに関して有効である.LANG,LANGUAGEはアプリケーションに
      よって有効になる場合とならない場合がある. | 
  
    | PATH | コマンドサーチパス.計算機が自動的にコマンドがある場所(ディレクトリ) を探せるようにするためのパス | 
  
    | HOME | ホームディレクトリ | 
  
    - 現在設定されている環境変数を見るには, printenv と打ち込みます. 
    
- 環境変数の設定と変更は, export コマンドを使います. 
  
  環境変数には, 
  あらかじめ使い方が決められたものがあり, 
  変更には注意が必要です. 
  
  
  例として, 以下の4つのコマンドを順番に入力してみてください. 
  
| 
$ export LC_ALL=C
$ man passwd
$ export LC_ALL=ja_JP.UTF-8
$ man passwd
 | 
<--言語環境をデフォルト(英語)にする
<--passwd のマニュアルを表示する(終了するには[q])
<--言語環境を日本語にする
<--passwd のマニュアルを表示する
 | 
  これを実際に試してみると, 一度目の man passwd と二度目の man passwd で出力される結果が違うのが確認できると思います. 
  これはシェル上で実行される man というコマンド(各種のマニュアルを表示するためのプログラム)が, 起動の際に環境変数 LC_ALL を参照し, その記述に従って決められた言語を使って表示を行ったためです. 
  環境変数とはこのように, あらかじめ設定していた文字列によってプログラムの動作を規定する為のものです. 
  
  次に以下のコマンドを実行して下さい. 
  
| 
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/games:
$ date
Fri May  7 14:18:18 JST 2016
$ export PATH=""
$ date
bash: date: command not found
$ /bin/date
Fri May  7 14:20:10 JST 2016
$ export PATH="/usr/local/bin:/usr/bin:/bin:/usr/games:"
$ date
Fri May  7 14:22:45 JST 2016
 | 
<-- 環境変数 PATH を表示させます
--> date コマンドで
    現在の時刻が表示されます.
<-- 環境変数 PATH を空にします.
--> date コマンドは無いと言われました. 
<-- date コマンドの絶対パスを指定しました.
--> 現在の時刻が表示されます.
<-- 環境変数 PATH の設定を元に戻します.
--> date コマンドで
    現在の時刻が表示されます.
 | 
  上記の例では, シェル自身が動作の際に参照している環境変数を操作してもらいました. 
  我々が学んできた「コマンド」はそれ自体が実行ファイルであり, そのファイル名を指定することでコマンドを実行しています. 
  Windows で言うところの「ショートカットアイコンをダブルクリック」しているのと一緒です. 
  環境変数 PATH では, このショートカットアイコンの「デフォルトのリンク先」が記載されています. 
  そのため, これを空欄にするとコマンドのリンク先がわからなくなるために, コマンドが実行出来なくなります. 
  上記の例の中の「date コマンドの絶対パスを指定しました」というのは, ショートカットアイコンのリンク先にあるファイルを直接ダブルクリックすることにあたります. 
  そして「環境変数 PATH の設定を元に戻します」というのは, 正しくショートカットアイコンを作り直すことにあたるでしょう. 
  
  シェルの基本的な説明は以上です.
  他にもいろいろな機能がありますので, 疑問に思ったときは積極的に調べてみましょう.
<< 戻る(事前準備)
    
次へ >>(エディタ)
 
エイリアス(別名)機能
  
  あるコマンドに対して, 別名をつけたいときに用います. 
  
alias 別名=コマンド名
alias 別名='オプション付きのコマンド名'
  
  rm -i(-i オプションは実行確認) を rm と変更してみましょう.
  
| 
$ echo "hello world" > hello.txt
$ rm hello.txt
$ echo "hello world" > hello.txt
$ rm -i hello.txt
rm: remove regular file ‘hello.txt’?
$ echo "hello world" > hello.txt
$ alias rm='rm -i'
$ rm hello.txt
rm: remove regular file `hello.txt'?
 | 
<-- hello.txt ファイルを作成
<-- hello.txt ファイルを削除
<-- hello.txt ファイルを作成
<-- hello.txt ファイルを削除
-->  削除の確認の問い合わせ.y でファイル削除, n で取り消し
<-- hello.txt ファイルを作成
<-- rm -i を rm として登録
<-- hello.txt ファイルを削除
--> -i オプションをつけなくても削除の確認の問い合わせをしてくれる. y でファイル削除, n で取り消し
 | 
ジョブ制御
  ジョブ(Job)とは, ユーザがコンピュータに行なわせる仕事の単位です.
  例えば ls コマンドを実行した時, コンピュータは「ディレクトリ内のファイルリストを作成して表示する」という一つの仕事(job)を請け負うことになります.
  ls コマンドの場合はその job が単純なために一瞬で job が終了しますが, 仕事量の多い(すなわち「重い」)job や継続的な作業が必要な job もあります.
  bash には, 1つのシェル上で複数の job を切替えながら並行して作業を行う機能があります.
  これをジョブ制御と呼びます. 
  
    - フォアグランドジョブ:
 通常シェルでコマンドを実行すると, その作業はジョブとして登録され, そのコマンドが終了するまで次のコマンドを実行することが出来ません.
 このような, シェルが「専念している」 job のことを"フォアグランドジョブ"と言います.
 
- バックグラントジョブ:
 これに対して, コマンドの末尾に & を付けて実行すると, シェルはコマンドの終了を待たずに, すぐ次のコマンドを受け付ける状態になります.
 このような, シェルが「片手間に実行している」 job のことを"バックグランドジョブ"と言います.
 
  言葉だけでは分かりにくいので, 次の 2 つの job を例にして考えてみましょう. 
  
    -  xeyes   : マウスカーソルを目で追うだけのソフトウェア
    
-  xclock  : 時計を表示するソフトウェア
  
  まずは普通に job を実行してみましょう.
| 
$ xeyes 
 | 
<-- xeyes というアプリケーション(ポインタを追いかける目玉)が起動します. 
 | 
  xeyes を起動すると, 目玉が出現する代わりにシェルは入力を受け付けなくなるはずです.
  これはシェルが xeyes をフォアグランドジョブとして登録し, その実行に「専念」しているためです.
  当然のことながら, 一つのシェルが専念できる job は一つだけなので, フォアグランドジョブはシェル一つにつき同時に複数存在することはありません.
  
  では引き続き, バックグラウンドジョブについて見ていきましょう.
  まずはフォアグランドジョブである xeyes を停止しますので, ターミナル上で以下のキーを入力してください.
| 
[Ctrl - C] 
^C
 | 
<-- フォアグランドジョブは Ctrl-C(Ctrlキーを押しながら C キーを押す) で強制終了できます(Ctrl-Z で一時停止にすることもできます).
--> これで xeyes が終了します.
 | 
  コマンドの最後に「&」を付加すると, シェルはそのコマンドをバックグランドジョブとして登録します. 
| 
$ xeyes &
[1] 20758
$ xclock &
[2] 20759
 | 
<-- 今度は xeyes の末尾に & をつけて実行しましょう
--> 先ほどと違い, xeyes を実行しつつシェルは入力待ちの状態になります([]の中はjobナンバー, そのあとの数字はプロセスID を示しています)
<-- バックグランドジョブは複数登録できます
 | 
  バックグランドジョブとして動作しているジョブの一覧を表示させるには, jobs コマンドを用います.
| 
$ jobs
[1]-  実行中               xeyes &
[2]+  実行中               xclock &
 | 
<-- jobs コマンドでバックグランドジョブのリストを呼び出します
--> 実行中のジョブのリストが表示されます. 左側の数字は job ナンバーです
 | 
  job ナンバーを用いると, バックグランドジョブの停止やフォアグランドへの呼び出しが可能になります.
| 
$ kill %1
[1]   終了しました      xeyes
$ fg %2
[Ctrl-C]
^C
$ jobs
 | 
<-- kill コマンドを用いて job ナンバー 1 の xeyes を終了させます
--> 終了できました
<-- fg コマンドを用いて job ナンバー 2 の xclock をフォアグランドに呼び出します
--> フォアグランドに job が登録されたのでシェルは入力を受け付けなくなります
<-- [Ctrl-C]でフォアグランドジョブを終了します
--> 終了できました
<-- jobs で残っている job がないか確認してみましょう
--> 無ければプロンプトが返ってきます
 | 
シェルの組み込みコマンド
シェルで実行できるコマンドの種類には, 「外部コマンド」,「組み込みコマ
ンド」, 「エイリアスで定義されたコマンド」等があります.  「外部コマン
ド」は /bin/, /usr/bin/ 以下のディレクトリに個別に格納されており (例:
ls, xterm) , 「組み込みコマンド」はシェルのプログラムに直接組み込まれ
ています.「組み込みコマンド」には以下のようなものがあります. 
echo, set, unset, alias, history, cd, ...
help コマンドを利用すると, これら組み込みコマンドの, 簡単な説明を得られます. 
  - (help で説明可能な)組み込みコマンドの一覧を表示:
 $ help 
- 組み込みコマンドの説明を表示:
 $ help [組み込みコマンド名] 
コマンドに関するマニュアルは, man というコマンドを用いることで得られます. 
  - 外部コマンドに関するマニュアル
    $ man [外部コマンド名] 
- 組み込みコマンドに関するマニュアル (bash の場合)
    $ man bash 
起動ファイル, 環境定義ファイル
環境変数やシェル変数, aliasを設定 or 変更しても, そのシェルを終了したりログアウト
した場合その設定や変更は消えてしまいます.
一時的な変更ではなく個人で恒常的に環境変数やシェル変数を変更する場合, 
ホームディレクトリ以下に存在する .bashrc, .bash_profile を編集します. 
例えば自分の作成したプログラムやスクリプトの置場にも PATH を通す場合, 
.bashrc や .bash_profile を編集する必要があるでしょう. 
この 2 つのファイルの役割は以下のようになっています. 
  .bashrc と .bash_profile の役割
  
    | ファイル名 | 役割 | 
  
    | .bash_profile | ログインシェルの設定. | 
  
    | .bashrc | ログインシェル以外のシェルの設定 | 
ログインシェルとはユーザがログインした時直後に現れるシェルのことです
(情報実験機のログインシェルは bash です.).
ターミナル(xterm 等)を起動すると一緒にシェルも起動されますが, 
そのシェルは .bashrc を読み込んでいます. 
 2 つ設定ファイルがあって紛らわしいかもしれませんが, 混同しないように
しましょう. 
.bash_profile,.bashrc 共に「シェルスクリプト」になっています
(シェルスクリプトに関しては後述します. ). 
それらのファイルの中身はコマンドが羅列してあると考えて下さい. 
ですから ls --color を ls にエイリアスし, LC_ALL 環境変数を日本語に
したかったらファイル内に以下の 2 行だけ書いておけば良いです.
$ alias ls='ls --color'
$ export LANG=ja_JP.UTF-8
代表的なシェルの紹介
主要なシェルには以下のようなものがあります. 
  - sh(Bourne shell):
 現在利用できるもっとも古いシェル. 
  AT&T のベル研究所で開発され, 
  開発者の1人であるSteven Bourne 氏にちなんで名付けられた. 
  色々なシェルの中で共通項的な位置にあり, 
  ほとんど全ての UNIX で利用できる標準的なシェルであるため, 
  シェルスクリプトの作成には B シェルがよく用いられる.
- csh(c shell):
 カリフォルニア大学バークレイ校の William Joy 氏が中心になって開発したシェルで, 
  C 言語に似た構文を持つことから, この名前が付けられている. 
  B シェルに比べ, ヒストリー機能やジョブ制御, 
  エイリアスなどの機能が付加されており, 対話形式で使用する場合に便利である.
- bash(Bourne Again shell):
 MIT(マサチューセッツ工科大学)の Brian Fox 氏が作成したシェルで, 
  現在, GNU ソフトウェアの一部として配布されている. 
  bash は, 元来 B シェル において貧弱であった, 
  ユーザーインターフェイスとしての機能を強化するため, 
  ヒストリー機能, エイリアスなどが追加されている.
- ash (Almquist shell)  : 
 sh のクローンとして Kenneth Almquist 氏が作成し, 1989 年にオリジナル版がリリースされた. 
  非常に軽量なのでメモリが小さいマシンには適しているが, bash や csh などが持つ拡張機能は持たない.
- dash (Debian Almquist shell)  : 
 ash の NetBSD バージョンを拡張して debian 用に置き換えたシェルである. 
  1997 年初期に debian に移植され, 2002 年に dash と名前を変えた. 
  現在の jessie では /bin/sh は /bin/dash にリンクが貼られている. 
  dash は可能限り軽量になるように作られており, 処理速度は bash よりも速い.
- zsh  : 
 Bourne shell の機能を拡張したシェルで,1990 年に当時プリンストン大学の学生Paul Falstad によって開発された.
  sh のみならず,bashやksh, tcsh などの有用な機能も取り込まれており,カスタマイズもかなり自由度が高い.
  渡辺自身がzsh を支持する理由としては,コマンド修正機能や補間機能がbash に比べて優れているため.
 名前の由来は,当時プリンストン大学のTA であったZhong Shao のログイン名"zsh" より.
  詳細は,2014/11/07 EPnetFaN 座学第20 回「ロースキルユーザによるzsh の紹介」
 
- その他:
 csh の拡張版である tcsh(TC shell)や, ksh などがある.
ここでは bash について説明しましたが, 時間があれば他のシェルも試しに
使ってみましょう.
  
    | $ sh
> 
$ ^[[A^[[A^[[D^[[D
$ exit
 | 
<-- これが sh に debian が改良を加えた「dash」である.
--> dashのプロンプト (bash とは違うモノが表示されるはず)
<-- ヒストリ機能は使えず, カーソルキー(矢印キー)
    を押してもこんな文字が表示されるだけ.
<-- 元のシェルに戻る.
 | 
<< 戻る(事前準備)
    
次へ >>(エディタ)