Variables d'environnement dans bash_profile ou bashrc?

36

J'ai trouvé cette question [blog]: La différence entre .bashrc et .bash_profile est très utile mais après avoir vu la réponse la plus votée (très bien d'ailleurs), j'ai d'autres questions. Vers la fin de la réponse correcte la plus votée, je vois la déclaration comme suit:

Notez que vous pouvez voir ici et là des recommandations pour mettre des définitions de variable d’environnement dans ~ / .bashrc ou toujours lancer des shells de login dans des terminaux. Les deux sont de mauvaises idées.

  1. Pourquoi est-ce une mauvaise idée (je n'essaie pas de me battre, je veux juste comprendre)?

  2. Si je veux définir une variable d'environnement et l'ajouter à la variable PATH (par exemple, JAVA_HOME), ce serait le meilleur endroit pour placer l'entrée d'exportation? dans ~ / .bash_profile ou ~ / .bashrc ?

  3. Si la réponse à la question 2 est ~ / .bash_profile , j'ai deux autres questions:

    3.1. Que mettriez-vous sous ~ / .bashrc ? seulement des alias?

    3.2. Dans un shell sans connexion, je pense que le fichier ~ / .bash_profile n'est pas "récupéré". Si l'exportation de l'entrée JAVA_HOME était dans bash_profile, pourrais-je exécuter des commandes javac et java ? Les trouverait-il sur le chemin? Est-ce la raison pour laquelle certains messages et forums suggèrent de définir JAVA_HOME et les mêmes comme ~ / .bashrc ?

    Merci d'avance.

Viriato
la source

Réponses:

26

Sur un système moderne, il n’est pas particulièrement courant de se retrouver dans les cas où cela compte, mais cela arrive. (En particulier, si vous utilisez des opérations de shell dans ou vimsous :r !commandla !<motion>commandforme en ligne .)

Que mettriez-vous sous ~ / .bashrc? seulement des alias?

Vous insérez des éléments ~/.bashrcqui ne seraient pas automatiquement hérités par les sous-shell; cela signifie principalement des alias et des fonctions, même si parfois vous avez des paramètres variables que vous ne voulez pas voir visibles à l'extérieur du shell (c'est très rare). On pourrait soutenir que ceux-ci devraient être exportés d'une manière ou d'une autre, mais diverses tentatives expérimentales ont rencontré des problèmes de compatibilité en essayant de les cacher dans l'environnement et ont été pour la plupart abandonnées.

Si je veux définir une variable d'environnement et l'ajouter à la variable PATH (par exemple, JAVA_HOME), ce serait le meilleur endroit pour placer l'entrée d'exportation? dans ~ / .bash_profile ou ~ / .bashrc?

Vous définissez les paramètres d’environnement de ~/.bash_profilemanière à ce que les paramètres initiaux soient corrects. Parfois, vous voudrez les remplacer (souvent par des environnements complexes tels que Matlab ou Cadence); Si vous définissez les paramètres d'environnement, les ~/.bashrcshells exécutés à partir de ces environnements perdront la personnalisation des environnements, ce qui risque de ne pas fonctionner correctement. Cela s'applique également si vous utilisez un package tel que modules , virtualenv , rvm , etc. pour gérer plusieurs environnements de développement. mettre vos paramètres dans ~/.bashrcsignifie que vous ne pouvez pas exécuter l'environnement que vous voulez depuis votre éditeur, mais que vous serez forcé à utiliser les valeurs par défaut du système.

Dans un shell sans connexion, je pense que le fichier ~ / .bash_profile n'est pas "récupéré".

C'est correct; vous voulez normalement que le shell initial soit un shell de connexion et que tous les shell commencés sous celui-ci ne soient pas des shell de connexion. Si le shell initial n'est pas un shell de connexion, vous n'aurez pas de PATHparamètres par défaut ou autres (y compris votre JAVA_HOMEexemple).

La plupart des environnements de bureau lancés à partir de gestionnaires d'affichage (c'est-à-dire la grande majorité des connexions graphiques) ne configurent pas d'environnement de connexion pour l'ensemble du bureau. Vous devez donc exécuter le shell initial dans les terminaux en tant que shell de connexion. Cela pose un certain nombre de problèmes (notamment le fait que les PATHprogrammes disponibles depuis des panneaux, par exemple, ne sont pas configurés correctement, car le panneau n’est pas un terminal et n’a pas fonctionné ~/.bash_profile), mais constitue un compromis raisonnable, étant donné que ce n’est pas toujours possible. à exécuter correctement ~/.bash_profiledans l'environnement non interactif au début d'une session démarrée par un gestionnaire d'affichage, en fonction de son contenu. Il est parfois suggéré de placer les paramètres d’environnement dans~/.bashrcau lieu de configurer un shell de connexion à la place; comme indiqué plus haut, cela fonctionne aussi longtemps que vous n'avez pas besoin de passer outre cet environnement, et les causes bizarres une fois que vous casses faire besoin de le faire.

