`ssh <host>` è una shell di accesso, ma `ssh <host> <comando>` non lo è?


12

Ho notato che quando eseguo un comando direttamente su un host SSH utilizzando la ssh <host> <command>sintassi, vedo l'output di .bashrcma non l'output di .bash_profile(o .profile).

Ad esempio, se inserisco il seguente comando nella parte superiore di entrambi i file,

echo ${BASH_SOURCE[0]}

e fonte manualmente .bash_profile(quali fonti .bashrca loro volta), vedrò

$ . .bash_profile
.bash_profile
.bashrc

Questo è lo stesso output che vedo se accedo a questo computer in remoto tramite SSH, usando il ssh <host>modulo del comando. (E se rimango .bash_profiletemporaneamente da qualche altra parte, nessuna di queste righe viene ripetuta.)

Tuttavia, se eseguo un comando direttamente sul computer remoto con la ssh <host> <command>forma di ssh, l'output è simile al seguente:

$ ssh <host> echo foo
/home/rlue/.bashrc
foo

La mia comprensione è che la differenza tra .bash_profileed .bashrcè che il primo è per le shell di accesso mentre il secondo è per le shell interattive, non di accesso .

Ho concluso quanto segue:

  1. ssh <host>solo fonti .bash_profile, mentre
  2. ssh <host> <command>solo fonti .bashrc, il che significa
  3. il primo è una shell di accesso e il secondo no.

Queste conclusioni sono corrette? Perché viene ssh <host> <command>considerata una shell interattiva senza accesso? SSH non sta ancora effettuando l'accesso al computer remoto per eseguire il comando?


uscita di .bashrc? Quel file non dovrebbe produrre alcun output. Qualsiasi output da .bashrcpuò rompere tutti gli strumenti usando ssh come loro trasporto.
Kasperd,

Giusto. In questo caso, un paio di linee in .bashrcentrata generavano un errore, mentre altre linee simili .bash_profilenon lo erano. Ho colto l'occasione per indagare sulla discrepanza prima di correggere le linee offensive.
Ryan Lue,

Risposte:


12

OpenSSH (molto probabilmente quello che stai eseguendo) decide se creare o meno una shell di accesso e lo fa solo se non stai eseguendo un comando specifico. Da man ssh:

 If command is specified, it is executed on the remote host instead of a
 login shell.

Quindi è una scelta di implementazione per il server ssh se vuole creare una shell di login o meno, e se si dà un comando da eseguire, non lo fa.

Mentre sshesegue un login, se lo fai eseguire un comando ed uscire, è davvero molto più simile alla creazione di una shell solo per eseguire quel comando che per ottenere un ambiente di accesso. Sembra, dato che, le persone che scrivono OpenSSH hanno deciso di trattarlo come quel tipo di attività.

Creano una shell non interattiva e non di accesso per eseguire il comando, poiché questo è lo spirito dell'esecuzione di un comando in un altro contesto / shell. Normalmente, tuttavia, le shell non interattive non si procurano automaticamente, ~/.bashrccosa che sta chiaramente accadendo qui. bashsta effettivamente cercando di aiutarci qui. Dai documenti

Richiamato dal demone shell remoto

Bash tenta di determinare quando viene eseguito con il suo input standard collegato a una connessione di rete, come quando viene eseguito dal daemon di shell remoto, di solito rshd o dal daemon di shell sicuro sshd. Se Bash determina che viene eseguito in questo modo, legge ed esegue i comandi da ~ / .bashrc, se quel file esiste ed è leggibile. Non lo farà se invocato come sh. L'opzione --norc può essere usata per inibire questo comportamento e l'opzione --rcfile può essere usata per forzare la lettura di un altro file, ma né rshd né sshd generalmente invocano la shell con quelle opzioni o consentono di specificarle.


"... viene eseguito sull'host remoto anziché su una shell di accesso." Non capisco questa dicotomia. Il comando viene eseguito sull'host remoto invece che in una shell di accesso , oppure il comando viene eseguito sull'host remoto, invece che una shell di accesso viene eseguita lì? Se il primo, come è / o? (non è normalmente entrambi? ) Se quest'ultimo, è ancora eseguito nel contesto di una shell, non è vero? (uno interattivo, senza login?) Quindi la mia domanda riguarda anche la semantica: cosa significa "login shell" e perché OpenSSH dovrebbe essere progettato per non crearne uno per singoli comandi?
Ryan Lue,

