環境変数マニュアル

環境変数とは、いろいろなアプリケーションが参照する定義です。LESSCHARSET のように、あるコマンドだけが参照する環境変数と、HOMEEDITOR などのように多くのコマンドが参照する環境変数があります。

環境変数の設定方法は csh・tcsh と sh・bash で違います。

% setenv ENVIRONMENT_VARIABLE CONTENT (csh・tcshの場合)
% ENVIRONMENT_VARIABLE=CONTENT; export ENVIRONMENT_VARIABLE (sh・bashの場合)
とすると、環境変数 ENVIRONMENT_VARIABLE の値が CONTENT にセットされます。シェルによって 「=」を付けるかどうかが変わることに注意してください。

現在設定されている環境変数を見るには、setenv コマンドや printenv コマンドを使います。

コマンドラインやシェルスクリプトから環境変数を参照するには、

% echo $HOME
というふうに「$環境変数名」とします。

環境変数名の大文字・小文字は区別されますが、慣例として環境変数名には大文字を使うようになっているようです (シェル変数には小文字を使います)。特別な理由がないなら大文字のみを使う方が無難でしょう。

環境変数はシェル変数と違って子プロセスに引き継がれます。つまり、

% printenv
..(現在設定されている環境変数が表示される)...
% tcsh (新しいシェルを起動)
% printenv
..(前に表示されたものと同じ環境変数が表示される)...
というわけです。これは当然の話で、シェルがいろんなコマンドを子プロセスとして実行するのですから、その子プロセスから環境変数を参照できないと、環境変数の存在意義がありません。

ただし、子プロセスが設定した環境変数は親プロセスには影響を与えませんし、全く無関係のプロセス(親子の関係にないプロセス)にも反映されません。ですから、常に設定しておきたい環境変数は、

  • ~/.login
  • ~/.cshrc (csh・tcshの場合)
  • ~/.tcshrc (tcshの場合)
  • ~/.profile (sh・bashの場合)
  • ~/.bash_profile (bashの場合)
などの中で、ログイン時に設定するといいでしょう。

BLOCKSIZE ブロックサイズの単位。

df・du コマンドなどが参照する。(FreeBSD では) ブロックサイズは512バイトのため、df・du コマンドの出力が 512バイト単位となり、わかりにくい。
% setenv BLOCKSIZE k
とすると、出力が 1KB 単位になる。
% setenv BLOCKSIZE k 1キロバイト単位
% setenv BLOCKSIZE m 1メガバイト単位
% setenv BLOCKSIZE g 1ギガバイト単位
% setenv BLOCKSIZE 1024 1キロバイト単位
% setenv BLOCKSIZE 1048576 1メガバイト単位

du -k などと、コマンド実行時に -k オプションを付けても 1KB 単位で表示できる。

CDPATH 

DISC cdcontrol が参照する CD のデバイス名

DISPLAY Xサーバが実際に描画するサーバ名

現在 foo.com というローカルホストにいて、そこで X サーバが起動されているとする。ここで xeyes を実行すると、当然 xeyes のウィンドウが画面に表示される。この状況で実行されているプログラムは、X クライアント (xeyes) と X サーバである。xeyes が「マウスの位置を教えろ」「円を描け」と X サーバに要求し、X サーバはそのリクエストに従ってマウスの情報を渡したり、画面に円を描いたりしている。

では他のホストで X クライアントを実行してみよう。まず他のホストにログインする必要があるが、その前に
% xhost +
としておく (理由は後述)。そして telnet で bar.com にログインする。
% telnet bar.com
login: ログインネーム入力
password: パスワード入力
ここで xeyes を実行すると
% xeyes
cannot open display.
とエラーになってしまう。これは bar.com 側でウィンドウを開こうとして失敗したからである。foo.com にウィンドウを開くように指示しなければならない。
% setenv DISPLAY foo.com:0.0
これで xeyes が実際にリクエストを出す X サーバは bar.com ではなく foo.com になる。
% xeyes
とすると xeyes が表示されるはずである。この状況では、xeyes という X クライアントは bar.com で動いているが、xeyes は foo.com の X サーバに対して「円を描け」などと要求している。