J'ai récemment aidé à diagnostiquer un problème comme celui-ci sous OS X, dans lequel un utilisateur qui avait placé des paramètres avait ~/.bashrccommencé à utiliser rvmet perlbrew avait eu un comportement étrange, car les environnements configurés par les deux avaient été "défaits" par des ~/.bashrcéditeurs internes et sudo(qui sous OS X). , contrairement à Linux, propage l'utilisateur $HOMEpour qu'il ~/.bashrcsoit exécuté par le shell root). Avant d'essayer d'utiliser ces environnements, il n'y avait pas de problème; en commençant à les utiliser, ils étaient déconcertés par la perte inattendue de leurs réglages.

geekosaur
la source
1
Je pense que je comprends, je vais peut-être devoir le lire plus de fois pour l'intérioriser davantage, mais je conclus ce qui suit. Dans les environnements d'entreprise, afin de contrôler plus précisément les shells personnalisés sans les effets secondaires de celui global, il est recommandé de placer les variables d'environnement dans ~ / .bash_profile . Dans un environnement personnel comme Ubuntu ou Linux Mint pour que le PATH soit correctement défini, je devrais le définir sous ~ / .bashrc (ou même dans / etc / profile ). Ai-je raison?
Viriato
Cela a moins à voir avec les environnements d'entreprise qu'avec le fait que vous soyez simplement un utilisateur ou un développeur; les systèmes aiment moduleset rvmsont des outils de développement, de même que Matlab et Cadence pour des définitions quelque peu différentes de "développeur". Développement simple aussi ne les oblige pas, mais quand vous devez tester contre plusieurs versions de Ruby, Perl, Python ou alors vous voulez vraiment quelque chose comme rvm, perlbrewet virtualenv(respectivement) autour pour aider à garder tout droit.
geekosaur
2

pour être honnête, il y a peu de différence ces jours-ci malgré ce que le gourou avait à dire.

Le problème derrière tout cela est qu’aujourd’hui, nous nous connectons de manière graphique plutôt que par le biais d’un shell de connexion. Dans le passé, nous, les utilisateurs Unix, aimons voir un bref rapport sur ce qui se passe sur un serveur immédiatement après la connexion. Nous démarrons ensuite X par ligne de commande. Ces rapports nécessitent souvent un certain temps pour être générés (par exemple, 10 à 20 secondes). et alors nous ne voulons pas voir la même chose quand nous commençons, par exemple, xterm. donc la différence.

De nos jours, je ne pense pas que la distinction soit importante maintenant. Je pense que ces jours-ci, si vous sourcez bashrc dans bash_profile, personne ne pourrait vous en vouloir.

notez que cela ne s'applique pas à macos x (chaque terminal.app démarré est un shell de connexion)

bubu
la source
Je ne suis pas tout à fait sûr de bien comprendre, mais au travail, lorsque je me connecte via ssh, il s’agit d’un shell de connexion, puis bash_profile et bashrc sont recherchés; Mais si je me connecte graphiquement (qu'est-ce que cela signifie)? comme vous connecter à mon Ubuntu personnel?
Viriato
D'accord avec @bubu, répondez ici - toute configuration dans laquelle la ~/.bash_profilesource ~/.bashrcn'est pas assez difficile à gérer et qui frise . Les applications de terminal graphique signifient qu'il est plus simple de simplement générer ~ / .bashrc et de mettre toute la configuration dans le même fichier.
RichVel
1

Eh bien, à propos des "connexions graphiques", cela dépend du * DM que vous utilisez ...

Avec GDM (Gnome 3.18), j'ai ceci:

/ etc / gdm / Xsession

#!/bin/sh   <= *important*

...

# First read /etc/profile and .profile
test -f /etc/profile && . /etc/profile
test -f "$HOME/.profile" && . "$HOME/.profile"
# Second read /etc/xprofile and .xprofile for X specific setup
test -f /etc/xprofile && . /etc/xprofile
test -f "$HOME/.xprofile" && . "$HOME/.xprofile"

Ainsi, ~ / .profile est identifié lors de la connexion en utilisant / bin / sh et non / bin / bash

Il y a deux cas

  1. / bin / sh est lié à / bin / bash mais s'exécute en mode "POSIX / Bourne"
  2. / bin / sh est / bin / dash (debian / ubuntu). Le plus rapide mais avec moins de fonctionnalités (support ShellShock;) )

