Eu configurei sudopara executar sem uma senha, mas quando tento ssh 'sudo Foo', ainda recebo a mensagem de erro sudo: sorry, you must have a tty to run sudo.
Por que isso acontece e como posso solucionar isso?
Eu configurei sudopara executar sem uma senha, mas quando tento ssh 'sudo Foo', ainda recebo a mensagem de erro sudo: sorry, you must have a tty to run sudo.
Por que isso acontece e como posso solucionar isso?
Respostas:
Provavelmente porque seu /etc/sudoersarquivo (ou qualquer outro arquivo incluído) possui:
Defaults requiretty
... o que sudoexige um TTY. Sabe-se que os sistemas Red Hat (RHEL, Fedora ...) exigem um TTY no sudoersarquivo padrão . Isso não oferece nenhum benefício real de segurança e pode ser removido com segurança.
A Red Hat reconheceu o problema e ele será removido em versões futuras.
Se alterar a configuração do servidor não for uma opção, como uma solução alternativa para essa configuração incorreta, você poderá usar as opções -tou -ttnas sshquais gera um pseudo-terminal no lado remoto, mas cuidado com o fato de ter vários efeitos
-ttdestina-se ao uso interativo. Ele coloca o terminal local no rawmodo para que você interaja com o terminal remoto. Isso significa que, se a sshE / S não for de / para um terminal, isso terá efeitos colaterais. Por exemplo, todas as entradas serão eco de volta, caracteres especiais terminais ( ^?, ^C, ^U) irá causar um processamento especial; na saída, LFs serão convertidos em CRLFs ... (consulte esta resposta em Por que este arquivo binário está sendo alterado? para obter mais detalhes.
Para minimizar o impacto, você pode invocá-lo como:
ssh -tt host 'stty raw -echo; sudo ...' < <(cat)
O < <(cat)evitará a configuração do terminal local (se houver) no rawmodo. E estamos usando stty raw -echopara definir a disciplina de linha do terminal remoto como passagem (efetivamente, ele se comporta como o tubo que seria usado em vez de um pseudo-terminal sem -tt, embora isso só se aplique após a execução desse comando, então você precisa atrasar o envio de algo para entrada até que isso aconteça).
Observe que, como a saída do comando remoto será direcionada para um terminal, isso ainda afetará seu buffer (que será baseado em linhas para muitas aplicações) e a eficiência da largura de banda desde que TCP_NODELAYativada. Também com -tt, sshdefine o IPQoS lowdelaycomo oposto a throughput. Você pode solucionar os dois com:
ssh -o IPQoS=throughput -tt host 'stty raw -echo; sudo cmd | cat' < <(cat)
Além disso, observe que isso significa que o comando remoto não pode detectar o final do arquivo em seu stdin e o stdout e o stderr do comando remoto são mesclados em um único fluxo.
Então, não é tão bom assim, afinal.
Se você um tem uma maneira de gerar um pseudo-terminal no host remoto (como com expect, zsh, socat, perl's IO::Pty...), então seria melhor usar isso para criar o pseudo-terminal para anexar sudoa (mas não para E / S) e use sshsem -t.
Por exemplo, com expect:
ssh host 'expect -c "spawn -noecho sh -c {
exec sudo cmd >&4 2>&5 <&6 4>&- 5>&- 6<&-}
exit [lindex [wait] 3]" 4>&1 5>&2 6<&0'
Ou com script(assumindo aqui a implementação de util-linux):
ssh host 'SHELL=/bin/sh script -qec "
sudo cmd <&3 >&4 2>&5 3<&- 4>&- 5>&-
" /dev/null 3<&0 4>&1 5>&2'
(assumindo (para ambos) que o shell de login do usuário remoto é semelhante ao Bourne).
Por padrão, SUDO está configurado para exigir um TTY. Ou seja, espera-se que o SUDO seja executado a partir de um shell de login. Você pode anular esse requisito adicionando a -topção à sua chamada SSH:
ssh -t someserver sudo somecommand
A -talocação de forças de uma pseudo-tty.
Se você deseja executar isso globalmente, modifique /etc/sudoerspara especificar !requiretty. Isso pode ser feito por usuário, grupo ou nível abrangente.
Use o -tsinalizador sshpara forçar a alocação de tty.
$ ssh luci tty
not a tty
$ ssh luci -t tty
/dev/ttys003
$
-tpara forçar a alocação quandoPseudo-terminal will not be allocated because stdin is not a terminal.
Encontrei esse problema usando o Docker e o Centos 7. Acabei fazendo o seguinte:
yum install -y sudo
sed -i -e 's/Defaults requiretty.*/ #Defaults requiretty/g' /etc/sudoers
Encontrei este hack em https://hub.docker.com/r/liubin/fluentd-agent/~/dockerfile
Uma alternativa interessante é executar o FreeIPA ou o IdM para gerenciar centralmente seus usuários e regras de sudoer. Você pode criar regras de sudo e atribuir a opção
! requiretty
na regra. O comando será executado conforme o esperado. Você também terá os benefícios de gerenciar todos os servidores e usuários a partir de um único conjunto de configurações.
Eu tive o mesmo problema. No meu caso, a solução foram duas linhas
myscript=$(cat ssh_test.sh)
ssh -t user@host "$myscript"
Explicação:
Coloque os comandos que você deseja executar (incluindo comandos sudo) em um script, por exemplo, "ssh_test.sh".
Leia o script inteiro em uma variável chamada "myscript".
Invoque ssh com apenas um -t e forneça a variável em vez de um comando.
Antes disso, tive problemas ao usar combinações de leitura de stdin e heredocs
requirettyem seus sudoers padrão. Ele será corrigido em versões mais recentes