UNIX系のOSでは、「環境変数」と呼ばれる変数がコマンドの動作に影響を与える。標準ライブラリが、環境変数を見て動作を変えるためだ。あらかじめ設定されている環境変数はOSごとに異なっているし、シェルやシステムの設定ファイル、ユーザーの設定ファイルなどによっても変わってくる。今回は、この環境変数を操るためのコマンドを紹介しよう。

環境変数を一覧表示する

あらかじめ設定されている環境変数は、シェルであれば「env」というコマンドで一覧表示させることができる。主なOSの環境変数の例は、次のとおりだ。

●CentOS 7で設定されている環境変数の例

[root@centos ~]# env
XDG_SESSION_ID=1
HOSTNAME=centos.ongs.co.jp
TERM=vt220
SHELL=/bin/bash
HISTSIZE=1000
USER=root
LS_COLORS=
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/root
LANG=ja_JP.UTF-8
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
LOGNAME=root
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/0
_=/bin/env
[root@centos ~]#

●macOSで設定されている環境変数の例

/Users/daichi$ env
TERM_PROGRAM=iTerm.app
TERM=xterm-256color
SHELL=/bin/bash
TMPDIR=/var/folders/2h/1b8rfbs95pl0f8mpj1qj3bxm0000gn/T/
Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.ZRfBk5wMuZ/Render
TERM_PROGRAM_VERSION=3.0.15
TERM_SESSION_ID=w10t0p0:D619F530-E193-4BAB-8943-6BC826EFB86C
SVN_EDITOR=nvim
USER=daichi
LS_COLORS=di=32:ln=35:so=01:pi=33:ex=31:bd=46;34:cd=43;34:su=41;30:sg=46;30:tw=42;30:ow=43;30
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.oTQlCBTfPR/Listeners
__CF_USER_TEXT_ENCODING=0x1F5:0:0
LSCOLORS=cxFxCxdxBxegedabagacad
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin
PWD=/Users/daichi
LANG=ja_JP.UTF-8
ITERM_PROFILE=Default
XPC_FLAGS=0x0
XPC_SERVICE_NAME=0
SHLVL=1
HOME=/Users/daichi
COLORFGBG=7;0
ITERM_SESSION_ID=w10t0p0:D619F530-E193-4BAB-8943-6BC826EFB86C
LOGNAME=daichi
DISPLAY=/private/tmp/com.apple.launchd.jbYIYRXah9/org.macosforge.xquartz:0
_=/usr/bin/env
/Users/daichi$

実のところ、「ホームディレクトリ」は環境変数HOMEで設定されているパスのことだし、各種コマンドは環境変数PATHに設定されているディレクトリ以下に配置されている実行可能なファイルのことだ。ユーザー名すら、環境変数USERに設定されている。

この環境変数は、子プロセスにコピーされるということを知っておいていただきたい。その辺りの動作についてきちんと理解するには、まずプロセスの生成メカニズムを押さえておく必要があるのだが、詳細に解説するのは本連載の趣旨に反するので、ここではごく簡単な説明に留めておこう。

UNIX系OSでは、シェルから「コマンドを実行する」というのは「シェルプロセスをコピーして、それをコマンドで上書きして実行する」という処理を意味する。

わかりにくいかもしれないが、要するに「実行するコマンドにはシェルの環境変数がコピーされている」ということだ。シェルで設定した環境変数がコマンドに影響を与えるのは、このためである。シェルの環境変数は、全てコマンドにコピーされており、コマンドはその環境変数に従って処理を行うのだ。

envコマンドではシェルで設定されている環境変数を一覧表示することができるが、つまりこれはenvコマンドが実行される前にシェルの環境変数がenvのプロセスにコピーされているため、envコマンドは(コピーされた)自身の環境変数を一覧出力しているだけにほかならない。説明がややこしいが、ひとまずは「シェルで設定されている環境変数を一覧表示するコマンド」だと理解してもらえればと思う。

特定のコマンドの環境変数だけを変えて実行する

このenvコマンドは環境変数を一覧表示するだけではなく、「指定した環境変数を書き換えた後に、指定したコマンドを実行する」という機能も持っている。シェルの環境変数を変更すると、その後の全てのコマンドに影響を与えてしまうので、ちょっと困るようなケースがある。そんな「特定のコマンドの環境変数だけを変えて実行したい」という場合には、このenvコマンドが有効なのだ。

実行例は、以下のとおりだ。

[root@centos ~]# echo $LANG
ja_JP.UTF-8
[root@centos ~]# date
2017年  8月  8日 火曜日 04:37:35 JST
[root@centos ~]# env LANG=en_US.UTF-8 date
Tue Aug  8 04:37:37 JST 2017
[root@centos ~]#
[root@centos ~]# echo $LANG
ja_JP.UTF-8
[root@centos ~]#

この例では、シェルの環境変数LANGが「jaJP.UTF-8」に設定されている。環境変数LANGは言語設定を変更するためのもので、iPhoneやAndroidで言えば言語設定を英語や日本語にする処理に相当する部分だ。「jaJP.UTF-8」は日本語にする設定である。ほかの値を指定することもできるのだが、今ではほとんどのディストリビューションでこの設定を使っているはずだ。

環境変数LANGが「ja_JP.UTF-8」になっていると、コマンドの出力は日本語をベースとしたものになる。ただし、場合によってはこの設定では困ることがある。日本語ではなく英語で出力したいとか、コマンドによっては日本語設定では動作しないものがあるからだ。

ちなみに、古くからUNIX系のOSを使っている人のなかには、こうした問題を避けるために全て英語の設定にしている人もいるが、最近のディストリビューションはよくできているので日本語設定にしておいて問題があることはほとんどない(全くないわけではないけれども)。

一時的にこうした環境変数を設定してコマンドを実行するには,上記のように「env LANG=enUS.UTF-8 date」と設定してコマンドを実行する。こうすると、環境変数LANGは「enUS.UTF-8」に変更されるが、それはdateコマンドの実行に対して影響を与えるだけで、元のシェルには影響を与えない。システムコールであるfork(8)およびexec(8)の動作を考えれば当たり前のことなのだが、その辺りの細かい話は本連載では割愛する。envコマンドはこう使えばよい、ということだけ覚えておいてもらえればと思う。

シェルの環境変数を変更すると、全てのコマンドに影響が出てしまう。一時的に環境変数を変えられればよい場合には、envコマンドが便利だ。ぜひ覚えておいていただきたい。