저는 다음과 같이 특정 사용자로 시작하곤 했습니다 su
.tmux
$ su - someuser -c tmux
그러나 이로 인해 다음과 같은 오류 메시지가 발생합니다.
tmux: need UTF-8 locale (LC_CTYPE) but have ANSI_X3.4-1968
이 오류는 LANG
환경 변수가 설정되지 않았기 때문에 발생합니다. 새로운 것로그인 쉘이 via는 일반적으로 설정되지만 사용이 실제로 요청되고 로그인 쉘을 생성하는 것처럼 보이 더라도 /etc/profile
through 호출은 su
사용되지 않습니다 ./etc/profile
su -
쉘을 사용하는 사용자에게는 someuser
작동하지 않습니다 bash
. 그러나 dash
또는 와 같은 다른 쉘과 함께 사용할 수 있습니다 zsh
. 대화형 bash
로그인 셸도 예상대로 작동합니다.
전화할 때 왜 bash
무시 되나요?/etc/profile
비대화형으로통과하다 su -
?
내 연구(아래)에 따르면 문제는 ( 및 /또는 ) 명령줄 옵션 에 하이픈을 사용하는 것이 bash
다른 쉘과 비교하여 로그인 쉘을 요청할 때 다르게 동작한다는 것입니다.$0
su
-l
--login
연구
(약간 길지만 조사 내용을 문서로 기록하고 싶었습니다.)
man su
이 -c
인수가 사용됨 을 설명합니다.
-c 옵션을 사용하여 명령을 셸에 전달합니다.
그리고 -
논쟁
쉘을 로그인 쉘로 시작하십시오. 환경은 실제 로그인과 유사합니다.
따라서 실제 로그인과 유사한 환경의 로그인 쉘에서 실행되어야 한다 su - someuser -c cmd
.cmd
someuser
데모를 위해 테스트 명령을 사용할 수 있습니다.
$ 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
것 같습니다 .bash
bash
대화형 셸을 시작하면 예상대로 작동합니다.
$ 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'