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


31

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

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


2
これは、ディストリビューションとは関係がなく、シェルとは関係ありません。ただし、移植可能な方法があるかどうかはわかりません。
ジョセフR.

うーん 素晴らしい
-strugee

回答:


29

残念ながら、環境変数を設定するための完全に移植可能な場所はありません。最も近い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が'or "で始まり、別の同じ引用符が含まれている場合、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は、対話式であってもログインシェルを読み取りません。これらの癖を二度と覚える必要がないようにするに~/.bash_profileは、次の2行でを作成します。

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

bashを使用して環境変数を設定するために使用する必要があるセットアップファイルも参照してください

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

Zshはを読み取りますが~/.zprofile~/.zloginではありません~/.profile。Zshの構文はshとは異なりますが~/.profile、shエミュレーションモードで読み取ることができます。あなたはこれをあなたのために使うことができます~/.zprofile

emulate sh -c '. ~/.profile'

〜/ .profileにヒットしないZshも参照してください。

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

ここで/bin/shは、ログインシェルとして使用したり、お気に入りのシェル(魚など)を対話型シェルとしてのみ使用したりする以外に、できることはあまりありません。それは私がzshでやっていることです。から別のシェルを呼び出す例については、上記を参照してください~/.profile

リモートコマンド

インタラクティブシェルを経由せずにリモートコマンドを呼び出す場合、すべてのシェルがスタートアップファイルを読み取るわけではありません。

ENVあなたがそれを渡すことに成功した場合、Kshは変数で指定されたファイルを読み取ります。

Bash ~/.bashrc、対話型ではなく(!)、その親プロセスがrshdor と呼ばれる場合に読み取りますsshd。あなたを開始することができるように~/.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は、起動スクリプトから明示的にソースを取得するか、ログインシェルを実行することにより、ます。

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

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


何をcase $- in *i*)するの?
qodeninja 14

2
@qodeninja パターンと一致する場合、つまり、containsが含まれる場合、つまりシェルが対話型である場合、次の命令を(一致;;またはになるまでesac)実行します。$-*i*$-i
ジル 'SO-悪であるのをやめる' 14

$-現在設定されているシェルオプションの文字列です。(などset -x)。 i対話型シェルを意味します。
ピーター・コーデス

たとえば~/.config/env、エミュレーションなしでも、一般的なファイルをソースにできませんか?
ケビンSuttle

1
@StéphaneChazelasそれは純粋主義者の見解です。私.profileはかなり古いBourneシェルに準拠していますが、気にしない人もいます。自分のファイルに対してsh = bashであると想定している人に対しては何もありません#!/bin/sh。bash機能を使用するスクリプトを公開するかどうかだけが気になります。
ジル 'SO-悪であるのをやめる'

4

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

最も一般的なデファクトスタンダードがあると思われる/etc/profile~/.profile。第二の最も一般的にはあると思われる/etc/environment~/.pam_environment

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

  • Debianはお勧め/etc/profileします~/.profileリンク)。
  • Ubuntuはお勧め/etc/environmentします~/.pam_environmentリンク)。
  • アーチLinuxは、とりわけ、言及し、/etc/profileおよび/etc/environmentリンク)。

ボーナス:/etc/environmentdebianでの使用や誤用を疑うテキスト(link、最終更新2008年)。


使用するファイルに関係なく、異なるシェル間で互換性のない構文にぶつかります。
ジョセフR.

1
@JosephR。ほとんどのシェルは後方互換性を維持していませんshか?POSIXに固執している限り、私はあなたが大丈夫だと思っていただろう
...-evilsoup

1
知っていると、変数を割り当てcshたり、POSIXの方法で友達にしたりすることはできません(setまたはのようなものが必要ですsetenv
ジョセフR.

0

次のスクリプト〜/ 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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.