sh fichiers de démarrage sur ssh

10

J'ai quelques commandes importantes que je dois exécuter avant que tout shell sh ne démarre. Cela est nécessaire pour passer des commandes SSH dans la commande SSH ( ssh host somecommand) et d'autres programmes qui exécutent des commandes.

Dans mon .profilej'ai ceci:

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

Cependant, cela échoue:

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

Remarquez les options PATH manquantes

Quel est le nom propre du profil sh? Remarque: je n'ai pas d'accès root et je ne souhaite pas que cela soit appliqué à d'autres utilisateurs. Y a-t-il une autre façon de procéder?


EDIT: Il apparaît des /bin/shliens vers bash, ce qui n'est pas surprenant. Ce qui est surprenant, c'est que mon profil est toujours ignoré. Aucune suggestion?

TheLQ
la source
1
Je n'ai pas envie de répéter ce qui est dans la page de manuel, alors regardez simplement dans la page de manuel bash sous la section 'INVOCATION'. C'est près du sommet et décrit tout ce que vous devez savoir.
camh
Vous pouvez essayer d'utiliser ssh name@host -t echo $PATH.
Gert
La sortie @Gert est la même
TheLQ
@camh Pensez-vous que je poserais cette question si je n'avais pas déjà consulté les pages de manuel? Je les ai lus plusieurs fois + d'autres articles mais je n'ai jamais trouvé de réponse à ce problème spécifique, car je ne sais pas dans quelle étape les commandes ssh et les autres commandes de programme sont exécutées
TheLQ
1
@TheLQ: Je ne vous connais pas, donc je ne sais pas si vous voudriez consulter la page de manuel. Tout ce que je savais, c'est que les réponses étaient là, alors au lieu de le répéter mot pour mot, je vous l'ai indiqué. Un pointeur plus spécifique consiste à rechercher des shells non interactifs puisque c'est votre scénario ssh. Si quelque chose dans la page de manuel n'est pas clair, vous pouvez peut-être poser une question plus spécifique.
camh

Réponses:

8

Il semble intéressant de noter que la commande que vous mentionnez dans votre question

ssh name@host echo $PATH

ne sera pratiquement jamais utile. La substitution de variable pour $ PATH est effectuée par votre shell local, et passée à ssh qui exécute echo sur le système distant pour imprimer le contenu de la variable path, telle qu'elle s'est développée sur votre système local. Voici un exemple de moi faisant quelque chose de similaire entre mon Mac et une machine Linux sur mon réseau:

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$ 

Notez comment j'avais besoin d'utiliser des guillemets pour empêcher mon shell local d'étendre la variable.

wrosecrans
la source
Dans Windows Cygwin land, les guillemets simples ne font rien dans Cygwin ou dans l'invite de commande. Étrangement, les guillemets doubles permettent au PATH de s'étendre complètement à ma machine locale dans Cygwin. Donc, tout ce que ssh me donnait n'était pas mon chemin, c'était celui du serveur
TheLQ
@TheLQ Les guillemets simples sont nécessaires à l'invite unix (y compris Cygwin), mais vous n'avez pas besoin de guillemets à l'invite cmd.
Gilles 'SO- arrête d'être méchant'
12

~/.profileest uniquement exécuté par des shells de connexion. Le programme qui appelle le shell décide si le shell sera un shell de connexion (en mettant a -comme premier caractère de l'argument zéro sur l'invocation du shell). Il n'est généralement pas exécuté lorsque vous vous connectez pour exécuter une commande spécifique.

OpenSSH en particulier invoque un shell de connexion uniquement si vous ne spécifiez pas de commande. Donc, si vous spécifiez une commande, ~/.profileelle ne sera pas lue.

OpenSSH permet de définir des variables d'environnement côté serveur. Cela doit être activé dans la configuration du serveur , avec la PermitUserEnvironmentdirective. Les variables peuvent être définies dans le fichier ~/.ssh/environment. En supposant que vous utilisez l'authentification par clé publique, vous pouvez également définir des variables par clé dans ~/.ssh/authorized_keys: ajouter environment="FOO=bar"au début de la ligne appropriée.

Ssh prend également en charge l'envoi de variables d'environnement. Dans OpenSSH, utilisez la SendEnvdirective dans ~/.ssh/config. Cependant, la variable d'environnement spécifique doit être activée avec une AcceptEnvdirective dans la configuration du serveur, donc cela risque de ne pas fonctionner pour vous.

Une chose qui, selon moi, fonctionne toujours (curieusement) tant que vous utilisez l'authentification par clé publique consiste à (ab) utiliser l' command=option dans le authorized_keysfichier . Une clé avec une commandoption n'est valable que pour exécuter la commande spécifiée; mais la commande du authorized_keysfichier s'exécute avec la variable d'environnement SSH_ORIGINAL_COMMANDdéfinie sur la commande spécifiée par l'utilisateur. Cette variable est vide si l'utilisateur n'a pas spécifié de commande et attend donc un shell interactif. Vous pouvez donc utiliser quelque chose comme ça dans ~/.ssh/authorized_keys(bien sûr, cela ne s'appliquera pas si vous n'utilisez pas cette clé pour vous authentifier):

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

