いくつかの環境変数を設定し、引数として送信したプログラムを起動するためのシェルスクリプトがあります。
export PATH=$HOME/local/bin:$PATH
export LD_LIBRARY_PATH=$HOME/local/lib:$LD_LIBRARY_PATH
export TESTER="MY TEST VAR"
$@
たとえば、これを使用してbash
を呼び出すと、次のように機能します。
kjfletch@flatbed:~$ envrun.sh bash
kjfletch@flatbed:~$ echo $LD_LIBRARY_PATH
/home/kjfletch/local/lib:
kjfletch@flatbed:~$ echo $TESTER
MY TEST VAR
これを使用して端末(xterm
、aterm
、...)を呼び出すと、my LD_LIBRARY_PATH
設定が解除されます:
kjfletch@flatbed:~$ echo $LD_LIBRARY_PATH
kjfletch@flatbed:~$ echo $TESTER
MY TEST VAR
なぜこれが起こるのですか?どうすればこれを止めることができますか? (私はDebian 5.0を実行しています)
私の端末はログインとしてbashを呼び出していません:
kjfletch@flatbed:~$ echo $0
bash
ぼくの LD_LIBRARY_PATH
はbashスタートアップファイルのいずれにも表示されません(.bash_historyと〜/ .profileは別として存在しません):
kjfletch@flatbed:~$ grep "LD" ~/.bash*
kjfletch@flatbed:~$ grep "LD" /etc/bash.bashrc
kjfletch@flatbed:~$ grep "LD" /etc/profile
ターミナルバイナリは、グループsetgid
に対してutmp
である可能性が高いです。 setuidおよびsetgidバイナリは、セキュリティ上の理由から_LD_LIBRARY_PATH
_の設定を解除します。 ld.so(8)
を参照してください:
プログラムに必要な共有ライブラリを次の順序で検索します
- 環境変数_
LD_LIBRARY_PATH
_(a.outプログラムの場合は_LD_AOUT_LIBRARY_PATH
_)を使用します。実行可能ファイルがsetuid/setgidバイナリである場合を除き、その場合は無視されます。
ターミナル(xterm、atermなど)で、シェルがどのように呼び出されたかを確認します。echo $0
を呼び出すと、ログインシェルには「-bash」が表示され、非ログインシェルには「bash」が表示されます。
$ echo $0
-bash
$ bash
$ echo $0
bash
ログインbashシェルは、以下を順番に読み取ります。
これらのファイルのいずれかが存在するかどうか、およびそれらが変数をリセットするかどうかを確認してください。また、これらのファイルに含まれるすべてのファイルを追跡する必要があります。
Bashがログインシェルとして呼び出されない場合でも、インタラクティブシェルであると判断された場合は、以下のファイルを読み取ります。
呼び出されているbashシェルの種類を判別する簡単な方法は、.bash_profileと.bashrcを定義し、それぞれ「ログインシェル」と「インタラクティブシェル」をエコーすることです。
呼び出されているシェルの種類がわかったら、ホームディレクトリの.bashrcファイルまたは.bash_profileファイルにスクリプトを追加するオプションがあります。または、LD_LIBRARY_PATHのリセットを無効にすることもできます。
.bashrcまたは.bash_profileが以下のようなガードで保護されている場合は、スクリプトの外部でスクリプトを呼び出す必要がある場合があることに注意してください。
if [ "X$BASH_SOURCED" != "XYES" ]; then
export BASH_SOURCED=YES
fi
このようなガードは通常、セッションでスクリプトが複数回ソースされるのを防ぐために配置されます。
編集:変数がリセットされている場所を追跡するのが面倒で、たとえば/ etc/profileまたは/etc/bash.bashrcにアクセスできる場合は、一時的に「set-スクリプトの上部にあるx "で、実行されるすべてのコマンドを確認できます。出力はかなり冗長になるため、最初にシェルで「set -x」を実行し、いくつかのコマンドを実行して、何が期待できるかを理解します。
bashは、起動方法に応じて異なる起動スクリプトを使用します。それを開始するには7つの異なる方法がありますが、最も重要なのはログインシェルと非ログインインタラクティブシェルです。
詳細については、 bashマニュアル を確認してください。/etc/profileまたは〜/ .bash_profileがLD_LIBRARY_PATH変数をリセットするために何かをしているのではないかと思います。
編集:bashにLD_LIBRARY_PATHを設定解除する起動スクリプトがないことを示すために合理的にできることはすべて行ったと思います。大きな銃を引き出す時が来ました。
次のコマンドは、bashからxtermまで、各プロセスの起動時に環境全体を表示します。その他の関連するものはすべて表示されます。おそらく大量の出力が得られるため、出力をファイルに保存することをお勧めします。 。
strace -v -f -e trace=process -o strace_output.txt envrun.sh xterm
これで、ファイルstrace_output.txtに、スクリプトによって行われた各システムコールとすべての子プロセスが表示され、LD_LIBRARY_PATHが最後にあったプロセスを確認できます。削除されました。
(この質問は非常に古いですが、私は同じ問題に遭遇し、事後性の解決策を文書化しています:)
GNU screen(ターミナルマルチプレクサ)でこの問題が発生しましたが、通常のターミナルでも発生する可能性があります。私の場合、Teddyは正しかったので、screenはsetguidを設定しました。
$ ls -l /usr/bin/screen
-rwxr-sr-x 1 root 84 361016 Mar 30 2011 /usr/bin/screen
^
私の解決策は、実行前にLD_LIBRARY_PATHを保存し、後で復元することでした。そこで、次の内容でラッパー〜/ bin/screen(PATHに〜/ binを配置)を作成しました。
#!/bin/bash
# somehow, screen resets LD_LIBRARY_PATH.
# save it here, and restore it in .bashrc
export PRESERVE_LD_LIBRARY_PATH="$LD_LIBRARY_PATH"
/usr/bin/screen "$@"
次に、chmod +x ~/bin/screen
で実行可能にしました。ラッパーを取得するために、新しいシェルを開く必要がある場合があります。
次に、以下を〜/ .bashrcに追加しました。ログイン時(通常は起動時、またはssh経由でログインするとき)にのみソースされる〜/ .bash_profileとは異なり、〜/ .bashrcはbashを開始するたびにソースされることに注意してください。
if [[ "$PRESERVE_LD_LIBRARY_PATH" != "" ]]; then
export LD_LIBRARY_PATH="$PRESERVE_LD_LIBRARY_PATH"
#echo "restored LD_LIBRARY_PATH"
export -n PRESERVE_LD_LIBRARY_PATH
fi
これで、screen(またはaterm、xterm、...上記で置き換えてください)は、必要に応じて$ LD_LIBRARY_PATHを保持する必要があります。
ほとんどのウィンドウシステムは、ターミナルウィンドウを起動するときにログインプロセスを再作成します。これは主に、ターミナルウィンドウが起動シェルではなくウィンドウマネージャの子になるためです。
したがって、新しいウィンドウに表示する場合は、.bash_profileまたは.bashrcに配置します。
もう1つの方法は、xterm(たとえば)に引数を渡して起動スクリプトを実行することです。そのスクリプトの最後で終了しないでください..。
この変数を定義する.bashrc(または同等の)ファイルがホームディレクトリにあるようです。詳細はわかりませんが。
編集わかりました。bashの開始は機能するので、推測していますnot。bashrc。しかし、xtermまたはatermを起動すると、たまたま同じ方法で実行される他の構成ファイルがあるかもしれません。