sudo como outro usuário com seu ambiente

56

$ whoami
admin
$ sudo -S -u otheruser whoami
otheruser
$ sudo -S -u otheruser /bin/bash -l -c 'echo $HOME'
/home/admin

Por que não está $HOMEsendo definido como o /home/otheruserbash é chamado como um shell de logon?

Especificamente, /home/otheruser/.bashrcnão está sendo originado. Além disso, /home/otheruser/.profilenão está sendo fornecido. - ( /home/otheruser/.bash_profilenão existe)

EDIT: o problema exato é realmente https://stackoverflow.com/questions/27738224/mkvirtualenv-with-fabric-as-another-user-fails

user80551
fonte
Uma solução para esta pergunta também resolverá a outra questão. Você pode excluir a outra pergunta nessa situação.
Pavel Šimerda

Respostas:

83

Para chamar um shell de login usando sudoapenas use -i. Quando o comando não for especificado, você receberá um prompt de shell de login, caso contrário, obterá a saída do seu comando.

Exemplo (shell de login):

sudo -i

Exemplo (com um usuário especificado):

sudo -i -u user

Exemplo (com um comando):

sudo -i -u user whoami

Exemplo (usuário de impressão $HOME):

sudo -i -u user echo \$HOME

Nota: O caractere de barra invertida garante que o cifrão alcance o shell do usuário de destino e não seja interpretado no shell do usuário que está chamando.

Acabei de verificar o último exemplo com strace, que diz exatamente o que está acontecendo. A saída abaixo mostra que o shell está sendo chamado com --logine com o comando especificado, assim como na sua chamada explícita para o bash, mas, além disso, o sudo pode fazer seu próprio trabalho, como definir o $HOME.

# strace -f -e process sudo -S -i -u user echo \$HOME
execve("/usr/bin/sudo", ["sudo", "-S", "-i", "-u", "user", "echo", "$HOME"], [/* 42 vars */]) = 0
...
[pid 12270] execve("/bin/bash", ["-bash", "--login", "-c", "echo \\$HOME"], [/* 16 vars */]) = 0
...

Notei que você está usando -Se geralmente não acho que seja uma boa técnica. Se você deseja executar comandos como um usuário diferente sem executar autenticação no teclado, pode usar o SSH. Ele funciona para localhostoutros hosts e fornece autenticação de chave pública que funciona sem nenhuma entrada interativa.

ssh user@localhost echo \$HOME

Nota: Você não precisa de opções especiais com o SSH, pois o servidor SSH sempre cria um shell de login para ser acessado pelo cliente SSH.

Pavel Šimerda
fonte
2
sudo -i -u user echo \$HOMEnão funciona para mim. Saída: $HOME. strace fornece a mesma saída que a sua. Qual é o problema?
23415 John_West
Não faço ideia, ainda funciona para mim, eu precisaria vê-lo ou talvez até tocar o sistema.
Pavel Šimerda
10

Você está dando muito crédito ao Bash. Todo "shell de login" significa para o Bash quais arquivos são originados na inicialização e no desligamento. A $HOMEvariável não aparece nela.

Os documentos do Bash explicam um pouco mais o que significa shell de login: https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html#Bash-Startup-Files

De fato, Bash não faz nada para definir $HOME. $HOMEé definido pelo que chama o shell (login, ssh, etc.), e o shell o herda. O que quer que tenha iniciado seu shell como administrador definido $HOMEe depois executado bash, sudopor padrão, não altera o ambiente, a menos que seja solicitado ou configurado para fazê-lo, assim bashcomo outro usuário o herdou do seu shell.

Se você deseja sudolidar com mais do ambiente da maneira que espera, veja o -iswitch sudo. Experimentar:

sudo -S -u otheruser -i /bin/bash -l -c 'echo $HOME'

A página de manual do sudo descreve mais detalhadamente, embora não muito bem, eu acho: http://linux.die.net/man/8/sudo

Jeff Snider
fonte
4
$ HOME não é definido pelo bash - Obrigado, eu não sabia disso.
user80551
Procure traços na minha resposta. Isso mostra que você não precisa criar uma /bin/bash -l -c 'echo $HOME'linha de comando quando estiver usando -i.
Pavel Šimerda
11
Essa sudosintaxe gerou um erro na minha máquina. ( suusa a -copção, mas acho que sudonão.) Tive melhor sorte com:HomeDir=$( sudo -u "$1" -H -s echo "\$HOME" )
palswim 13/10/16
sim, @palswim está certo. Não tenho certeza -S(eu não precisava, então deixei de fora), mas -cnão funciona aqui, você precisa -s.
polynomial_donut