Une autre possibilité est d'écrire un script wrapper sur le serveur. Quelque chose comme ce qui suit dans ~/bin/ssh-wrapper:

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

Ensuite , faire des liens symboliques à ce script appelé rsync, unisonetc. Passe --rsync-path='bin/rsync'sur la rsyncligne de commande, et ainsi de suite pour d' autres programmes. Alternativement, certaines commandes vous permettent de spécifier un extrait de shell entier à exécuter à distance, ce qui vous permet de rendre la commande autonome: par exemple, avec rsync, vous pouvez utiliser --rsync-path='. ~/.profile; rsync'.

Il existe une autre avenue qui dépend de votre shell de connexion étant bash ou zsh. Bash lit toujours ~/.bashrcquand il est invoqué par rshd ou sshd, même s'il n'est pas interactif (mais pas s'il est appelé comme sh). Zsh lit toujours ~/.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
Gilles 'SO- arrête d'être méchant'
la source
Qu'en est-il des commandes que les autres commandes exécutent? Dans ce cas, ce serait des crochets Mercurial. Mercurial doit être sur la
bonne
Utilisez l'une des techniques que j'ai indiquées pour exécuter votre profil dans des commandes ssh non interactives. L'un d'eux ( command=en authorized_keys) fonctionne de manière transparente. D'autres nécessitent un shell ou des options spécifiques dans la configuration du serveur ssh. L'équivalent Mercurial de --rsync-pathest --remotecmd.
Gilles 'SO- arrête d'être méchant'
Il pourrait être utile pour certains d'inclure la même command=commande complète que dans votre message superuser.com/a/207262/137762
mforbes
1

Habituellement, lors de la connexion, bash lit les commandes de:

~ / .bash_profile
~ / .bashrc

Depuis la page de manuel de bash:

~ / .bash_profile
Le fichier d'initialisation personnel, exécuté pour les shells de connexion

~ / .bashrc
Le fichier de démarrage individuel par shell interactif

Alexander Pogrebnyak
la source
0

Je manque de temps pour tester cela, mais en parcourant les pages de manuel que j'ai trouvées:

man bash: lorsque bash est démarré de manière non interactive, pour exécuter un script shell, par exemple, il recherche la variable BASH_ENV dans l'environnement, développe sa valeur si elle y apparaît et utilise la valeur développée comme nom d'un fichier pour lire et exécuter. Bash se comporte comme si la commande suivante avait été exécutée: if [-n "$ BASH_ENV"]; puis . "$ BASH_ENV"; fi mais la valeur de la variable PATH n'est pas utilisée pour rechercher le nom de fichier.

man ssh: ~ / .ssh / environment Contient des définitions supplémentaires pour les variables d'environnement; voir ENVIRONNEMENT, ci-dessus.

La combinaison suggère comment vous pouvez demander à ssh d'exécuter votre .profile

Malheureusement, mon serveur a PermitUserEnvironment à la valeur par défaut no, ce qui fait que cela ne fonctionne pas pour moi (et comme je l'ai dit, je n'ai plus le temps de jouer avec).

kasterma
la source
Même si je pouvais faire fonctionner SSH en indiquant explicitement certaines variables d'environnement dans l'environnement, cela n'aiderait toujours pas à résoudre l'exécution de mon profil lorsque d'autres programmes appellent des commandes
TheLQ
Dans votre exemple, tout ce que vous faites est de définir des variables d'environnement, que voulez-vous faire d'autre?
kasterma
0

(supprimé ... ne peut avoir qu'un seul lien hypertexte en tant que nouvel utilisateur ~)

Mettre à jour

Désolé, je n'ai pas vu qu'il s'agit d'une session non interactive, à laquelle le lien ci-dessus ne s'applique pas.

Lorsque Bash démarre en mode de compatibilité SH, il essaie d'imiter le comportement de démarrage des versions historiques de sh aussi fidèlement que possible, tout en se conformant également à la norme POSIX®. Les fichiers de profil lus sont / etc / profile et ~ / .profile, s'il s'agit d'un shell de connexion.

S'il ne s'agit pas d'un shell de connexion, la variable d'environnement ENV est évaluée et le nom de fichier résultant est pris comme nom du fichier de démarrage.

Une fois les fichiers de démarrage lus, Bash passe en mode de compatibilité POSIX (r) (pour l'exécution, pas pour le démarrage!).

Bash démarre en mode de compatibilité sh lorsque:

  • le nom de fichier de base dans argv [0] est sh (:!: Attention chers utilisateurs Linux ultra-intelligents ... / bin / sh peut être lié à / bin / bash, mais cela ne signifie pas qu'il agit comme / bin / bash :! :)

La question est donc de savoir pourquoi il ne l'exécute pas, même si votre shell est démarré comme ça.

La source


la source
J'ai regardé, mais comme je l'ai dit à camh, je ne sais pas dans quelle étape les commandes ssh et autres commandes de programme sont exécutées. J'ai déjà lu plusieurs fois les pages de manuel et d'autres guides
TheLQ