Pourquoi une commande distante SSH reçoit-elle moins de variables d’environnement lorsqu’elle est exécutée manuellement?

J’ai une commande qui fonctionne bien si je ssh sur une machine et l’exécute, mais échoue lorsque j’essaie de l’exécuter en utilisant une commande ssh distante comme:

ssh user@IP  

En comparant la sortie de “env” en utilisant les deux méthodes, on se retrouve dans des environnements différents. Lorsque je me connecte manuellement à la machine et que je lance env, je reçois beaucoup plus de variables d’environnement que lorsque je lance:

 ssh user@IP "env" 

Une idée pourquoi?

Il existe différents types de coquilles. Le shell d’exécution de la commande SSH est un shell non interactif, alors que votre shell normal est un shell de connexion ou un shell interactif. La description suit, de l’homme bash:

        Un shell de connexion est un shell dont le premier caractère d'argument
        zéro est un - ou un est lancé avec l'option --login.

        Un shell interactif est un shell lancé sans aucune option
        arguments et sans l'option -c dont l'entrée standard
        et erreur sont tous deux connectés aux terminaux (comme déterminé
        par isatty (3)), ou une avec l'option -i.  PS1 est
        set et $ - inclut i si bash est interactif, permettant un
        script shell ou un fichier de démarrage pour tester cet état.

        Les paragraphes suivants décrivent comment bash exécute son
        fichiers de démarrage.  Si l'un des fichiers existe mais ne peut pas être
        lire, bash signale une erreur.  Tildes sont développées dans un fichier
        noms comme décrit ci-dessous sous Tilde Expansion dans le
        Section EXPANSION.

        Lorsque bash est appelé en tant que shell de connexion interactif ou
        un shell non interactif avec l'option --login, le premier
        lit et exécute les commandes du fichier / etc / profile, si
        ce fichier existe.  Après avoir lu ce fichier, il cherche
        ~ / .bash_profile, ~ / .bash_login et ~ / .profile, dans cette
        ordre, et lit et exécute les commandes du premier
        cela existe et est lisible.  L'option --noprofile peut
        être utilisé lorsque le shell est démarré pour inhiber ce comportement
        ior.

        Lorsqu'un shell de connexion se ferme, bash lit et exécute les commandes
        à partir du fichier ~ / .bash_logout, s'il existe.

        Lorsqu'un shell interactif qui n'est pas un shell de connexion est
        démarré, bash lit et exécute les commandes de ~ / .bashrc,
        si ce fichier existe  Cela peut être inhibé en utilisant le
        - option de rappel.  L'option de fichier --rcfile forcera bash
        pour lire et exécuter des commandes depuis un fichier au lieu de
        ~ / .bashrc.

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

Que diriez-vous de rechercher le profil avant d’exécuter la commande?

ssh user@host "source /etc/profile; /path/script.sh"

Vous trouverez peut-être mieux de changer cela en ~/.bash_profile , ~/.bashrc ou autre chose.

(Comme ici (linuxquestions.org) )

L’environnement Shell ne se charge pas lors de l’exécution de la commande ssh distante. Vous pouvez éditer le fichier d’environnement ssh:

 vi ~/.ssh/environment 

Son format est le suivant:

 VAR1=VALUE1 VAR2=VALUE2 

Vérifiez également la configuration de sshd pour l’option PermitUserEnvironment = yes.

J’ai eu un problème similaire, mais à la fin, j’ai découvert que ~ / .bashrc était tout ce dont j’avais besoin.

Cependant, dans Ubuntu, j’ai dû commenter la ligne qui cesse de traiter ~ / .bashrc:

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

J’ai trouvé une solution simple à ce problème en ajoutant la source / etc / profile en haut du fichier script.sh que j’essayais d’exécuter sur le système cible. Sur les systèmes, les variables d’environnement requirejses par script.sh étaient configurées comme si elles étaient exécutées à partir d’un shell de connexion.

Dans l’une des réponses précédentes, il a été suggéré d’utiliser ~ / .bashr_profile etc … Je n’ai pas passé beaucoup de temps là-dessus, mais le problème est que si vous utilisez ssh pour un autre utilisateur sur le système cible que le shell sur le système source à partir duquel vous vous connectez, il m’a semblé que l’utilisateur du système source nom à utiliser pour le ~.

Il suffit d’exporter les variables d’environnement souhaitées au-dessus de la vérification d’un shell non interactif dans ~ / .bashrc.