[Litz' UNION] > [Dal Segno] > [UNIXたん] > [その5] // [その4][その6]

UNIXたん その5

標準入出力

ファイルディスクリプタとは、プログラムがアクセスするファイル(と、標準入出力)をOSが識別するために使う識別子です。
OSは、このディスクリプタを用いてアクセスすべきファイルを判断します。
さて、プログラムがアクセスする先は何もファイルだけじゃあない。
キー入力とか画面表示とか、とにかく凄い。物凄い。

標準入力
プログラムが汎用データ入力に使うデスクリプタのこと。通常はキー入力。

標準出力
プログラムが汎用データ出力に使うデスクリプタのこと。通常は画面表示。

標準エラー出力
プログラムが汎用エラーメッセージ出力に使うデスクリプタのこと。通常は画面表示。

リダイレクション

今まで、コマンドをキーボードから入力しては画面に表示させてきました。
しかし、標準入出力先を変更することにより、たとえば
ファイル内容をコマンドに与えたり、コマンドの出力をファイルに書き出したりすることができます。
この標準入出力制御のことをリダイレクションと呼ぶのでお忘れなく。
リダイレクションの書き方を以下に示します。コマンドの後ろに書き足して下さい。
(シェルに依存して、通用する書き方と通用しない書き方があります)

標準入力をfileにするもの
< file

標準出力をfileにするもの
> file … 上書き保存。fileが存在しない場合は新規作成
! file (| file) … 上書き保存。noclobber変数を無視して無理矢理上書き
>> file … 追加書き込み保存。fileが存在しない場合は新規作成
>>! file … 追加書き込み保存。noclobber変数を無視して無理矢理追加

標準エラー出力をfileにするもの
2> file … 上書き保存。fileが存在しない場合は新規作成

標準出力と標準エラー出力をfileにするもの
> file 2>&1 (>& file) … 上書き保存。fileが存在しない場合は新規作成
>| file 2>&1 (>&! file) … 上書き保存。noclobber無視
>> file 2>&1 (>>& file) … 追加書き込み保存。新規作成
>>&! file … 追加書き込み保存。noclobber無視

標準出力をfile1、標準エラー出力をfile2にするもの
(コマンド > file1) >& file2 … 上書き保存。fileが存在しない場合は新規作成

標準入力を最初の「EOF」から最後の「EOF」までの内容にするもの
(EOFの部分は他の文字列でも良い。但し2個所は一致させること)
<< EOF
内容行(複数行にわたっても良い)
EOF

> ls -al > file

ls- al の結果そのままの内容がファイルfileに書き出されます。プロンプトは次のコマンドラインへ

ブラックホールファイル

/dev/null は非常に特殊なファイルで、ブラックホールファイルと呼ばれています。
全てを飲み込む・中身なしといった性質はまさにブラックホール。何もかも皆懐かしい

さて、これをリダイレクト先に指定すると
標準入力 … 何も入力しない
標準出力 … 出力が飲み込まれる。ブラックホールファイル自体は何の変化もなし

これはもしかするといろいろな用途に使えるかもしれない。

> cp /dev/null file

fileという空っぽのファイルが作成されます。

取っておく必要のない出力を、画面に表示させたくないしどないしよかなーというとき、
リダイレクト先に /dev/null を指定するとよさげ。

パイプ

リダイレクションとは「標準入出力先を変更する」ことです(前述)。
これを用いて、「ps の出力を less で見る」などといったように、プログラムの出力を別のプログラムの入力に与えることができます。
通常のリダイレクションでは、このような制御を行おうとすると新たなファイルを介在させねばならず、間違いも起こりやすいのでやってられません。
そこで、パイプと呼ばれる方法がUNIXには備わっています。

パイプの使い方は以下の通り。
なお、パイプは何段にも重ねて繋ぐことができます。

A | B … Aの標準出力をBの標準入力として渡す。
A 2>&1| B … Aの標準出力と標準エラー出力をBの標準入力として渡す。
(csh系の場合は A |& B )

> ps -axu | less
ps -axu だけでは大量のデータで画面が流れてしまいますが、ページャで見ると楽々。

> ps -axu | sort +1 | less
さらにプロセスID順にソートするも良し

tee

パイプからの入力を標準出力とファイルに書き出します。無害

引数(ファイル名)を与えると、そのファイルに書き出されます。

> ls -l | tee sample
total 0
-rw-r--r-- 1 litz staff 0 Jun 19 21:35 file1
-rw-r--r-- 1 litz staff 0 Jun 5 18:39 file2


> cat sample
total 0
-rw-r--r-- 1 litz staff 0 Jun 19 21:35 file1
-rw-r--r-- 1 litz staff 0 Jun 5 18:39 file2


確かに、ls の出力とファイル sample の内容は一致しています。

「ファイルに取っておきたいけど、画面でも確かめたい」ときに活用しましょう。
そういえば作業過程を記録するものに script があったかな(違いを意識しておくこと)

先読み評価

コマンドの中で、 ` (逆引用符。[Shift][@])で囲まれた部分は先に実行されます。
コマンドを組み合わせるという点ではパイプと似てますね。どちらも重要です。
使い方などは、例を見ながら自分で試したりなどして覚えていきましょう。

> touch file_`date +%Y%m%d`
> ls
file_20040619

date +%Y%m%d の結果は 20040619 など「今日8」と呼ばれる数字列。(前述)
今回は `` で囲まれているので、その中身が先に評価されます。
従って、コマンドとしては touch file_20040619 と等価。

シェル環境の設定

環境変数とは、環境全体に関する変数のことかも知れない。全てのプロセスに有効。
シェル変数とは、実行中のシェルのみに関する変数のことかも知れない。

printenv

現在の環境変数を全て表示します。無害

引数なしの env, setenv でも同じ結果が得られます。
echo $変数名 とすると、指定した環境変数を見られます。
詳細は「環境変数」の項目を参照のこと

環境変数

printenv で、環境変数を見てみましょう。
これらの変数は、シェルから起動した全てのプロセスで設定・参照できます。
$ 変数名 で参照。設定は後述

> printenv
HOME=/Users/litz
SHELL=/bin/tcsh
USER=litz
LANG=ja_JP
PATH=/bin:/sbin:/usr/bin:/usr/sbin

(以下略)

主な環境変数は以下の通り。

HOME … ホームディレクトリ
SHELL … ログイン(デフォルト)シェル
USER … ユーザ名
LANG … 使用言語
PATH … コマンドサーチパス。後述
TERM … 端末の種類
PWD … カレントディレクトリ
EDITOR … エディタを起動するときのデフォルト。vi, xemacsなど
PAGER … ページャを起動するときのデフォルト。more, lessなど

EDITOR, PAGER, LANG, TERM あたりがよくいじられます。いじり方は後述

シェル変数

set で、シェル変数を見てみましょう。
$ 変数名 で参照。設定は後述

> set
history 100
home /Users/litz
prompt [%B%T%b]
(一部抜粋)

主なシェル変数は次の通り。
csh系での変数名(sh系での変数名) でお送りします。括弧書きの無いものは共通

prompt(PS1) … プロンプト(入力待ちの時に表示される[litz ~/] % など)の形式
prompt2(PS2) … サブプロンプトの形式
history(HISTSIZE) … 記憶するコマンド履歴の最大数
ignoreeof(IGNOREEOF) … EOF(入力の終わり; [Control][D])でシェルが終了するのを防ぐ
noclobber … 存在するファイルに出力リダイレクトをしない
(リダイレクションの項目で出てきた noclobber っていうのはこれ。不注意による上書きを防ぎます)
noglob … ファイル名のワイルドカード展開をしない

プロンプトの設定の例

csh, tcshの場合
> set prompt="%{\e]2;${TERM}: %n@%m\a%}[%{\e[35;04m%P:\e[32m%~\e[00m%}] "
sh, bash, zshの場合
> PS1="\[\e]2;$TERM: \u@\h\a[\[\e[35;4m\]\t:\[\e[32m\]\w\[\e[0m\]] "

これでプロンプトが [12:00:00:~Desktop/qma] みたいになるかも
ウィンドウのタイトルが vt100: litz@zaq3d2e28a7 みたいになるかも

いろいろ試してみたりして自分好みの環境を見つけて下さい。
ただし、保護色(背景色と文字色が同じ状態)にしないよう注意

環境変数とシェル変数の設定(sh)

sh系シェルでは、シェル変数を export したものが環境変数です。

シェル変数に値を代入するには、 変数名=値 とするだけ。

unset

シェル変数・環境変数を削除します。やや有害

unset a とすると、変数aが解除されます。

export

シェル変数を公開します。やや有害

export A とすると、シェル変数Aを環境変数として公開します。

環境変数とシェル変数の設定(csh)

csh系シェルでは、シェル変数と環境変数は別物。
シェル変数は変数名を小文字、環境変数は大文字で表記します。

set

シェル変数を設定します。やや有害

set key=val とすると、シェル変数keyに値valを代入します。
ignoreeof あたりは set ignoreeof だけでも良し

setenv

環境変数を設定します。やや有害

setenv KEY=val とすると、環境変数KEYに値valを代入します。

unset

シェル変数を解除します。やや有害

unset a とすると、シェル変数aが解除されます。

unsetsnv

環境変数を解除します。やや有害

unsetenv A とすると、環境変数Aが解除されます。

設定ファイル

いくらシェル変数や環境変数を設定しても、一度ログアウトしたら水の泡。
そこで、よく使う設定はファイルに保存しておきましょう。
大概になってきたので簡単に解説しておきます。頑張ってついてこい

tcshの場合
.login … ログイン端末の初期設定ファイル。ログイン時に実行される
.tcshrc … tcshの初期設定ファイル。ログイン時に実行される
.logout … ログアウト時に実行される

bashの場合
.bash_profile … ログイン時に実行される。環境変数を書いたり
.bashrc … ログイン時に実行される。エイリアスを書いたり
.logout … ログアウト時に実行される

とまあ、色とりどり。使っていると知らず識らずに増えたりもします。
とりあえず、良くわからんうちは .bashrc か .tcshrc だけをいじれば何とかなります。

この中にalias文だとか、setやらsetenvやらを書きましょう。
最後の設定の後ろにも改行(LF)が要ります。
ファイルを保存したら、ログインし直すか source を行えば、設定が有効になります。

source

ファイルに書かれたコマンドを実行します。やや有害

source file とすると、fileに書かれた内容をコマンドとして実行します。
シェルの設定ファイルを今すぐ読み込んで実行したい時に便利です。

ここまでの内容をおさらいする意味で、設定の例を置いておきます。
まず、vi(他のテキストエディタでもOK)で .tcshrc を作成。

> cat .tcshrc
setenv PATH=/bin:/sbin:/usr/bin:/usr/sbin:/test
alias LS "ls -al"
alias PS "ps -axu"
set prompt="%{e]2;${TERM}: %n@%ma%}[%{e[35;04m%P:e[32m%~e[00m%}] "


こんな内容にでもしておきましょう。

> source .tcshrc
[12:00:00:~] LS
drwxr-xr-x 22 litz staff 748 Jun 20 13:10 .
drwxrwxr-t 6 root wheel 204 Dec 15 2002 ..

(以下略)

確かに設定が有効になっているようです。再びログインしても有効です。

今一度まとめます。
自分好みの設定をいつも使いたいときは…

(1).bashrc か .tcshrc に、setenv, set, aliasなど、ログイン時に実行したいコマンドを記述する。

(2)ログインしなおすか、sourceで読み込む。

各自お好みの設定をお楽しみ下さい。

エイリアス

エイリアスの基本的な使い方については以前にも述べましたが、ここで補足

\!* で、全ての引数を参照します。
\!$ で、最後の引数を参照します。
\!:n で、n番目の引数を参照します。

2つの引数の和を表示するコマンドを作ってみると、

> alias SUM "echo '\!:1 + \!:2' | bc"

> SUM 57 43
100

関数

sh系のシェルでは、シェル設定ファイルに関数を定義することができます。
機能的にはaliasと同じ。

関数名 () {
処理1;
処理2:
}
といった感じ。n番目の変数は$n で参照できます。

2つの引数の和を表示する関数(上記のものと同じ)は、

SUM () {
echo "\!:1 + \!:2" | bc
}

↑これを設定ファイルに追記する。

> SUM 57 43
100

環境設定の注意点

ここではシェルのカスタマイズを紹介しましたが、その気になれば
vi とか emacs とか、各種ソフトの環境設定も自由に行えます。
どんどんカスタマイズしちゃいましょう。

そこで一つ注意が必要なのは、
「設定変更が完了するまでログアウトしないウィンドウを確保しておく」こと。
つい下手な設定をやらかしてしまうと、どうしようもない事態に陥るかもしれないから。
(ターミナルの文字が保護色になってしまうのもその一つと言えるでしょう)

何か設定を変更したときは、新窓で確認するようにしましょう

[Litz' UNION] > [Dal Segno] > [UNIXたん] > [その5] // [その4][その6]