上記のように環境変数 DISPLAY で設定してもよいが、
% xeyes -display foo.com:0.0
などとオプションで指定することもできる。-display オプションはほとんど全ての X アプリケーションで指定することができる。普通は X クライアントと X サーバは同一のホスト(ローカルホスト)で動いているので、DISPLAY は :0.0 (=localhost:0.0) となっている。

EDITOR 標準エディタの指定

あるプログラム中で自動的にエディタを起動し、ユーザにファイルの編集をさせる場合があるが、このとき、どのエディタを起動すればよいかを指定する。

vipw・chsh・crontab・cvs・less などが参照する。FreeBSD の標準では vi になっているが、例えば mule を使いたい場合は
% setenv EDITOR mule (csh・tcsh の場合)
% export EDITOR=mule (sh・bash の場合)
とすればよい。
% setenv EDITOR "mule -nw" (csh・tcsh の場合)
% export EDITOR="mule -nw" (sh・bash の場合)
のようにオプションも含めて指定した場合、プログラムによってはエラーになることもある。例えば vipw や chsh などは、上の例だと「mule -nw」というプログラムを実行しようとしてしまい、うまくいかない。そういう場合は、 mule-nw というファイル名で
#!/bin/sh
mule -nw $@
という内容のスクリプトを作っておき、
% setenv EDITOR "mule-nw" (csh・tcsh の場合)
% export EDITOR="mule-nw" (sh・bash の場合)
とすればよい。

EXINIT 

GROUP 自分の属するグループ名

HOME ホームディレクトリ。

引数なしで cd を実行したときに移動するディレクトリ。

HTTP_PROXY HTTP で使用する proxy サーバ名

HTTP proxy のホスト名を
% setenv HTTP_PROXY proxy.foo.bar.com (csh・tcsh の場合)
% export HTTP_PROXY=proxy.foo.bar.com (sh・bash の場合)
などと指定する。ポート番号を指定したい場合は
% setenv HTTP_PROXY proxy.foo.bar.com:8080 (csh・tcsh の場合)
% export HTTP_PROXY=proxy.foo.bar.com:8080 (sh・bash の場合)
のようにすればよい。

アプリケーションによっては、
http_proxy=proxy.example.co.jp:8080
などと環境変数名を小文字にしなければ受け付けないものもあるので、マニュアルを読んでほしい。

lynx・fetch・wget などがこの環境変数を参照する。

LANG 使用言語の指定。

コマンドの出力が日本語になったりする便利なもの。
% date
Sat Aug 9 08:08:01 JST 2003
% env LC_ALL=ja_JP.eucJP date
2003年 8月 9日 土曜日 08時08分05秒 JST

EUC-JP を使いたいのであれば、以下のいずれか。
ja_JP.eucJP
ja_JP.EUC
ja_JP.ujis
ja_JP.EUC-JP
Shift_JIS を使いたいのであれば、以下のいずれか。
ja_JP.SJIS
ja_JP.PCK
Unicode であれば
ja_JP.UTF8
を使うとよい。

この辺は各種 UNIX で統一がされず、例えば FreeBSD だけでも
  • 大昔は ja
  • FreeBSD 2.2.? あたりで ja_JP.EUC に変更 (日本のコミュニティは ja_JP.eucJP にすべきと反対したが、受け入れられず)
  • FreeBSD 4.?-RELEASE あたりで結局 ja_JP.eucJP に変更
という始末である。

詳細は「ロケール」の項を参照。

LD_LIBRARY_PATH ランタイムライブラリを検索するパス名

バイナリがランタイムライブラリを必要としているとき、ライブラリを検索するためのパス。

LIBRARY_PATH ライブラリのパス名

MANPATH オンラインマニュアルのパス名

PAGER 標準ページャの指定

