多くのシェルには、プロファイル(Profile)と呼ばれる起動時に環境設定を行うための機能がある。UnixのBourne Shellがホームディレクトリに置かれた“.profile”で起動時の環境設定を行っていたこともあり、シェルでプロファイルというと、シェル起動時の環境設定スクリプトを意味する。
過去を探すとBell研のPWB/Unix(1974年)に入っていたPWB Shell(Mashey Shell)のマニュアルには、起動時に“.profile”を読むという記述ある。もう50年近くも前のことだ。このMashey Shellは、のちにUnixの標準となるBourne shellのベースとなった。Bourne Shellが入ったUnix V7のshのmanページにも“$HOME/.profile”の記述がある。現在広く使われているbashは、このBourn Shellを置き換えることを目的にオープンソース・プロジェクトとして開発された。このため、Bourne Shellの主要な機能が継承されている。
bashでは、“.bashrc”というファイルも初期化スクリプトとして利用する。「.ナントカrc」というファイル名は、1979年のC Shellで、やはりプロファイル用に「.cshrc」という名称で使われている。これは2BSDのcshのソースコードで確認できる。
こうした背景があるため、多くのシェルはプロファイル機能を持つ。各種のLinux/Unix系シェルやWindowsのPowerShellにもある。名前はプロファイルではないが、MS-DOSのCommand.comを先祖とするcmd.exeにも似た機能がある。MS-DOS時代にはautoexec.batというバッチファイルを起動時に実行していた。
Ubuntuに見るbashのプロファイル
bashのプロファイル実行過程はちょっと複雑だ。まず、起動時の状況や起動オフションなどによってプロファイルの振る舞いが違って来る。さらに、シェルがユーザーと対話するのか(ユーザーからコマンドを受け付けるのか)、そうでないのかによっても違いがある。また、起動するファイル名についてはbashで決まっているものの、その中で何をするのかは、ディストリビューション側の設定に依存する。あるいは、ユーザーが完全に中身を書き換えることもある。このため、同じbashであっても、その実行過程にはディストリビューションごとの違いが出てくる(ここではUbuntu 18.04 LTSを調べた)。
表01がbashのプロファイルの実行過程だ。まず、プロファイルの実行過程は、bashが「ログインシェル」として起動されたか、そうでないかによって違いが出る。プログラムの起動パスなど、一回だけ調べればいいようなものは、ログインシェルとしての起動時に済ませてしまうわけだ。一般にプロセスには親子関係があり、bashなどのシェルでもこれは同じ。子プロセスは、親プロセスの環境を引き継ぐことができるため、一回環境変数に情報を保持したら、これを継承することで同じことを繰り返さずに済む。
■表01 | ||
---|---|---|
起動状態 | bashの動作 | Ubuntu 18.04 LTSの場合 |
ログインシェルのとき | /etc/profileを実行 | /etc/bash.bashrc、/etc/profile.d/*.shを呼び出し(*1) |
最初に発見したものを実行 | ||
~/.bash_profile | 存在しない | |
~/.bash_login | 存在しない | |
~/.profile | ~/.bashrcの呼び出しとPATHの追加設定 | |
ログアウト時に存在すれば実行 | ||
~/.bash_logout | 存在しない | |
ログインシェルでない2回目以降の起動など | 対話的に起動されたとき実行 | |
~/.bashrc | aliasや補完、プロンプトの設定など | |
非対話的なとき | ||
環境変数$BASH_ENVがあれば指定されたファイルを実行 | 存在しない | |
(*1):bash.bashrcではsudo関連の設定を行っている。profile.dにはアプリケーションが登録した初期化スクリプトが登録される |
ログインシェルではない場合、大きく2つの場合があり得る。1つは、ユーザーがコマンドを入力する「対話的(あるいはインタラクティブなどとも)」なシェルとして起動される場合と、シェルスクリプトを実行するために起動される場合(非対話的、非インタラクティブ)の2つだ。前者は、ユーザーが自分の使い方に合わせて、設定を変更したいだろう。逆に非対話的な場合には、余計なことはしないですぐに処理を済ませたい。だからプロンプトやPATHの設定を省くわけだ。
複数のプロファイルがあるが、実際には、「~/.profile」に自分用の一回きりの処理(たとえばPATH環境変数の設定など)を書き、「~/.bashrc」には、起動時に毎回行う自分用の処理(プロンプトの設定など)を書く。
プロファイルの処理にかかせないのが、「ドットソース」と呼ばれるコマンドだ。「source」というbashの内部コマンドだが、省略形としてピリオド1つが割り当てられているため、この名がある。このsourceコマンドは、スクリプトを実行してその結果を現在のシェルプロセスに反映させるものだ。スクリプトを普通に実行してしまうと、子プロセスとしシェルが起動するため、実行後は環境変数などに結果が残らない。各種のプロファイルの中にはこのドットソースが結構使われている。
PowerShellのプロファイル
PowerShellにもプロファイルがあり、起動時に指定されたファイルを実行する。PowerShellには、ホスト別、ユーザー別に4つのプロファイルがある(表02)。プロファイルのファイル名は、$PROFILEという変数で参照でき、たとえば「notepad.exe $PROFILE」などとすると、ユーザープロファイルをメモ帳で開くことが可能だ。このときにはCurrentUserCurrentHostプロパティの設定値が編集対象になる。プロファイルのうちAllUsersAllHost、AllUsersCurrentHostの2つは編集に管理者権限が必要だ。
■表02 | ||||
---|---|---|---|---|
プロパティ | 順 | Ver. | フォルダ | ファイル名 |
$PROFILE.AllUsersAllHosts(*1) | 1 | 5 | C:\Windows\System32\WindowsPowerShell\v1.0 | profile.ps1 |
7.2 | C:\Program Files\PowerShell\7 | |||
Preview | C:\Program Files\PowerShell\7-preview | |||
$PROFILE.AllUsersCurrentHost(*1) | 2 | 5 | C:\Windows\System32\WindowsPowerShell\v1.0 | Microsoft.PowerShell_profile.ps1 |
7.2 | C:\Program Files\PowerShell\7 | |||
Preview | C:\Program Files\PowerShell\7-preview | |||
$PROFILE.CurrentUserAllHosts | 3 | 5 | %userprofile%\WindowsPowerShell | profile.ps1 |
7.2 | %userprofile%\PowerShell | |||
Preview | ||||
$PROFILE.CurrentUserCurrentHost(*2) | 4 | 5 | %userprofile%\WindowsPowerShell | Microsoft.PowerShell_profile.ps1 |
7.2 | %userprofile%\PowerShell | |||
Preview | ||||
(*1):編集には管理者権限が必要 (*2):$PROFILEをコマンドラインで評価すると「$PROFILE.CurrentUserCurrentHosts」に指定されたパスのみが返る |
4つの初期化スクリプトがあり、その名前から基本的な役割がわかるが、実際には、プロファイルを自動で他のホストにコピーする機能や、他のマシン用のプロファイルを自動で区別する機能があるわけではないので、「お勧め」のルールにしか過ぎず、単に優先順位(読み込み順)が違うだけだ。実際には、ドキュメントフォルダのprofile.ps1だけを使い、もし機種依存する処理ならホスト名などで判定して実行を決めるスクリプトにする。他のPCでも利用したいなら、OneDriveでドキュメントフォルダをバックアップ設定にすればよい。
なお、PowerShellにもドットソースコマンドがあり、指定したファイルを読み込んで現在のセッションに結果を反映できる。これは、PowerShellのスコープを制御するための特殊な記法だが、振る舞いとしてはbashのドットソースと同じである。
cmd.exeのAutoRun
cmd.exeには、(表03)のようなレジストリで、起動時に実行するコマンドを指定できる。このレジストリに複数のコマンドを記述したいときには、コマンドを&&で区切る。たとえば「set AutoRun=TRUE && set AutoRun2=Yes」などとする。
■表03 | |||
---|---|---|---|
キー | 名前 | タイプ | データ |
"HKLM\SOFTWARE\Microsoft\Command Processor" | AutoRun | REG_SZ | 全ユーザーで実行するコマンド |
"HKCU\SOFTWARE\Microsoft\Command Processor" | AutoRun | REG_SZ | 現在のユーザーで実行するコマンド |
レジストリ指定ではどんなコマンドも実行できるが、直接、間接を問わずcmd.exeを起動すると、無限にcmd.exeを起動しようとする(よーく考えてくれ)。最悪の場合「詰む」ことがあるので、どうしてもという場合に環境変数の設定だけで使うほうがよい。
cmd.exeで環境設定するなら、バッチファイルとして直接実行させるようにしたほうがよい。cmd.exeにはドットソースはないが起動オプションとして、スクリプトの実行後に終了しない「/k」というオプションがある。コマンドラインを使うとき、必ず実行したいコマンドがあるなら、それを記述したバッチファイル(仮にMyCmd.batとする。中身はなんでもよい)を作り、これを実行したあとプロンプトに戻るようにする。具体的には、
cmd.exe /k "MyCmd.bat"
というコマンドを実行すればよい。スタートメニューなどに登録したいなら、cmd.exeのショートカットを作り上記のようにオプションを指定する。あとは、これを「コマンドプロンプト」のように起動すればよい。
Windowsでは、GUIとコマンドラインのプログラムが分断されているので、GUIアプリケーションだけを使っていると、プロファイルとは無縁だが、Linux/Unixでは、GUIアプリケーションとコマンドラインは近い場所にあり、GUIアプリケーションが環境変数を見て挙動を変えるといったことがある。たとえばGIMPは環境変数で表示言語を変更できる。Windowsでも不可能ではないが、Linux/Unix由来のアプリケーションでもないとほとんどみかけない。そういうわけで、sh系シェルでは、プロファイルは、自分の環境設定の基本でもある。注意しないと、リモートでログインしたときに前に誰もいないマシンにウィンドウを表示しかねないが、X Window Systemでは、リモートにウィンドウを表示することもできた。