web-dev-qa-db-ja.com

環境変数を設定するためのディストリビューション/シェルに依存しない最良の方法は何ですか?

質問はそれをすべて言います。現在、Arch Linuxとzshを使用していますが、VTとxtermの両方で(少なくとも)機能し、ディストリビューションやシェルを切り替えても(できれば)引き続き機能するソリューションが欲しいです。

さまざまなディストリビューションのドキュメントで、この質問に対するまったく異なる回答を聞いたことがあります。 Ubuntuは「.pam_environmentを使用」と言っています。 Archで彼らが推奨するものはあなたのシェルに依存すると思います。現在、私はすべてを 。profile に入れており、シェルが何らかの理由(たとえば、.bash_profileが存在する場合はbash)でソースを提供しない場合は、手動でソースを追加してオーバーライドします。しかし、もっと良い方法があるに違いないようです。

32
strugee

残念ながら、環境変数を設定するための完全に移植可能な場所はありません。最も近い2つのファイルは _~/.profile_ です。これは従来の場所であり、そのまま使用できます多くの設定、および_~/.pam_environment_は、現代的でありふれた場所ですが、代替手段は限られています。

_~/.pam_environment_に何を入れるか

ファイル_~/.pam_environment_は、 [〜#〜] pam [〜#〜] を使用し、このファイルが有効になっているすべてのログインメソッドによって読み取られます。これは、現在ほとんどのLinuxシステムをカバーしています。

_~/.pam_environment_の主な利点は、(有効になっている場合)ユーザーのシェルが起動する前に読み取られるため、セッションの種類、ログインシェル、その他の複雑さに関係なく機能することです。 _su -c somecommand_や_ssh somecommand_などの非対話型ログインでも機能します。

_~/.pam_environment_の主な制限は、複雑なシェル構文ではなく、単純な割り当てのみを配置できることです。このファイルの構文は次のとおりです。

  • ファイルは行ごとに解析されます。
  • 先頭の空白は無視されます。
  • オプションで、行をexportと1つのスペースで開始できます(タブではなく、図を参照)。
  • その後、各行の形式は_VAR=VALUE_である必要があります。VARは文字、数字、およびアンダースコアで構成されます。
  • _#_はコメントを開始します。値に含めることはできません。
  • VALUEが_'_または_"_で始まり、同じ引用符がもう1つ含まれている場合、VARは引用符の間の文字列に設定されます(2番目の引用符以降は無視されます)。それ以外の場合、VARは_=_記号の後の文字列に設定されます。
  • _=_がない場合、変数は環境から削除されます。

つまり、_~/.pam_environment_は、さまざまな状況で機能します。欠点としては、変数の値を別の変数に基づいて(PATHにディレクトリを追加するなど)、コマンドの出力を使用する(たとえば、ディレクトリまたはプログラムが存在するかどうかをテストする)などの動的な設定を行うことはできません。文字(_#'"_、改行)を値に入れることは不可能または面倒です。

_~/.profile_に何を入れるか

このファイルには、移植可能な(POSIX)sh構文が必要です。システムにこれらのシェルが_[[ … ]]_として含まれていることがわかっている場合にのみ、kshまたはbash拡張機能(配列、_/bin/sh_など)を使用してください。

このファイルは、自動化されたアプリケーションのスクリプトによって読み取られる可能性があるため、出力を生成するプログラムを呼び出したり、execを呼び出したりしないでください。テキストモードのログインでそれを実行したい場合は、対話型シェルに対してのみ実行してください。例:

_case $- in *i*)
  # Display a message if I have new mail
  if mail -e; then echo 'You have new mail'; fi
  # If zsh is available, and this looks like a text-mode login, run zsh
  case "`ps $PPID` " in
    *" login "*)
      if type zsh >/dev/null 2>/dev/null; then exec zsh; fi;;
  esac
esac
_

これは、ログインシェルとして_/bin/sh_を使用し、お気に入りのシェルに切り替える例です。参照 システム管理者が変更を拒否したときに、ログインシェルとしてbashを使用するにはどうすればよいですか

非グラフィカルログインで_~/.profile_が読み込まれないのはいつですか?

異なる ログインシェル 異なるファイルを読み取ります。

ログインシェルがbashの場合

Bashは、_~/.bash_login_ではなく_~/.bash_profile_または_~/.profile_が存在する場合はそれらを読み取ります。また、bashは、インタラクティブであっても、ログインシェルで_~/.bashrc_を読み取りません。これらの癖を覚える必要がないようにするには、次の2行で_~/.bash_profile_を作成します。

