sh file di avvio su ssh


10

Ho alcuni comandi importanti che devo eseguire prima che inizi qualsiasi sh shell. Questo è necessario per passare i comandi SSH nel comando SSH ( ssh host somecommand) e altri programmi che eseguono comandi.

Nel mio .profileho questo:

ihammerhands@wreckcreations:~> cat .profile
#specific environment and startup programs
export PS1="\u@wreckcreations:\w> "
export PYTHONPATH=~/python/lib/python2.4/site-packages
export PATH=$PATH:~/bin:~/python/bin

Tuttavia, questo non riesce:

W:\programming\wreckcreations-site\test-hg>ssh name@host echo $PATH
Enter passphrase for key '/home/Owner/.ssh/id_rsa':
/usr/local/bin:/bin:/usr/bin

Notare le opzioni PATH mancanti

Qual è il nome corretto per il profilo sh? Nota: non ho accesso come root e non voglio che questo venga applicato ad altri utenti. c'è un altro modo per fare ciò?


EDIT: sembra /bin/shcollegamenti a bash, il che non è sorprendente. Ciò che sorprende è che il mio profilo è ancora ignorato. Eventuali suggerimenti?


1
Non ho voglia di ripetere ciò che è nella pagina man, quindi basta guardare nella pagina man bash nella sezione 'INVOCATION'. È vicino alla cima e descrive tutto ciò che devi sapere.
Camh,

Potresti provare a usare ssh name@host -t echo $PATH.
Gert,

L'output di @Gert è lo stesso
TheLQ

@camh Pensi che farei questa domanda se non avessi già controllato le pagine man? Li ho letti molte volte + altri post, ma non sono mai riuscito a trovare una risposta a questo specifico problema, dal momento che non sono sicuro su quali comandi stage ssh e comandi di altri programmi vengano eseguiti in
TheLQ

1
@TheLQ: Non ti conosco, quindi non so se verifichi la pagina man. Tutto quello che sapevo è che le risposte erano proprio lì, quindi invece di ripeterlo parola per parola, ti ho indicato. Un puntatore più specifico è quello di cercare shell non interattive poiché questo è il tuo scenario ssh. Se qualcosa nella pagina man non è chiaro, forse puoi fare una domanda più specifica.
Camh,

Risposte:


8

Vale la pena notare che il comando che menzioni nella tua domanda

ssh name@host echo $PATH

praticamente non sarà mai utile. La sostituzione della variabile per $ PATH viene eseguita dalla shell locale e passata a ssh che esegue l'eco sul sistema remoto per stampare il contenuto della variabile path, mentre si espandeva sul sistema locale. Ecco un esempio del mio fare qualcosa di simile tra il mio Mac e una macchina Linux sulla mia rete:

LibMBP:~ will$ echo $PATH
/opt/local/bin:/opt/local/sbin:/Users/will/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/texbin:/usr/X11/bin
LibMBP:~ will$ ssh warren echo $PATH
will@warren's password: 
/opt/local/bin:/opt/local/sbin:/Users/will/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/texbin:/usr/X11/bin
LibMBP:~ will$ ssh warren 'echo $PATH'
will@warren's password: 
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
LibMBP:~ will$ 

Nota come avevo bisogno di usare le virgolette per impedire alla mia shell locale di espandere la variabile.


In Windows Cygwin land, le virgolette singole non fanno nulla nel prompt di Cygwin o Command. Stranamente, le doppie virgolette fanno espandere il PERCORSO completamente alla mia macchina locale in Cygwin. Quindi qualunque cosa mi abbia dato ssh non era il mio percorso, era il server
TheLQ

@TheLQ Le virgolette singole sono necessarie al prompt di unix (incluso Cygwin), ma non sono necessarie virgolette al prompt di cmd.
Gilles 'SO- smetti di essere malvagio' il

12

~/.profileviene eseguito solo dalle shell di login. Il programma che chiama la shell decide se la shell sarà una shell di login (inserendo a -come primo carattere dell'argomento zeroth nell'invocazione della shell). In genere non viene eseguito quando si accede per eseguire un comando specifico.

In particolare OpenSSH invoca una shell di accesso solo se non si specifica un comando. Quindi, se si specifica un comando, ~/.profilenon verrà letto.

OpenSSH consente di impostare le variabili di ambiente sul lato server. Questo deve essere abilitato nella configurazione del server , con la PermitUserEnvironmentdirettiva. Le variabili possono essere impostate nel file ~/.ssh/environment. Supponendo che tu utilizzi l'autenticazione con chiave pubblica, puoi anche impostare variabili per chiave in ~/.ssh/authorized_keys: aggiungi environment="FOO=bar"all'inizio della riga pertinente.

Ssh supporta anche l'invio di variabili d'ambiente. In OpenSSH, usa la SendEnvdirettiva in ~/.ssh/config. Tuttavia, la variabile di ambiente specifica deve essere abilitata con una AcceptEnvdirettiva nella configurazione del server, quindi potrebbe non funzionare per te.

Una cosa che penso funzioni sempre (abbastanza stranamente) fintanto che stai usando l'autenticazione con chiave pubblica è (ab) usare l' command=opzione nel authorized_keysfile . Una chiave con commandun'opzione è valida solo per l'esecuzione del comando specificato; ma il comando nel authorized_keysfile viene eseguito con la variabile di ambiente SSH_ORIGINAL_COMMANDimpostata sul comando specificato dall'utente. Questa variabile è vuota se l'utente non ha specificato un comando e quindi si aspettava una shell interattiva. Quindi puoi usare qualcosa del genere in ~/.ssh/authorized_keys(ovviamente, non si applicherà se non usi questa chiave per autenticarti):

