Qual è il vantaggio di non allocare un terminale in ssh?


66

Ogni tanto farò qualcosa del genere

ssh user@host sudo thing

e mi viene ricordato che ssh non alloca una pseudo-tty di default. Perché no? Quali benefici sarei perdendo se alias ssha ssh -t?


1
> Mi viene ricordato che ssh non assegna uno psuedo-tty Cosa succede? Arricchirebbe la domanda per capire qual è il problema.
Air

5
@Air Non c'è un problema che stavo cercando di risolvere. C'era una scelta su come implementare ssh che stavo cercando di capire. La domanda è molto chiara e la risposta di Andrew B risponde bene alla domanda. La risposta può essere riassunta in questo modo: l'esecuzione ssh -tè sempre negativa perché può causare l'interruzione di alcuni comandi in modi strani. Considerando che, eseguendo un comando che richiede un PTY senza uno si ottiene un chiaro messaggio di errore che è necessario un terminale.
Chas. Owens,

Risposte:


73

La differenza principale è il concetto di interattività . È simile all'esecuzione dei comandi localmente all'interno di uno script, anziché digitarli da soli. È diverso in quanto un comando remoto deve scegliere un valore predefinito e non interattivo è il più sicuro. (e di solito più onesto)

STDIN

  • Se viene assegnato un PTY, le applicazioni possono rilevarlo e sapere che è sicuro richiedere all'utente ulteriori input senza interrompere le cose. Esistono molti programmi che salteranno il passaggio di richiesta all'utente per l'input se non è presente alcun terminale, e questa è una buona cosa. In caso contrario, gli script potrebbero bloccarsi inutilmente.
  • L'input verrà inviato al server remoto per la durata del comando. Ciò include sequenze di controllo. Mentre Ctrl-cun'interruzione normalmente causerebbe l'interruzione immediata di un ciclo sul comando ssh, le sequenze di controllo verranno invece inviate al server remoto. Ciò comporta la necessità di "martellare" la sequenza di tasti per assicurarsi che arrivi quando il controllo lascia il comando ssh, ma prima che inizi il successivo comando ssh.

Vorrei mettere in guardia contro l'uso ssh -tin script incustoditi, come le croni. Una shell non interattiva che chiede a un comando remoto di comportarsi in modo interattivo per l'input sta richiedendo tutti i tipi di problemi.

È inoltre possibile verificare la presenza di un terminale nei propri script di shell. Per testare STDIN con le versioni più recenti di bash:

# fd 0 is STDIN
[ -t 0 ]; echo $?

STDOUT

  • Quando aliasing ssha ssh -t, ci si può aspettare di ottenere un ritorno a capo in più in linea termina. Potrebbe non essere visibile a te, ma è lì; verrà visualizzato come ^Mquando viene reindirizzato a cat -e. È quindi necessario dedicare ulteriore impegno per garantire che questo codice di controllo non venga assegnato alle variabili, in particolare se si intende inserire tale output in un database.
  • Esiste anche il rischio che i programmi assumano di essere in grado di eseguire il rendering di output non adatti al reindirizzamento dei file. Normalmente se dovessi reindirizzare STDOUT su un file, il programma riconoscerebbe che STDOUT non è un terminale e ometterebbe qualsiasi codice colore. Se il reindirizzamento STDOUT proviene dall'output del client ssh e c'è un PTY associato all'estremità remota del client, i programmi remoti non possono fare una tale distinzione e si finirà con immondizia terminale nel file di output. Il reindirizzamento dell'output su un file all'estremità remota della connessione dovrebbe comunque funzionare come previsto.

Ecco lo stesso test bash di prima, ma per STDOUT:

# fd 1 is STDOUT
[ -t 1 ]; echo $?

Mentre è possibile aggirare questi problemi, inevitabilmente ti dimenticherai di progettare script intorno a loro. Lo facciamo tutti ad un certo punto. I membri del team possono anche non rendersi conto / ricordare che l'alias è a posto, che a sua volta creare problemi per voi quando si scrivono script che utilizzano l'alias.

Aliasing sshper ssh -tmolto è un caso in cui sarete violando il principio di progettazione di minima sorpresa ; le persone incontreranno problemi che non si aspettano e potrebbero non capire cosa li sta causando.


9
Si ha quasi l'impressione di aver lavorato in una squadra che ha fatto questo ...
Andrew B,

Nell'ambito coperto da questa risposta, è un grande. Ma la domanda aveva una portata più ampia, essenzialmente volendo conoscere TUTTE le differenze (cosa aspettarsi). Informazioni aggiuntive: a livello di processo, -t allocerà PRIMA un tty e POI eseguirà una shell (lungo la strada, sourcing / etc / profile e ~ / .bash_profile) e THEN eseguirà il comando. Senza -t, ssh INSTEAD procurerà diversi file env (/etc/bash.bashrc, quindi ~ / .bashrc) e POI eseguirà il comando. Ciò significa che puoi vedere un comportamento molto diverso in ciascuno: $ PATH più corto, forse un errore 'unario' bash perché la var ENV che hai assunto non c'è ...
Scott Prive

@Crossfit Abbiamo trattato l'argomento delle shell di login e non nei commenti di un'altra risposta, ma non siamo entrati in un'esaustiva suddivisione delle differenze ambientali perché l'OP aveva già considerato la risposta alla domanda per le loro esigenze particolari. Sentiti libero di aggiungere dettagli dove vedi spazio per farlo in quanto ciò potrebbe aiutare gli altri che si imbattono in queste domande e risposte.
Andrew B,

33

Caratteri di escape SSH e trasferimento di file binari