_. ~/.profile
case $- in *i*) . ~/.bashrc;; esac
_

参照 bashを使用して環境変数を設定するには、どの設定ファイルを使用する必要がありますか?

ログインシェルがzshの場合

Zshは_~/.zprofile_および_~/.zlogin_を読み取りますが、_~/.profile_は読み取りません。 Zshの構文はshとは異なりますが、shエミュレーションモードでは_~/.profile_を読み取ることができます。これを_~/.zprofile_に使用できます:

_emulate sh -c '. ~/.profile'
_

参照 Zshが〜/ .profileにヒットしない

ログインシェルが他のシェルの場合

ログインシェルとして_/bin/sh_を使用し、インタラクティブシェルとしてのみお気に入りのシェル(魚など)を使用する以外は、そこでできることは多くありません。それが私がzshで行うことです。 _~/.profile_から別のシェルを呼び出す例については、上記を参照してください。

リモートコマンド

対話型シェルを経由せずにリモートコマンドを呼び出す場合、すべてのシェルが起動ファイルを読み取るわけではありません。

Kshは、渡した場合、ENV変数で指定されたファイルを読み取ります。

Bashは、インタラクティブでない(!)であり、その親プロセスがrshdまたはsshdである場合、_~/.bashrc_を読み取ります。したがって、_~/.bashrc_を

_if [[ $- != *i* ]]; then
  . ~/.profile
  return
fi
_

Zshは起動時に常に_~/.zshenv_を読み取ります。これは、他の変数を設定したサブシェルであっても、zshのすべてのインスタンスによって読み取られるため、注意して使用してください。ログインシェルがzshであり、それを使用してリモートコマンドの変数のみを設定する場合は、ガードを使用します。_~/.profile_などの変数を_MY_ENVIRONMENT_HAS_BEEN_SET=yes_に設定し、_~/.profile_。

_if [[ -z $MY_ENVIRONMENT_HAS_BEEN_SET ]]; then emulate sh -c '~/.profile'; fi
_

グラフィカルログインの場合

多くのディストリビューション、ディスプレイマネージャー、およびデスクトップ環境では、スタートアップスクリプトから明示的に取得するか、ログインシェルを実行することにより、_~/.profile_を実行するようになっています。

残念ながら、_~/.profile_が読み取られないdistro/DM/DEの組み合わせを処理する一般的な方法はありません。

_~/.xsession_によって開始される従来のセッションを使用する場合、これは環境変数を設定する場所です。 _~/.profile_(つまり、_. ~/.profile_)をソースとして使用します。一部のセットアップでは、デスクトップ環境の起動スクリプトが_~/.profile_を再度ソースすることに注意してください。

私が知る限り、環境変数の設定方法はディストリビューションやシェルにとらわれない標準が存在しません。

最も一般的で事実上の標準は/etc/profile~/.profileのようです。 2番目に一般的なのは、/etc/environment~/.pam_environmentのようです。

私が見つけたすべてのドキュメントもすでに見つけたようです。私は他の読者のためにとにかくそれらをここにリストします。

  • Debianは/etc/profileおよび~/.profilelink )を推奨しています。
  • Ubuntuは/etc/environmentおよび~/.pam_environmentlink )を推奨しています。
  • Arch Linuxは、特に/etc/profileおよび/etc/environmentlink )について言及しています。

おまけ:debianでの/etc/environmentの使用や誤用について質問するテキスト( link 、最終更新2008)。

4
lesmana

次のスクリプト〜/ bin/agnostic_setenvを追加しました:

#!/bin/csh -f
set args = ($*)
if ($#args == 1) then
   echo "export $args[1]="
   exit 0
endif

if ($#args == 2) then
   if ("$args[1]" =~ *csh*) then 
      echo "setenv $args[2]"
      exit 0
   else
      echo "export $args[1]=$args[2]"
      exit 0
   endif
endif

echo "setenv $args[2] $args[3]"

そして〜/ .Perl-homedirで私は使用します:

eval `${HOME}/bin/agnostic_setenv $Shell Perl_HOMEDIR 0`

Agnostic_unsetenvの類似スクリプト:

#!/bin/csh -f
set args = ($*)
if ($#args == 1) then
   echo "export $args[1]"
   exit 0
endif

echo "unsetenv $args[2]"
exit 0
0
Kobi