man や vipw などを実行したとき、自動的に環境変数 PAGER に設定されているプログラムがページャとして実行される。

% setenv PAGER more (csh・tcsh の場合)
% export PAGER=more (sh・bash の場合)
とすると man ls で more が呼ばれるが、
% setenv PAGER less (csh・tcsh の場合)
% export PAGER=less (sh・bash の場合)
とすると man ls で lessが呼ばれる。
% setenv PAGER "less -gj10" (csh・tcsh の場合)
% export PAGER="less -gj10" (sh・bash の場合)
のようにオプションを設定することもできる。

PATH コマンド・プログラムの置いてあるディレクトリ名を設定する

環境変数 PATH は、コマンド名のみをタイプした際、どこに置いてある実行ファイルを実行すべきかを探すための仕組みである。


PATH の役割
ls とタイプすると /bin/ls が実行されるのはパスという仕組みのおかげである。PATH の内容が
% echo $PATH
/bin:/usr/bin:/usr/local/bin
であるとき、less とタイプすると、
/bin/less
/usr/bin/less
/usr/local/bin/less
の順にプログラムが検索され、コマンドが見つかるとそれが実行される。もし /bin/less が存在すればそれが実行される。もし /bin/less がなくて、/usr/bin/less が存在すれば、/usr/bin/less が実行される。もし /usr/bin/less と /usr/local/bin/less の両方が存在すれば先に書いてある方の /usr/bin/less が実行される。

PATH を変更・追加するには (パスを通す)
単に「less」とタイプしたとき、/usr/local/bin ではなく ~/bin/less を実行したい場合、PATH を変更する。

方法1. パスの順番を変えて全体を設定しなおす
% PATH="$HOME/bin:/bin:/usr/bin:/usr/local/bin"; export PATH
→ sh・bcsh の場合
% setenv PATH $HOME/bin:/bin:/usr/bin:/usr/local/bin
→ csh・tcsh の場合
方法2. PATH の先頭に追加する
% PATH="$HOME/bin:$PATH"; export PATH
→ sh・bcsh の場合
% setenv PATH "$HOME/bin:$PATH"
→ csh・tcsh の場合
なお、PATH 内に同じディレクトリが複数箇所に出現したとしても、特に動作には問題はない (もちろん、あまりキレイではないが)。

また、PATH を変更せずに、alias で
% alias less="$HOME/bin/less"
→ sh・bcsh の場合
% alias less ~/bin/less
→ csh・tcsh の場合
と設定する手もある。

同名のコマンドが複数存在するかどうかを調べる場合は where コマンドを使う (csh・tcsh の場合)。
% where foo
/usr/bin/foo
/usr/X11R6/bin/foo
この場合は先に表示されている /usr/bin/foo が実行されることになる。

シェル変数 path を変更すると、即座に環境変数 PATH にも反映される。逆も同じである。つまり、パスを設定するには、シェル変数 path を設定してもよいし、環境変数 PATH を設定してもよいということである。

セキュリティ上の注意点: PATH に . を含めてはいけない
なお、下記のようにパスに '.' (カレントディレクトリ) を含めるのは危険である。例えば
% setenv PATH ".:/bin:/usr/bin:${HOME}/bin:/usr/local/bin"
→ csh・tcsh の場合
% PATH=".:/bin:/usr/bin:${HOME}/bin:/usr/local/bin"; export PATH
→ sh・bash の場合
と PATH の先頭に '.' を記述していたとする。そのとき、
% cd /tmp
% ls
とすると、もし /tmp/ls が存在した場合、意図せず実行してしまう。もし/tmp/ls の中身が
#!/bin/sh
/bin/rm -rf $HOME
だったとしたら、あなたのホームディレクトリのファイルは全て消えてしまうことになるわけだ。もっとタチの悪いのは、
% cd /tmp
% cat ls
#!/bin/sh
cp /bin/sh /tmp/sh-$USER >/dev/null 2>&1
chmod 4755 /tmp/sh-$USER >/dev/null 2>&1
exec /bin/ls "$@"
と書いておくと、そのユーザの権限になることができる /bin/sh ができあがり。一見、ls を実行しているように見えるので、気づきにくい。