command=". ~/.profile; if [ -n \"$SSH_ORIGINAL_COMMAND\" ]; then eval \"$SSH_ORIGINAL_COMMAND\"; else exec \"$SHELL\"; fi" ssh-rsa 

Un'altra possibilità è scrivere script di un wrapper sul server. Qualcosa di simile al seguente in ~/bin/ssh-wrapper:

#!/bin/sh
. ~/.profile
exec "${0##*/}" "$@"

Quindi crea collegamenti simbolici a questo script chiamato rsync, unisonecc. Passa --rsync-path='bin/rsync'dalla rsyncriga di comando e così via per altri programmi. In alternativa, alcuni comandi consentono di specificare un intero frammento di shell da eseguire in remoto, il che consente di rendere autonomo il comando: ad esempio, con rsync, è possibile utilizzare --rsync-path='. ~/.profile; rsync'.

C'è un'altra strada che dipende dal fatto che la shell di accesso sia bash o zsh. Bash legge sempre ~/.bashrcquando viene invocato da rshd o sshd, anche se non è interattivo (ma non se si chiama come sh). Zsh legge sempre ~/.zshenv.

## ~/.bashrc
if [[ $- != *i* ]]; then
  # Either .bashrc was sourced explicitly, or this is an rsh/ssh session.
  . ~/.profile
fi

## ~/.zshenv
if [[ $(ps -p $PPID -o comm=) = [rs]shd && $- != *l* ]]; then
  # Not a login shell, but this is an rsh/ssh session
  . ~/.profile
fi

Che dire dei comandi eseguiti da altri comandi? In questo caso sarebbe ganci Mercurial. Mercurial deve essere sulla buona strada perché l'hook
riesca

Usa una delle tecniche che ho indicato per far funzionare il tuo profilo in comandi ssh non interattivi. Uno di questi ( command=in authorized_keys) funziona in modo trasparente. Altri richiedono una shell o opzioni specifiche nella configurazione del server ssh. L'equivalente mercuriale di --rsync-pathè --remotecmd.
Gilles 'SO- smetti di essere malvagio' il

Per alcuni potrebbe essere utile includere lo stesso command=comando completo nel tuo post superuser.com/a/207262/137762
mforbes

1

Di solito al login, bash legge i comandi da:

~ / .bash_profile
~ / .bashrc

Dalla pagina man di bash:

~ / .bash_profile
Il file di inizializzazione personale, eseguito per le shell di login

~ / .bashrc
Il file di avvio individuale per shell interattiva


0

Sono a corto di tempo per testarlo, ma guardando le pagine man che ho trovato:

man bash: quando bash viene avviato in modo non interattivo, per eseguire uno script di shell, ad esempio, cerca la variabile BASH_ENV nell'ambiente, espande il suo valore se appare lì e usa il valore espanso come nome di un file per leggi ed esegui. Bash si comporta come se fosse eseguito il seguente comando: if [-n "$ BASH_ENV"]; poi . "$ BASH_ENV"; fi ma il valore della variabile PATH non viene utilizzato per cercare il nome del file.

man ssh: ~ / .ssh / environment Contiene definizioni aggiuntive per le variabili di ambiente; vedi AMBIENTE, sopra.

La combinazione suggerisce come si può fare in modo che ssh esegua il proprio .profile

Sfortunatamente il mio server ha PermitUserEnvironment al valore predefinito no, il che rende questo non funziona per me (e come ho detto non ho il tempo di giocarci di più).


Anche se riuscissi a far funzionare SSH affermando esplicitamente alcune variabili di ambiente nell'ambiente, ciò non aiuterebbe ancora a far sì che il mio profilo venisse eseguito quando altri programmi chiamano comandi
TheLQ

Nel tuo esempio tutto ciò che stai facendo è impostare le variabili di ambiente, cos'altro vuoi fare?
Kasterma,

0

(rimosso ... può avere un solo collegamento ipertestuale come nuovo utente ~)

Aggiornare

Siamo spiacenti, non ho visto che si tratta di una sessione non interattiva, a cui non si applica il link sopra.

Quando Bash si avvia in modalità compatibilità SH, cerca di imitare il comportamento di avvio delle versioni storiche di sh il più vicino possibile, rispettando allo stesso tempo lo standard POSIX®. I file di profilo letti sono / etc / profile e ~ / .profile, se si tratta di una shell di accesso.

Se non è una shell di accesso, viene valutata la variabile di ambiente ENV e il nome file risultante viene preso come nome del file di avvio.

Dopo aver letto i file di avvio, Bash entra in modalità compatibilità POSIX (r) (per l'esecuzione, non per l'avvio!).

Bash si avvia in modalità di compatibilità sh quando:

  • il nome file di base in argv [0] è sh (:!: attenzione cari utenti Linux super intelligenti ... / bin / sh può essere collegato a / bin / bash, ma ciò non significa che si comporti come / bin / bash :! :)

Quindi la domanda è: perché non la esegue, anche se la tua shell è avviata in questo modo.

fonte


Ho guardato ma, come ho detto a Camh, non so in quali comandi stage ssh e altri comandi del programma vengano eseguiti. Ho già letto molte volte le pagine man e altre guide
TheLQ
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.