Estou confuso sobre o que ssh -t
faz e por que às vezes preciso da -t
opção. Meu entendimento é que se eu executar ssh -t program
, o ssh é forçado a alocar um pseudo tty, com o qual ele passa a entrada do teclado para program
's e passa a program
saída de 's para stdout.
Mas parece que estou errado. Por exemplo, os dois seguintes parecem funcionar de forma idêntica, pois posso operar interativamente com rclone usando qualquer um deles, embora o primeiro comando o force a alocar um pseudo tty e o segundo comando o force a não alocar um pseudo tty:
ssh -t [email protected] rclone config
ssh -T [email protected] rclone config
Então o que ssh -t
realmente faz?
Atualizar:
Para esclarecer melhor essa questão, criei o seguinte script python chamado hello.py
.
import sys, signal
def signal_handler(sig, frame):
print('You pressed Ctrl+C!')
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
print(f"stdin is tty:{sys.stdin.isatty()}")
print(f"stdout is tty:{sys.stdout.isatty()}")
s = input("Enter what you want:")
print("Hello ", s)
Em uma máquina remota, se eu invocá-lo como , obtenho a seguinte saída:ssh -t [email protected] "python hello.py"
stdin is tty: true
stdout is tty: true
Enter what you want: cat
Hello cat
Se eu invocá-lo como , obtenho o seguinte:ssh -T [email protected] "python hello.py"
stdin is tty: false
stdout is tty: false
Enter what you want: cat
Hello cat
Em ambos os casos, consigo interagir com o programa digitando "cat" no teclado.
Uma diferença que observo é que quando pressiono CTRL-C, a -t
versão captura SIGINT, mas a -T
versão não.
Estou curioso para saber por que ainda consigo interagir com ele mesmo que stdin/stdout não seja um tty. Além disso, isatty()
é de fato uma função de biblioteca C padrão. O que um (pseudo) TTY realmente significa aqui?
Ele faz isso, mas um pseudo tty não é necessário para que stdin/stdout funcione. Isso também pode ser alcançado usando pipes simples. Quando você executa
ssh -T
, a entrada e a saída do programa remoto são conectadas ao sshd usando pipes anônimos.Há outras funções que um tty faz, no entanto – ele fornece tradução de entrada e saída (por exemplo, LF para CRLF, ou Ctrl-Cpara o sinal SIGINT), ele tem um conceito de 'dimensões' (largura × altura são armazenados como parâmetros tty). O kernel também mantém um controle específico de processos anexados a um tty em particular para que o controle de trabalho (como em Ctrl-Z no shell) possa ser implementado, bem como SIGHUP quando o sshd sai e o tty é "desligado" ou SIGWINCH quando as dimensões mudam.
(E como um terminal interativo significa ter um tty, muitos programas também verificam a presença de um tty no stdin para determinar se devem ser executados no modo interativo ou não. Por exemplo, você pode executar o Bash sem um tty, mas — além de não poder executar o controle de tarefas — ele também decidirá desabilitar seus recursos de edição de linha e usar um 'prompt' vazio por padrão. A E/S em buffer de tempos de execução como Glibc fwrite() verificará um tty para saber se deve ser armazenado em buffer linha por linha para saída interativa ou em grandes lotes para saída de arquivo/pipe.)
Use
-t
quando quiser executar um programa orientado a terminal, comohtop
, e-T
quando quiser um canal de 8 bits "limpo" para transferir dados binários. (Geralmente, a única vez em que um explícito-T
é necessário é quando o lado remoto tem um comando forçado.)