では、PATH の先頭ではなく PATH の末尾に '.' を書くのはどうか。/tmp/ls よりも /bin/ls が先に実行されてしまうので成功率は下がるだろうが、/tmp/sl を配置して ls を sl とタイプミスするのを狙う攻撃は、何日も何ヶ月も待てば成功するかもしれない。結論としては PATH に '.' を含めるべきではない、ということだ。

セキュリティ上の注意点 その2: 空文字は . を意味する
さらにもう一点。PATH の要素に空文字があった場合、それは '.' カレントディレクトリ と同じ意味となる。例えば
% PATH="${PATH}:"; export PATH
⇒ sh・bash の場合
% setenv PATH "${PATH}:"
⇒ csh・tcsh の場合
は "${PATH}:." と同じ意味となる。「わざわざそんな書き方しないよ」と思うかもしれないが、
% setenv PATH "${PATH}:${ADD_PATH}"
% PATH="${PATH}:${ADD_PATH}"; export PATH
と書いたときに $ADD_PATH が空だったら、"${PATH}:" となってしまう。この挙動は LD_LIBRARY_PATH も同じであって、Apache httpd の CVE-2012-0883 の脆弱性がまさにこれ。"insecure ld_library_path -apache" で検索すると他にも同様に修正しているプロジェクトがたくさん見つかる。

PWD カレントディレクトリ名。

例えば cd /usr/local とすると自動的に $PWD=/usr/local と変更される。

REMOTEHOST 現在のホストにログインする前にいたホスト名

foo.com から telnet や rlogin などを使って hoge.com にログインした場合、REMOTEHOST=foo.com と設定される。

SHELL 現在使用しているシェルをフルパス表記したもの

例えば /usr/local/bin/tcsh など。

TERM 端末 (ターミナル) の名称

もともと、文字を入力したり表示したりする装置を指して端末と呼んでいた。最初のうちは端末はプリンタに文字を出力するだけで、いわば文字はたれ流し状態だった。そのうちモニタ上に文字を表示できるようになり、1文字戻ったり、1行削除したり、画面をクリアするなどの機能が求められるようになった。

そこで、「1文字戻る」を表すコードは xxx で、「画面クリア」を表すコードは yyy で…というふうな、特殊なコードが決められた。これをエスケープシーケンスと呼ぶ。ところが、端末を作成していた多くの会社は、独自のエスケープシーケンスを決めたため、互換性が全く存在しない状況になってしまった。そこで、termcap というデータベースが作成され、
  • foo という端末で画面クリアをするエスケープシーケンスは xxx
  • bar という端末で画面クリアをするエスケープシーケンスは yyy
というふうにアプリケーションが端末の種類に応じて、出力するエスケープシーケンスを変えるという仕組みができた。

ユーザが利用している端末の種類を知るために、アプリケーションは環境変数 TERM を参照するのである。(現在の PC-UNIX では) ほとんどのユーザは kterm を使っていると思われる (まぁ Eterm や rxvt もあるだろうけど。Solaris x86 なんかだと dtterm なんだろうか)。
% echo $TERM
kterm
となるだろうか。ここで emacs や vi を実行すると、当然うまく動くはずだ。では、
% unsetenv TERM (csh・tcsh の場合)
% unset TERM (sh・bash の場合)
として、環境変数 TERM をクリアしてから emacs や vi を実行してみてほしい。emacs は
% emacs -nw
Please set the environment variable TERM; see tset(1).
と言われて起動できず、vi は画面表示が変になるはずである。

emacs や vi では、1文字戻ったり画面をクリアする際、エスケープシーケンスを出力している。しかしエスケープシーケンスは端末の種類によって違うので、ユーザが今どの種類の端末を利用しているのかをプログラムに伝えるのが環境変数 TERM の役割なのだ。

USER 自分のログインネーム