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있습니다 . 장난감 상자 (안드로이드) 예 .-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:~$

관련 정보