su -를 통해 호출할 때 비대화형 bash 로그인 쉘이 /etc/profile을 무시하는 이유는 무엇입니까?

su -를 통해 호출할 때 비대화형 bash 로그인 쉘이 /etc/profile을 무시하는 이유는 무엇입니까?

저는 다음과 같이 특정 사용자로 시작하곤 했습니다 su.tmux

$ su - someuser -c tmux

그러나 이로 인해 다음과 같은 오류 메시지가 발생합니다.

tmux: need UTF-8 locale (LC_CTYPE) but have ANSI_X3.4-1968

이 오류는 LANG환경 변수가 설정되지 않았기 때문에 발생합니다. 새로운 것로그인 쉘이 via는 일반적으로 설정되지만 사용이 실제로 요청되고 로그인 쉘을 생성하는 것처럼 보이 더라도 /etc/profilethrough 호출은 su사용되지 않습니다 ./etc/profilesu -

쉘을 사용하는 사용자에게는 someuser작동하지 않습니다 bash. 그러나 dash또는 와 같은 다른 쉘과 함께 사용할 수 있습니다 zsh. 대화형 bash로그인 셸도 예상대로 작동합니다.

전화할 때 왜 bash무시 되나요?/etc/profile비대화형으로통과하다 su -?

내 연구(아래)에 따르면 문제는 ( 및 /또는 ) 명령줄 옵션 에 하이픈을 사용하는 것이 bash다른 쉘과 비교하여 로그인 쉘을 요청할 때 다르게 동작한다는 것입니다.$0su-l--login


연구

(약간 길지만 조사 내용을 문서로 기록하고 싶었습니다.)

man su-c인수가 사용됨 을 설명합니다.

-c 옵션을 사용하여 명령을 셸에 전달합니다.

그리고 -논쟁

쉘을 로그인 쉘로 시작하십시오. 환경은 실제 로그인과 유사합니다.

따라서 실제 로그인과 유사한 환경의 로그인 쉘에서 실행되어야 한다 su - someuser -c cmd.cmdsomeuser

데모를 위해 테스트 명령을 사용할 수 있습니다.

$ testcmd='shopt -q login_shell || echo -n non-; echo login shell $0 $LANG'

su로그인 및 비로그인 쉘에 대해 다음을 시도하십시오.

$ su - someuser -c "$testcmd"
login shell -bash
$ su someuser -c "$testcmd"
non-login shell bash en_GB.UTF-8

로그인 쉘 시작시 환경이 구성되지 않습니다( 사용하지 않기 LANG때문에 설정하지 않습니다 ). /etc/profile환경은 비로그인 셸을 시작할 때 상속되므로 값은 LANG미리 지워서 표시된 것처럼 시작 셸의 환경에서 가져옵니다.

$ LANG= su someuser -c "$testcmd"
non-login shell bash

위의 예에는 쉘 someuser이 있습니다 bash. (단순한 심볼릭 링크임) 을 사용하여 sh동일한 결과를 얻을 수 있습니다 bash. 사용 하면 예상대로 작동합니다 zsh.

$ ztestcmd='[[ -o login ]] || echo -n non-; echo login shell $LANG'
$ LANG= su - someuser -s /bin/zsh -c "$ztestcmd"
Password: 
login shell -zsh en_GB.UTF-8
$ LANG= su someuser -s /bin/zsh -c "$ztestcmd"
Password: 
non-login shell zsh
su someuser -s /bin/zsh -c "$ztestcmd"
Password: 
non-login shell zsh en_GB.UTF-8

에서도 작동합니다 . 따라서 문제는 더 깊이 파고드는 dash것 같습니다 .bashbash

대화형 셸을 시작하면 예상대로 작동합니다.

$ su - someuser
$ LANG= shopt -q login_shell || echo -n non-; echo login shell $0 $LANG
login shell -bash en_GB.UTF-8

bash따라서 대화형 실행 과 비대화형 실행 su은 다르게 동작합니다. bash직접 창업은 어떻습니까 ?

$ LANG= bash -c "$testcmd"
non-login shell bash
$ LANG= bash -l -c "$testcmd"
login shell bash en_GB.UTF-8

이것은 예상대로 작동합니다.

GNU 배쉬 매뉴얼상태저것

Bash가 대화형 로그인 셸 또는 options 가 포함된 비대화형 셸로 호출되면 --login먼저 파일에서 명령을 읽고 실행합니다./etc/profile

man 에 따르면 su해당 -옵션은 사용되지 않지만 --login대신

-쉘을 로그인 쉘로 만들 려면 쉘의 argv[0]을 설정하십시오.

다음을 증명할 수 있습니다:

$ su - someuser -c 'echo $0'
Password: 
-bash

우리는 이것을 직접 테스트할 수 있습니다. 선행 하이픈은 $0로그인 쉘을 제공합니다:

$ (LANG= exec -a '-' bash -c "$testcmd")
login shell -

그래서선두 하이픈$0로그인 쉘을 생성하지만bash 실행되지 않음/etc/profile이는 이러한 방식으로 호출될 때 해당 옵션의 동작과 일치하지 않으며 -l다른 쉘(예: zsh또는 ) 과도 일치하지 않습니다 dash. 또한 상호 작용이 시작될 때 자체 동작과도 일치하지 않습니다.

$ (LANG= exec -a '-' bash)
$ shopt -q login_shell || echo -n non-; echo login shell $0 $LANG
login shell - en_GB.UTF-8

불행하게도 이는 위에서 발췌한 문서와 충돌하지 않습니다. 왜냐하면 의 사용을 정의하지 않기 때문입니다 -l.

답변1

주석에 적힌 대로 정확하게 작동합니다.

다시 생각한다문서:

Bash가 대화형 로그인 셸 또는 options 가 포함된 비대화형 셸로 호출되면 --login먼저 파일에서 명령을 읽고 실행합니다./etc/profile

/etc/profile읽기 및 실행으로 올바르게 해석합니다.대화형 로그인 셸또는--login옵션이 있는 비대화형 셸. $0하이픈으로 시작하는 비대화형 로그인 쉘 이라고는 말하지 않습니다 .

그러나 이 동작은 의도적으로 설계된 동작이며 컴파일 타임 옵션의 주석 처리를 제거하여 컴파일 타임에 변경할 수 있습니다.구성-top.h:

/* Define this to make non-interactive shells begun with argv[0][0] == '-'
run the startup files when not in posix mode. */
/* #define NON_INTERACTIVE_LOGIN_SHELLS */

그러나 실제로는 그렇지 않은데 왜 이 동작이 구현되는지에 대한 의문이 제기됩니다.IMHO, 특히 다른 쉘처럼 구현되지 않은 경우 합리적으로 작동할 것으로 기대하는 방법입니다.

즉, 내 생각엔 아닌 것 같아POSIX 표준 쉘정의로그인 쉘그래서 설명이 가능한 것 같아요.

원래 문제에 적용되는 해결 방법은 다음과 같습니다 bash.

$ su - someuser -c 'bash -l -c tmux'

관련 정보