Un vantaggio che non è stato menzionato nelle altre risposte è che quando si opera senza uno pseudo-terminale , i caratteri di escape SSH come quelli non~C sono supportati ; questo rende sicuro per i programmi il trasferimento di file binari che possono contenere queste sequenze.

Verifica teorica

Copia un file binario usando uno pseudo-terminale:

$ ssh -t anthony@remote_host 'cat /usr/bin/free' > ~/free
Connection to remote_host closed.

Copia un file binario senza usare uno pseudo-terminale:

$ ssh anthony@remote_host 'cat /usr/bin/free' > ~/free2

I due file non sono uguali:

$ diff ~/free*
Binary files /home/anthony/free and /home/anthony/free2 differ

Quello che è stato copiato con uno pseudo-terminale è danneggiato:

$ chmod +x ~/free*
$ ./free
Segmentation fault

mentre l'altro non è:

$ ./free2
             total       used       free     shared    buffers     cached
Mem:       2065496    1980876      84620          0      48264    1502444
-/+ buffers/cache:     430168    1635328
Swap:      4128760        112    4128648

Trasferimento di file su SSH

Ciò è particolarmente importante per programmi come scpo rsyncche utilizzano SSH per il trasferimento di dati. Questa descrizione dettagliata di come funziona il protocollo SCP spiega come il protocollo SCP consista in una combinazione di messaggi di protocollo testuali e dati di file binari.


OpenSSH ti aiuta a proteggerti da te stesso

Vale la pena notare che anche se -tviene utilizzato il flag, il sshclient OpenSSH rifiuterà di allocare uno pseudo-terminale se rileva che il suo stdinflusso non è un terminale:

$ echo testing | ssh -t anthony@remote_host 'echo $TERM'
Pseudo-terminal will not be allocated because stdin is not a terminal.
dumb

Puoi comunque forzare il client OpenSSH a allocare uno pseudo-terminale con -tt:

$ echo testing | ssh -tt anthony@remote_host 'echo $TERM'
xterm

In entrambi i casi, (sensibilmente) non importa se stdouto stderrvengono reindirizzati:

$ ssh -t anthony@remote_host 'echo $TERM' >| ssh_output
Connection to remote_host closed.

2
Questo è stato un punto molto interessante che non avevo considerato, grazie per aver aggiunto questa risposta!
Jenny D dice di reintegrare Monica il

4

Sull'host remoto abbiamo a che fare con questa impostazione:

/etc/sudoers
...
Defaults requiretty

Senza sudo

$ ssh -T user@host echo -e 'foo\\nbar' | cat -e
foo$
bar$

E con sudo

$ ssh -T user@host sudo echo -e 'foo\\nbar' | cat -e
sudo: sorry, you must have a tty to run sudo

Con sudo otteniamo il ritorno extra in carrozza

$ ssh -t user@host sudo echo -e 'foo\\nbar' | cat -e
foo^M$
      bar^M$
            Connection to localhost closed.

La soluzione è disabilitare la nuova riga da tradurre a ritorno a capo con nuovastty -onlcr

$ ssh -t user@host stty -onlcr\; sudo echo -e 'foo\\nbar' | cat -e
foo$
    bar$
        Connection to localhost closed.

1
Bello ma l'output è rientrato /: ti capita di sapere se puoi auto-restituirlo (unix-like)?
Boop,

1

Pensa alla retrocompatibilità.

Le 2 modalità primarie di ssh sono login interattivo con un tty e comando specificato senza un tty, poiché quelle erano esattamente le capacità di rlogine rshrispettivamente. ssh aveva bisogno di fornire un superset di rlogin/ rshfeatures per avere successo in sostituzione.

Quindi le impostazioni predefinite sono state decise prima della nascita di ssh. Combinazioni come "Voglio specificare un comando e ottenere un tty" dovevano accedere con nuove opzioni. Sii contento che almeno adesso abbiamo questa opzione, a differenza di quando stavamo usando rsh. Non abbiamo scambiato nessuna funzionalità utile per ottenere connessioni crittografate. Abbiamo funzionalità bonus!


0

Da man ssh:

 -t      Force pseudo-tty allocation.  This can be used to execute arbi-
         trary screen-based programs on a remote machine, which can be
         very useful, e.g. when implementing menu services.  Multiple -t
         options force tty allocation, even if ssh has no local tty.

Ciò consente di ottenere una sorta di "shell" sul server remoto. Per i server che non concedono l'accesso alla shell ma consentono SSH (ad esempio, Github è un esempio noto di accesso SFTP), l'utilizzo di questo flag farà sì che il server rifiuti la connessione.

La shell ha anche tutte le variabili ambientali (come $PATH), quindi l'esecuzione degli script in genere ha bisogno di un tty per funzionare.


1
Questo non risponde alla domanda. So già come allocare una pseudo-tty. Voglio sapere perché non dovrei semplicemente assegnarne sempre uno.
Chas. Owens,

1
@ Chas.Owens Perché, come ho sottolineato nella risposta, alcuni server SSH non consentono l'accesso tty e la connessione verrà interrotta se ne richiedi una dal server.
Nathan C,

5
Penso che potresti confondere parte della tua terminologia. Non è una shell semplicemente perché ad essa è associato un PTY. Ci sono generalmente tre tipi di coperture: non-interactive, interactivee login. loginè un'ulteriore caratteristica degli altri due tipi di shell. Le permutazioni di questi tre determinano quali file provengono dall'accesso, il che a sua volta influenza il modo in cui l'ambiente verrà inizializzato. (variabili, come menzionavi)
Andrew B,

3
@AndrewB Hai ragione ... Ho imparato qualcosa anche da questa domanda. :)
Nathan C,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.