Estou usando su para iniciar tmux como um usuário específico, assim:
$ su - someuser -c tmux
No entanto, isso resulta em uma mensagem de erro:
tmux: need UTF-8 locale (LC_CTYPE) but have ANSI_X3.4-1968
O erro ocorre porque a variável de ambiente LANG não está definida. Um novo login shell normalmente define isso via /etc/profile , mas a invocação através de su não usa /etc/profile , embora o uso de su - solicite e pareça produzir um shell de login. / p>
O usuário someuser para o qual isso não funciona tem o shell bash . No entanto, ele funciona com outros shells, como dash ou zsh . Um shell de login bash interativo também funciona como esperado.
Por que bash ignora /etc/profile quando é invocado não interativamente por meio de su - ?
Minha pesquisa (abaixo) indicaria que o problema é que bash , em contraste com outros shells, se comporta de maneira diferente quando um shell de login é solicitado com um hífen principal em $0 (o que su faz) versus -l (ou --login ) opção de linha de comando.
Pesquisa
(isso é um pouco detalhado, mas eu queria registrar minhas investigações)
man su explica que o argumento -c é usado para
Pass command to the shell with the -c option.
e o argumento -
Start the shell as a login shell with an environment similar to a real login
Portanto, su - someuser -c cmd deve executar cmd em um shell de login para someuser com um ambiente semelhante a um login real.
Um comando de teste é útil para demonstrar:
$ testcmd='shopt -q login_shell || echo -n non-; echo login shell $0 $LANG'
Tentando isso com su para shells de login e não-login:
$ su - someuser -c "$testcmd"
login shell -bash
$ su someuser -c "$testcmd"
non-login shell bash en_GB.UTF-8
Quando um shell de login é iniciado, o ambiente não está configurado ( LANG não está definido porque /etc/profile não é usado). O ambiente é herdado de quando um shell não-login é lançado, então o valor de LANG é aquele do shell de inicialização, já que a limpeza é demonstrada de antemão:
$ LANG= su someuser -c "$testcmd"
non-login shell bash
Nos exemplos acima, someuser tem o shell bash . Os mesmos resultados são obtidos com sh (que é apenas um link simbólico para bash ). Se zsh for usado, as coisas funcionam conforme o esperado:
$ 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
Também funciona com dash . Portanto, o problema parece estar com bash . Investigando bash ...
Funciona como esperado se um shell interativo for lançado:
$ su - someuser
$ LANG= shopt -q login_shell || echo -n non-; echo login shell $0 $LANG
login shell -bash en_GB.UTF-8
Portanto, bash interativa e não interativa lançada por meio de su se comporta de maneira diferente. Que tal lançar bash diretamente?
$ LANG= bash -c "$testcmd"
non-login shell bash
$ LANG= bash -l -c "$testcmd"
login shell bash en_GB.UTF-8
Isso funciona como esperado.
O Manual GNU Bash afirma que
When Bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile
De acordo com o homem su , sua opção - não usa --login , mas sim
sets argv[0] of the shell to - in order to make the shell a login shell
O que pode ser comprovado:
$ su - someuser -c 'echo $0'
Password:
-bash
Podemos testar a nós mesmos que um hífen principal em $0 fornece um shell de login:
$ (LANG= exec -a '-' bash -c "$testcmd")
login shell -
Assim, um hífen principal em $0 produz um shell de login, mas bash não executa /etc/profile quando invocado dessa maneira, o que é inconsistente com o comportamento de sua opção -l e também com outros shells, como zsh ou dash . Também é inconsistente com seu próprio comportamento quando lançado interativamente:
$ (LANG= exec -a '-' bash)
$ shopt -q login_shell || echo -n non-; echo login shell $0 $LANG
login shell - en_GB.UTF-8
Infelizmente, isso não está de acordo com a documentação citada acima, porque isso não define o comportamento de um shell de login não interativo que não foi lançado com -l .