Donc, le profil / bin / sh est ~ / .profile et non ~ / .bash_profile, ~ / .zprofile

Ce fichier doit être utilisé pour les paramètres " indépendants du shell" , tels que les variables de chemin et d'environnement.

AUCUN programme exécutable pour une interaction utilisateur uniquement connexion devrait être mais ici (vérification du courrier, fortune, etc ...)

les ~ /.* rc sont uniquement destinés aux sessions "interactives" (alias par exemple ...)

Il existe une différence entre bash et zsh pour les shells de connexion interactifs

sources bash uniquement. profil_bash, tandis que les sources zsh dans l’ordre:

  1. ~ / .zprofile
  2. ~ / .zshrc
  3. ~ / zlogin (ici, les alias définis dans ~ / .zshrc sont disponibles. en cas de shells "interactifs" + "login"

La bonne façon de faire ~ / .bash_profile a été trouvée ici:

Différence entre .bashrc et .bash_profile

if [ -r ~/.profile ]; then . ~/.profile; fi
case "$-" in *i*) if [ -r ~/.bashrc ]; then . ~/.bashrc; fi;; esac

Pour activer le test (et le profilage), vous pouvez utiliser cette

~ / .bash_profile:

#!/bin/bash

# ------------------------------------------------
export _DOT_BASH_PROFILE_0=`date  --rfc-3339=ns`
# ------------------------------------------------

if [ -f ~/.profile ] ; then
    . ~/.profile
fi

case "$-" in *i*) if [ -r ~/.bashrc ]; then . ~/.bashrc; fi;; esac

# ------------------------------------------------
export _DOT_BASH_PROFILE_1=`date  --rfc-3339=ns`
# ------------------------------------------------

~ / .zprofile:

#!/bin/zsh

# ------------------------------------------------
export _DOT_ZSH_PROFILE_0=`date  --rfc-3339=ns`
# ------------------------------------------------

if [ -f ~/.profile ] ; then
    . ~/.profile
fi

# no need to source, zsh already handle ~/.zshrc

###case "$-" in *i*) if [ -r ~/.zshrc ]; then . ~/.zshrc; fi;; esac

# ------------------------------------------------
export _DOT_ZSH_PROFILE_1=`date  --rfc-3339=ns`
# ------------------------------------------------

puis, pour tester:

chsh -s /bin/bash

ssh localhost
env

exit

ssh localhost env

ssh -t localhost bash -i -c env


chsh -s /bin/zsh

ssh localhost
env

exit

ssh localhost env

ssh -t localhost bash -i -c env

Donc RVM / virtualenv devrait aller dans ~ / .profile, IMHO

Mais cela ne marche pas , parfois ...

Par exemple, virualenvwrapper ne fonctionne que si le shell qui exécute Xsession est un bash "original" (exportation BASH_VERSION).

Si vous êtes sur un système de tableau de bord , la variable d’environnement et le paramètre de chemin fonctionnent, mais la définition de la fonction virualenvwrapper ne fonctionne pas car le script n’est pas conforme à POSIX.

Le script ne donne aucune erreur mais il se termine sans définition "workon" .

Vous pouvez donc définir l’environnement actuel dans ~ / .profile , juste pour activer l’exécution correcte de python à partir du client démarré directement à partir de X:

export VIRTUAL_ENV="/home/mike/var/virtualenvs/myvirtualenv"
export PATH="$VIRTUAL_ENV/bin:$PATH"
unset PYTHON_HOME

https://gist.github.com/datagrok/2199506

https://www.bountysource.com/issues/9061991-setting-up-your-computer-virtualenvwrapper-linux-all

Mais pour virualenvwrapper, vous avez deux alternatives:

  1. le source dans ~ / .bash_profile ou ~ / .zprofile (ou ~ / .zlogin) lorsque le terminal agit comme un shell de connexion
  2. inclure le script dans ~ / .bashrc ou ~ / zshrc

Cela signifie que les clients X (emacs par exemple) doivent être lancés à partir du terminal shell et non du graphique!

"Je ne peux obtenir aucune satisfaction ..."

hute37
la source
Une autre histoire complète consiste à faire fonctionner les services avec systemd Voici quelques solutions de rechange possibles: écrire un script wrapper , définir l’environnement dans un fichier de définition "service" , vider l’environnement dans un fichier "env" pour le placer dans un shell parent. Les choses se compliquent avec RVM / virtualenv ...
hute37