su-で環境変数を保存する方法は?

su-で環境変数を保存する方法は?

リモートシステムでSSHを使用する場合LC_ALL="en_US.UTF-8"(ssh_configを介してsendEnv)エクスポートします。この変数はsu - user123シェルにログインするとリセットされます。LC_xxxリモートシステムで別のユーザーとしてログインシェルを実行するときにこの変数(および他の変数)を保存する方法はありますか?

シェルまたはターゲットユーザーのエントリを実行した後に手動で変数をエクスポートできることを知っていますが、~/.bashrc可能であれば送信された元の値を維持したいと思いますssh。ありがとうございます。

編集する:ユーザー環境の特定の部分を初期化する必要があるためsu -。私はただ保存したいLC_xxx

答え1

su私はandの実装(そして最終的にcoreutilsでは削除されましたが、GNUの実装)に環境を保存するオプションがあることがわかりました。util-linuxshadow-utilscoreutilssu

-m, -p, --preserve-environment
           Preserve the current environment, except for:
...

他のシステムには-m(BSDなど)-p両方があってもなくてもよい。 Busybox におよびがsuあります。おもちゃ箱(Android)はい。-m-psu-p

このように、ターゲットユーザーのシェル初期化ファイルはログインシェルのように実行されますが、すべての変数をテストできますが、すでにLC_xxx有効な値が含まれている場合は初期化されません。

編集する:/etc/profile.d/ssh_lc_vars.shエクスポートしたLC_xxx変数を処理するスクリプトを追加することで、この機能をシステム全体に適用できます。また、初期化されていない環境変数を使用していくつかの追加操作を実行する必要がありましたが、機能しませんでしたsu -ml userxxx。完全なスクリプトを含めることができなかったため、次の例があります。誰かが改善してくれればもっといいようです。

...
# clean up client-side variable for junk
lc_sanitize()
{
   arg="$1"
   # first, strip underscores
   clean="${arg//_/}"

   # next, replace spaces with underscores
   clean="${clean// /_}"

   # now, clean out anything that's not alphanumeric, underscore, hypen or dot
   ret="${clean//[^a-zA-Z0-9_\.-]/}"

   # return santized value to caller
   echo "$ret"
}

# LC_MY_LANG comes from an ssh client environment. If empty,
# this isn't a remote ssh user, but set it locally so this user
# can connect elsewhere where this script runs
if [ -z "$LC_MY_LANG" ]; then
   # force an LC_xxx setting for the environment
    LC_MY_LANG="en-US.utf-8"
else
    # otherwise, use the LC_xxxx variable from the ssh environment
    # 2017-01-30 - when using "su --preserve-environment  userxxx --login" be sure to fixup needed variables
    # shorthand: su -ml user111
    export USER=`whoami`
    export LOGNAME=${USER}
    export HOME=$( getent passwd "$USER" | cut -d: -f6 )
    cd ${HOME}

    # sanitize variable which was set client-side and log it
    u_sanitized=$(lc_sanitize "$LC_MY_LANG")
    echo "Notice: LC_MY_LANG sanitized to $u_sanitized from $SSH_CLIENT as user $USER" | logger -p auth.info
fi

# mark variable read-only so user cannot change it then export it
readonly LC_MY_LANG
# set terminal to LC_MY_LANG
export LC_LANG=${LC_MY_LANG}
export LC_MY_LANG
...

答え2

-suの引数をスキップします。

   -, -l, --login
       Provide an environment similar to what the user would expect had
       the user logged in directly.

答え3

以下は私にとって効果的でした。これは、環境変数を設定するコマンドを実行するために使用される追加のシェルを呼び出すのと同じです。

# LC_ALL is set in parent shell
> export LC_ALL=C
> env | grep LC_ALL
LC_ALL=C

# Verify that since we use `su -` the LC_ALL is not preserved
> su - user123 -c '/bin/bash'
user123@026aedc05a97:~$ env | grep LC_ALL
user123@026aedc05a97:~$ exit

# Pass the variable to the extra shell explicitly
> su - user123 -c 'LC_ALL='$LC_ALL' /bin/bash'
# The variable is now set
user123@026aedc05a97:~$ env | grep LC_ALL
LC_ALL=C
user123@026aedc05a97:~$

関連情報