POSIXシェルスクリプトから元の環境を復元できますか?

POSIXシェルスクリプトから元の環境を復元できますか?

シェルスクリプトが呼び出された元の環境に復元できますか?私は元の環境にアクセスする能力に依存するプログラムを書くことを意図していません。それが正しいかどうか知りたい。アクセシビリティ保証

新しい環境変数を生成し、PATH値を変更する単純なシェルスクリプトがあります。

#!/bin/sh

PATH=/usr/bin
NEW_VAR=new_var_value; export NEW_VAR

env

元の値を復元する方法はありますか、またはシェルスクリプトを実行するときに最初に存在しないようにPATH指示する方法はありますか?NEW_VAR

実行可能ファイルのパスがすべてシステムコールの初期に設定されているargvことはわかっていますが、実行可能ファイルが「どこ」または「どのように」保存されているかはわかりません。私の考えには、 を使用してパラメータベクトルと環境を操作する機能が実際におよび のデフォルト設定を変更しないようです。シェルの内部には、他のコマンド(たとえば)を呼び出すときに新しい呼び出しが正しいコマンドを使用することを確認するロジックのみがあります。envpexecv*(2)shiftexportunexportargvenvpexecv*(2)envpsome-command | LC_ALL=C sort

答え1

ほとんどのシステムでは、このコマンドを使用して、コマンドの実行中にps環境を表示できます。移植性がなく、すべてのシステムが安定した解析を可能にするわけではありませんが、必要なものが特定のUnixバリアントで動作するように初期環境の「興味深い」部分を抽出するのは簡単です。たとえば、Linux および *BSD では、次のようになります。

ps eww $$

またはSolarisおよびLinuxの場合:

cat /proc/$$/environ

またはSolarisおよびAIXの場合:

pargs -e $$

環境の古いコンテンツを非表示にする必要がある場合は、すべてのシェルプロセス(バックグラウンドサブシェルを含む)が終了していることを確認してください。リークしない方法でデータを渡すには、環境変数の代わりにパイプを使用します。

exec sh -c 'unset pw; pw=$PASSWORD; unset PASSWORD; printf %s "$pw" | exec theprogram'

ほとんどの(すべて最新の)Unixバリアントでは、プロセス環境は同じユーザーにのみ表示されます。通常、実行中のユーザーはパラメータのみを表示できますps。したがって、環境全体に機密データを渡すことは大丈夫です。これを排除するのは基本的なセキュリティではなく、強化の問題にすぎません。

答え2

POSIX自体はこれを行うための基本的な方法を提供しません。この目標にアプローチするいくつかの方法を考えることができます。

  1. 親環境(たとえば、/proc/pid/environLinux上の環境)に存在する環境を表示し、その環境に基づいて最初から環境を再充填します。これはうまくいかないかもしれません。
    • 親は必ずしも子供が始めた環境と同じである必要はありません。
    • 親項目が存在しなくなる可能性があります。
    • 子供が親の環境にアクセスできない可能性があります(例えば、権利放棄の文脈で)。
  2. スクリプトの先頭(たとえば、export -p開始部分を使用)に環境を保存し、後で復元します。/proc/self/environこれはうまくいきますが、それを復元するにはロジックを直接作成する必要があります。
  3. 新しい環境変数を設定するときは、以前の変数値を最初に保存する関数を使用してから、同じ関数を使用してそれらを復元することができます(または、たとえばに保存して手動で実行します$OLD_PATH)。これはうまくいきますが、面倒で忘れやすいです。たとえば、
$OLD_PATH=$PATH
# do something
$PATH=$OLD_PATH

答え3

変更する前に環境の状態を知りたい場合は、作業を実行する前に環境を保存してみてはいかがでしょうか?例えば、

#!/bin/sh
PATH_orig=$PATH; # save the original PATH
case ${NEW_VAR++} in
   ? ) echo 'Achtung: NEW_VAR is already in the original environment' ;;
   * ) echo 'NEW_VAR not found in the original environment' ;;
esac

OLD_ENV=$(export -p) # will save your original env in a source-able manner

### And now make your changes...
PATH=/usr/bin
NEW_VAR="foo"; export NEW_VAR

関連情報