@RyanLue I diversi "gusti" di shell rendono ciascuno più semplice / più sicuro / ottimizzato determinati compiti, ecc. Mentre si esegue una operazione sshrichiede un login, gli implementatori hanno apparentemente deciso che in alcune circostanze, ad esempio, chiedendogli di eseguire un comando e restituire, fare non necessitano / traggono vantaggio dai passaggi aggiuntivi che esegue una shell di accesso e quindi la ignorano. Quindi effettivamente c'è una shell che viene eseguita, presumo principalmente di configurare l'ambiente, e poiché la shell non verrà fornita all'utente che ha effettuato l'accesso, la trattano come se l'utente avesse appena avviato una nuova shell per eseguirla comando
Eric Renouf,

"Quindi effettivamente c'è una shell che viene eseguita, presumo principalmente di configurare l'ambiente ..." <ma l'ho appena sperimentato e sembra che ssh <host> <command>non erediti l'ambiente di alcuna shell di accesso esistente. Ad esempio, $ ssh <host> \$PATHrestituisce il percorso come sarebbe senza l' approvvigionamento .bash_profile(o .profile, per così dire) ... In senso pratico, perché dovresti eludere questo passaggio?
Ryan Lue,

"... gli implementatori apparentemente hanno deciso che in alcune circostanze, ad es. Chiedendogli di eseguire un comando e restituire, non hanno bisogno / beneficiano dei passaggi aggiuntivi che una shell di login prende, e quindi lo saltano." <anche, in particolare alla ricerca di chiarimenti / approfondimenti su questa scelta progettuale. Definisco il mio PATHin .profile- non è esattamente il tipo di cosa che vorresti caricare prima di eseguire un comando arbitrario su un host remoto?
Ryan Lue,

1
@RyanLue il server ssh di Boks distingue gli usi distinti di ssh e può concedere autorizzazioni per ciascuno. Accesso remoto, esecuzione remota, copia remota, forse questo aiuta a capire perché dovresti avere il comportamento che descrivi. L'accesso remoto (uso interattivo) potrebbe essere troppo da chiedere in un ambiente ad alta sicurezza. Openssh può essere limitato usando rbash / rksh e 'logout' in .bash_profile o chroot.
bbaassssiiee,

4

Il motivo di questo comportamento risiede a un livello inferiore rispetto alle shell: ssh host(il caso "login shell") utilizza uno pseudoterminale sull'host remoto, per comunicare tra il sshdprocesso del server e la shell; ssh host commandusa invece pipe tra sshde command. Gli pseudoterminali sono necessari per fare un uso interattivo di un interprete di comandi, come una shell, o la modalità " read-eval-print " di un linguaggio di scripting; implementano un sacco di funzioni a misura d'uomo come essere in grado di tornare indietro sugli errori di battitura. Ma hanno più sovraccarico e (a seconda della configurazione) non consentono il passaggio di dati arbitrari non modificati, quindi SSH evita di usarli quando non si verificherà l'interazione.

A volte il comando di SSH / nessun comando euristico può sbagliare; può essere sostituito con i pulsanti -te -T. Ad esempio, per accedere a una macchina remota e ricollegare immediatamente una screensessione sospesa , è necessario farlo ssh -t host screen -R; ssh host screen -Rfarà screenlamentare di non essere collegato a un terminale. Non riesco a pensare a una situazione in cui si sarebbe effettivamente desidera utilizzare -T, ma è lì se mai ne trovate uno.


1

Per prima cosa devi vedere i diversi tipi, puoi leggere questo:

/unix/170493/login-non-login-and-interactive-non-interactive-shells

Ora se apri il tuo bashrc vedrai all'inizio questo:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

Ciò significa che, a seconda di come si accede al sistema, questo file carica il codice all'interno o meno.


Va bene, ma questo solleva una domanda interessante: .bashrcpuò essere scritto in modo da non essere reperito se viene chiamato in un contesto non interattivo ( ovvero, se non vi è alcuna "istruzione prompt" / $PS1variabile). Ma ssh <host> <command> è decisamente non interattivo ; cioè, non genera un prompt dei comandi. Quindi perché OpenSSH dovrebbe essere progettato per creare un prompt interattivo senza accesso (uno che tenta di eseguire il sorgente .bashrc) per questo caso d'uso apparentemente non interattivo di accesso ??
Ryan Lue,
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.