Isso é provavelmente porque o arquivo /etc/sudoers
(ou qualquer arquivo incluído) possui:
Defaults requiretty
... o que faz com que sudo
exija um TTY. Sistemas Red Hat (RHEL, Fedora ...) são conhecidos por exigirem um TTY no arquivo sudoers
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 a alteração da configuração do servidor não for uma opção, como alternativa para essa configuração incorreta, você pode usar as opções -t
ou -tt
para ssh
, o que gera um pseudo-terminal no lado remoto, mas tenha cuidado com os vários efeitos colaterais.
-tt
destina-se ao uso interativo. Ele coloca o terminal local no modo raw
para que você interaja com o terminal remoto. Isso significa que se ssh
I / O não for de / para um terminal, isso terá efeitos colaterais. Por exemplo, toda a entrada será ecoada de volta, caracteres de terminal especiais ( ^?
, ^C
, ^U
) causarão processamento especial; na saída, LF
s será convertido em CRLF
s ... (consulte esta resposta para Por que este arquivo binário está sendo alterado? para mais detalhes.
Para minimizar o impacto, você poderia invocá-lo como:
ssh -tt host 'stty raw -echo; sudo ...' < <(cat)
O < <(cat)
evitará a configuração do terminal local (se houver) no modo raw
. E estamos usando stty raw -echo
para definir a disciplina de linha do terminal remoto como passagem (efetivamente para que se comporte como o canal que seria usado em vez de um pseudo-terminal sem -tt
, embora isso se aplique somente depois desse comando é executado, 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 irá para um terminal, isso ainda afetará seu buffering (que será baseado em linha para muitos aplicativos) e a eficiência da largura de banda, pois TCP_NODELAY
está ativado. Também com -tt
, ssh
define o IPQoS como lowdelay
em vez de throughput
. Você poderia contornar ambos 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 fim do arquivo em seu stdin e que o stdout e o stderr do comando remoto são mesclados em um único fluxo.
Então, não é um bom trabalho depois de tudo.
Se você tiver uma maneira de gerar um pseudo-terminal no host remoto (como expect
, zsh
, socat
, perl
' IO::Pty
...), então seria melhor usar isso para criar o pseudo-terminal para anexar sudo
a (mas não para E / S) e usar ssh
sem -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 é parecido com Bourne).