web-dev-qa-db-fra.com

Ajoutez des répertoires à $ PATH sans vous répéter

Mon shell est zsh et le système d'exploitation est Ubuntu 13.04

J'ai besoin d'ajouter un répertoire à $ PATH pour le faire fonctionner aux endroits suivants:

  • En environnement graphique (Unity) (telles que les applications de démarrage, gmrun programme exécuté par raccourci (il s’agit essentiellement de "Commande exécutée" sur alt + f2)
  • En terminal dans Unity
  • Dans le terminal sur Ctrl + Alt + F1

Je l'ai ajouté dans .profile et cela fonctionne pour les deux premiers points, mais pas pour le dernier. Je sais que je peux l’ajouter à .zshrc mais dans ce cas, il sera écrit en deux endroits (viole DRY) et dans le cas d’un terminal dans l’unité, ce sera deux fois en $PATH (je pense pas que c’est très mauvais mais au moins pas joli)

Si je l’ajoute uniquement à .zshrc cela ne fonctionne que pour les deuxième et troisième cas (évidemment)

Que puis-je faire?

5
RiaD

Cette réponse est essentiellement basée sur celle d’Eliah Kagan et contient ce que j’ai vraiment fait.

J'ai ajouté à ~/.pam_environment

PATH DEFAULT=${PATH}:/home/riad/scripts

Mais au moins sur mon PC, il n’a pas été analysé sur tty1 (Ctrl+Alt+F1), mais a été analysé lors de la connexion graphique. (Même les paramètres régionaux créés par l'unité ne fonctionnaient pas avec une connexion non graphique)

La raison en est qu'il y avait une ligne suivante dans le fichier de configuration de pam pour lightdm (/etc/pam.d/lightdm):

session required        pam_env.so readenv=1 user_readenv=1 envfile=/etc/default/locale

J'ai ajouté la même ligne à /etc/pam.d/login entre

@include common-session

et

@include common-password

Faites attention! Mauvais fichier .pam_environment peut rompre votre connexion.

1
RiaD

Définition d'une variable d'environnement pour toutes les connexions (peu importe le type)

Le meilleur moyen consiste à utiliser _~/.pam_environment_. Par exemple, pour ajouter _/opt/blah/bin_ à la fin de votre PATH , vous mettriez ceci dans le fichier _.pam_environment_ de votre répertoire personnel:

_PATH DEFAULT=${PATH}:/opt/blah/bin
_

Définition globale des variables d'environnement (mais ne le faites pas sauf si vous en avez besoin)

Si vous souhaitez ajouter quelque chose à PATH pour tous les utilisateurs , utilisez plutôt _/etc/environment_. De façon confuse, _/etc/environment_ et _~/.pam_environment_ n'utilisent pas la même syntaxe. Bien qu’aucun d’eux ne soit réellement un script, _/etc/environment_ ressemble à un script ( sans n’importe quelle commande export). Donc, si vous voulez ajouter _/opt/blah/bin_ à la fin de PATH de tout le monde, et la ligne PATH dans _/etc/environment_ a commencé par

_PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
_

alors vous le changeriez en:

_PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/blah/bin"_

Une analyse

La plupart des shells de type Bourne, y compris bash, génèrent _~/.profile_ quand ils sont démarrés en tant que shell de connexion. zsh est une exception inhabituelle; cela ne se fera que s’il est appelé avec l’un des coquillages traditionnels de type Bourne. C'est-à-dire que si vous call zsh du nom sh ou ksh (le plus souvent obtenu en créant un lien symbolique vers zsh avec l'un de ces noms), il se comportera comme eux et la source _~/.profile_ (s'il s'agit d'un shell de connexion). Sinon, ce ne sera pas. (Source: man zsh .)

C’est pourquoi zsh dans une session de console virtuelle (par exemple, où vous allez à Ctrl+Alt+F1) ne définit pas la variable d’environnement PATH à partir de _~/.profile_. C'est un shell de connexion, mais zsh est spécial; il ne se comporte pas comme des coquilles de style Bourne traditionnel à moins de prétendre en être un.

Pourquoi zsh exécutant une fenêtre de terminal contient-il les variables d’environnement définies dans _~/.profile_? Parce que , ils étaient déjà définis dans votre session graphique avant le lancement du terminal . Lorsque vous vous connectez graphiquement, le gestionnaire d'affichage (qui fournit l'écran de connexion graphique et gère les sessions graphiques) agit comme un shell de connexion . Habituellement, il source _~/.profile_ (bien que ce ne soit pas garanti ), et occasionnellement, une personne modifie les environnements de bureau uniquement pour découvrir que _~/.profile_ n'est plus lorsqu’ils se connectent graphiquement).

Rien sur les consoles virtuelles textuelles permettant à _~/.profile_ de ne pas être généré. Par exemple, si votre shell était bash au lieu de zsh et que vous vous êtes connecté à une console virtuelle, _~/.profile_ serait généré. Le problème est que, contrairement au comportement fiable d’un Shell de style Bourne traditionnel et au comportement moins fiable d’un gestionnaire d’affichage qui démarre une session de connexion graphique, zsh ne source pas _~/.profile_ quand il s’agit de votre shell de connexion.

De même, avec les variables d'environnement définies dans _~/.profile_, si vous vous connectiez à distance (par exemple, en activant SSH et en vous connectant de cette manière), _~/.profile_ ne serait pas généré.

Cela s'applique également au fichier global _/etc/profile_. Si vous définissez des variables d'environnement globalement, le comportement que vous rencontrez serait identique à celui que vous avez défini pour les utilisateurs dans _~/.profile_.

La solution à condition que vous n’ayez pas besoin d’écrire un test scripté pour déterminer le contenu de vos variables d’environnement, consiste à définir des variables d’environnement spécifiques à l’utilisateur dans _~/.pam_environment_ et dans tout le système (c.-à-d., pour tous les utilisateurs) dans _/etc/environment_.

Lorsque vous faites cela, PAM (en particulier, pam_env.so ) définit les variables lors de la connexion, pour pratiquement chaque type de connexion, et le fait avant le shell de connexion (par exemple, zsh, bash pour la plupart des gens) ou un objet semblable à login-Shell (par exemple, un gestionnaire d'affichage) utilise ses propres fichiers de configuration de connexion. C’est le moyen généralement recommandé de définir les variables d’environnement sur Ubuntu .

Cela résout le problème de certains shells de connexion qui ne recherchent pas toujours _~/.profile_ et _/etc/profile_ (qui est le problème que vous rencontrez). Cela résout également le problème occasionnel d’un gestionnaire d’affichage qui n’approvisionne pas ce fichier car il initialise une session de connexion graphique (c’est un problème que vous rencontrez not ).

Des alternatives

Et qu'est-ce qui se passerait si:

  • vous devez définir des variables d'environnement lors de la connexion, en fonction des résultats de tests scriptés? ou
  • vous ne voulez simplement pas utiliser _.pam_environment_ (ou pour les variables système, _/etc/environment_?

Si vous n'utilisiez pas zsh, mais plutôt bash ou un autre shell de style Bourne plus traditionnel, vous pouvez simplement définir vos variables d'environnement dans _~/.profile_ (ou _/etc/profile_ pour les variables système). Il arrive parfois qu’une configuration ne les configure pas pour les sessions de connexion graphiques, mais qu’elle fonctionne habituellement.

En les définissant dans _~/.bashrc_ ne fonctionnera pas à cette fin . Essentiellement, seules les sources bash de ce fichier sont remplies. Il ne fonctionnera donc pas si zsh est votre shell de connexion ni lorsque le gestionnaire d’affichage joue le rôle de votre shell de connexion. (En d'autres termes, dans votre situation, cela ne fonctionnera jamais.)

Ainsi, si vous avez besoin d’un script provenant de tous les types de connexion et que _~/.profile_ soit utilisé pour vos sessions graphiques, vous pouvez simplement:

  • modifier la configuration de zsh en source _~/.profile_, ou
  • rendez la configuration de zsh et _~/.profile_ source un troisième fichier partagé. (Cela pourrait même être ajouté à un fichier de configuration séparé pour les sessions graphiques, tel que _.xsession_ , si cela s'avérait nécessaire ultérieurement.)

La deuxième solution est préférable si vous n'avez pas lu le contenu de ~/.profile _and made sure they--and the contents of any script sourced from_. Profile _--won't cause problems if sourced by_ zsh`. (Cela ne devrait généralement pas, mais on ne sait jamais.)

Le meilleur fichier de configuration à modifier pour créer zsh source _~/.profile_ (ou un autre script) lors de la connexion est _~/.zprofile_. Cela correspond à _~/.profile_ sur des coquilles plus traditionnelles de style Bourne. (À strictement parler, c'est _$ZDOTDIR/.zprofile_, mais _$ZDOTDIR_ est typiquement _~_.)

Vous ajouteriez la ligne _source $HOME/.profile_ à ce fichier.

J'insiste cependant sur le fait que si vous devez simplement effectuer une affectation simple à des variables d'environnement (y compris une affectation récursive, une expression contenant elle-même et/ou d'autres variables d'environnement est affectée à une variable d'environnement), vous devez simplement utiliser _~/.pam_environment_ comme expliqué ci-dessus (ou _/etc/environment_ pour les variables d'environnement à l'échelle du système).

4
Eliah Kagan

Tout d’abord, vous pouvez simplement source votre fichier .profile dans votre fichier .zshrc.

De plus, comme vous utilisez zsh, vous pouvez ajouter ce qui suit à votre .zshrc:

typeset -U path

# If you want it at the front of your path
path=({/custom/path/bin "${path[@]}")

# If you want it at the end of your path
path+=(/custom/path/bin)

Comment ça marche:

Dans zsh, la variable $PATH est liée à la variable $path; $path est un tableau et $PATH est un scalaire avec les éléments de $path réunis par : (identique à ${(j|:|)path}). typeset -U path rend les éléments du tableau path (et donc le $PATH) uniques.

   typeset [ {+|-}AEFHUafghklprtuxmz ] [ -LRZi [ n ]] [ name[=value] ... ]
   typeset -T [ {+|-}Urux ] [ -LRZ [ n ]] SCALAR[=value] array [ sep ]
          Set or display attributes and values for Shell parameters.
          (...)
          -U     For  arrays  (but  not for associative arrays), keep only
                 the first occurrence of each duplicated value.  This  may
                 also  be  set for colon-separated special parameters like
                 PATH or FIGNORE, etc.  This flag has a different  meaning
                 when used with -f; see below.
1
Kevin