Où dois-je exporter une variable d'environnement pour que toutes les combinaisons de bash / dash, interactif / non interactif, connecté / non connecté, la récupèrent?

11

Voici la motivation de la question:

J'utilise Ubuntu 12.04 LTS 2 avec le bureau Unity. Dans mon fichier .bashrc, j'ajoute plusieurs répertoires à ma variable PATH et je définis quelques variables d'environnement, telles que JAVA_HOME. Lorsque je lance des applications à partir d'un terminal (exécutant bash, mon shell par défaut), cela fonctionne très bien, mais pour plusieurs des raccourcis qui utilisent le lanceur Unity, ils exécutent des applications qui semblent définies pour utiliser #! / Bin / sh, qui est aliasé vers / bin / dash, et ils ne récupèrent pas le contenu de ~ / .bashrc ou ~ / .profile.

Je suppose que je pourrais changer tous ces raccourcis pour utiliser / bin / bash au lieu de / bin / sh pour le forcer à reprendre les modifications de .bashrc, mais cela semble vraiment hacky.

Étant donné qu'Ubuntu 12.04 (par défaut) alias / bin / sh vers / bin / dash et que mon shell par défaut est / bin / bash, existe-t-il un seul endroit où je peux choisir de modifier le CHEMIN et définir des variables d'environnement si je les veux être présent dans toutes ces circonstances:

  1. Chaque fois que je crée un shell bash sans connexion (en utilisant le terminal dans l'unité)
  2. Chaque fois que je crée un shell bash de connexion (par exemple, connexion à distance via ssh)
  3. Chaque fois que j'utilise un lanceur d'application Unity (étant donné que le lanceur utilise / bin / sh).
  4. Chaque fois qu'un travail cron s'exécute (étant donné que SHELL = / bin / sh dans / etc / crontab).

Si je comprends bien, je suppose que:

  • (1) / (2) et (3) / (4) sont différents car (1) / (2) sont bash et (3) / (4) sont tirets.
  • (1) et (2) sont différents car les fichiers que bash choisit de charger diffèrent selon qu'il s'agit ou non d'un shell de connexion.
  • (3) et (4) sont différents parce que (3) viendra à un moment donné après que je me suis connecté (et donc ~ / .profile aura été trouvé par l'un de ses processus parents, tandis que (4) viendra à un moment donné quand je ne suis pas connecté, et donc ~ / .profile n'aura pas été lu.

(Je ne serais pas surpris si d'autres facteurs importaient aussi, comme le fait que le shell soit interactif ou non, donc il y a probablement plus de combinaisons que je n'avais même pas anticipées ... Je suis heureux d'avoir ma question "améliorée" " dans ce cas.)

Je m'attendrais à ce qu'à un moment donné, quelqu'un ait créé une sorte de guide qui vous indique comment / où modifier les variables d'environnement de manière indépendante du shell (ou au moins d'une manière compatible avec les tirets / bash) ... Je peux juste ' t semble trouver les bons termes de recherche pour trouver un tel guide.

Des solutions ou des pointeurs vers des solutions très appréciés!

Actualisé:

  • Clarification: Il s'agit de l'utilisateur Ubuntu par défaut créé par le processus d'installation 12.04, donc rien de spécial. Il ne dispose d' un ~ / .profile (qui explicitement les sources ~ / .bashrc), et le seul ~ / .bash * fichiers présents sont .bashrc, .bash_history et .bash_logout ... donc pas qu'il n'y a pas .bash_profile.
  • Accent sur la portée: je ne me soucie pas vraiment des shells autres que le shell interactif par défaut (bash) et de tout script qui utilise / bin / sh (aliasé en tiret), donc il n'y a pas besoin de compliquer cela avec quelque chose de plus pour tcsh / ksh / zsh / etc. soutien.
Mickalot
la source
2
Placez-le dans un fichier puis laissez les autres fichiers rc le source.
konsolebox
Selon la page de manuel du tableau de bord que j'ai ici, il devrait lire $ HOME / .profile pour les shells de connexion.
Etan Reisner
@konsolebox Quels fichiers rc? AFAICT, dash n'a pas de fichier rc. Et comme je l'ai dit, dash ne semble pas récupérer le contenu de ~ / .profile.
@EtanReisner Oui, et c'est le point de la question. Lorsque dash ne fonctionne pas en tant que shell de connexion (et donc que ~ / .profile n'est pas fourni), que se passe-t-il alors?
@Mickalot Exécutez-vous Dash de manière interactive? Sinon, essayez d'y ajouter l'option -l.
konsolebox

Réponses:

9

L'invocation de shell est un peu compliqué. Les pages de manuel bash et dash contiennent des INVOCATIONsections à ce sujet.

En résumé, ils disent (il y a plus de détails dans la page de manuel, vous devriez le lire):

When bash is                   | it reads
-------------------------------|----------
login shell                    | /etc/profile and then the first of ~/.bash_profile, ~/.bash_login or ~/.profile that exists.
                               |
interactive non-login shell    | /etc/bash.bashrc then ~/.bashrc
                               |
non-interactive shell          | The contents of $BASH_ENV (if it exists)
                               |
interactive (as "sh")          | The contents of $ENV (if it exists)

-

When dash is                   | it reads
-------------------------------|---------
login shell                    | /etc/profile then .profile
                               |
interactive shell              | The contents of ENV (it it exists, can be set in .profile as well as in initial environment)

Je ne connais pas les autres coquilles à la légère car je n'en utilise jamais. Votre meilleur pari pourrait être de définir quelques variables d'environnement pour pointer vers le script d'emplacement commun et de les récupérer manuellement (le cas échéant) dans les deux cas non couverts.

Etan Reisner
la source
Malheureusement, le nœud de ce problème est celui qui manque dans votre tableau de bord. Lorsque le bureau Unity invoque un script commençant par #! / Bin / sh, il lance (ce que je suppose) un shell de tableau de bord non connecté et non interactif. La question est donc: comment puis-je faire les mêmes variables d'environnement il qui sont présents partout ailleurs dans la matrice?
Droite. J'imagine que c'est pourquoi bash a ajouté BASH_ENV pour cet emplacement. Étant donné que le tableau de bord ne semble pas avoir quelque chose qui fonctionne dans cet emplacement, je ne suis pas sûr que vous puissiez résoudre ce problème sans affecter le changement dans l'environnement d'application qui lance le tableau de bord (tel que le tableau de bord en hérite). Cela nécessiterait que les variables d'environnement soient définies dans votre environnement X, où le commentaire .xsession (rc) de @Mickalot entre en jeu. Comme il l'a indiqué, cela laisse toujours de côté le point quatre (mais je crois que c'est en fait quelque peu intentionnel).
Etan Reisner
Puisque je suis sur Ubuntu 12.04 LTS, cron est en fait pixie-cron, donc je peux définir des variables env dans mon fichier crontab ... Je suppose que SHELL = / bin / bash et BASH_ENV = ~ / .bashrc devrait le faire?
3

Il y a donc plusieurs façons d'aborder cela. Beaucoup de gens:

une. Avoir un fichier qui a des choses communes à toutes vos coquilles de style sh, disons .shcommonet dans chacun des .profile .bashrc .kshrcet cetra, sourcez-le simplement avec. .shcommon

b. Mettez tout .profileet sourcez-le à partir des autres fichiers.

Les éléments nécessaires pour des shells spécifiques ou pour des shells interactifs ou non interactifs peuvent ensuite être placés dans le fichier approprié avant de s'approvisionner. .shcommon

Personnellement, je n'aime pas gérer plusieurs fichiers. Donc, j'utilise l'approche suivante:

Tout d'abord, tout ce dont j'ai besoin va dans .profile Comme j'ai des choses spécifiques à bash et ksh, je détermine le nom du shell actuel en utilisant ce qui suit:

# get name of current shell
# strip leading - from login shell
export SHELLNAME="${0#-}"

puis avoir des commandes pour des shells spécifiques dans quelque chose comme ce qui suit (certains préféreraient une déclaration de cas).

if [ "$SHELLNAME" = 'bash' ]
then
    shopt -s checkwinsize

elif [ "$SHELLNAME" = 'ksh' ]
then
    stty erase ^?
fi

Si j'ai des commandes qui ne doivent s'exécuter que dans des shells interactifs, j'utilise ce qui suit:

# check for interactive flag i in shell options $-
# in bash and ksh you could use the following, but breaks in dash
# if [[ $- == *i* ]]
if [ "$(echo $- | grep i)" != "" ]
then
  fortune
fi

Les choses qui sont courantes dans toutes les coquilles de style sh, par exemple, PATHpeuvent simplement aller en haut.

Ensuite, j'utilise des liens symboliques pour charger ce même fichier dans tous les shells de style sh:

ln -s .profile .bashrc
ln -s .profile .kshrc

Quelques notes annexes, si vous en avez un .bash_profile, alors bash le chargera au lieu de .profilemais dash et ksh continueront de se charger .profile Cela peut faire partie de votre problème.

En outre, vous voudrez peut-être envisager d'utiliser #!/bin/bashdans vos scripts au lieu de, #!/bin/dashsauf si vous voulez vraiment des scripts compatibles POSIX. bash a beaucoup de fonctionnalités supplémentaires qui sont très agréables et dash ou bash invoquées car sh désactivera beaucoup de ces fonctionnalités.

De plus, la page de manuel bash explique bien quand .profileversus .bashrcest chargé. Des règles similaires s'appliquent à ksh. le tableau de bord se charge .profileà la connexion et vous permet de charger un fichier au démarrage des shells interactifs qui est spécifié à l'aide de la ENVvariable d'environnement dans .profile(consultez également la page de manuel du tableau de bord et recherchez .profile).


la source
Ne pourriez-vous pas simplement tester $ 0 pour le nom du shell? Y a-t-il des coquilles / cas où cela ne fonctionne pas?
Etan Reisner
De même, la vérification de i dans $ - ne suffit-elle pas pour le test interactif du shell? (Il se déclenchera sur des shells interactifs sans tty que j'accorde mais cela peut ou non être un effet secondaire indésirable.)
Etan Reisner
@Etan: Hrm, je sais que j'ai d'abord essayé $0et rencontré des problèmes ... Je n'arrive pas à me souvenir exactement de ce qu'ils étaient. La connexion directe à la console apparaît $0comme -bashau lieu de bashmais cela pourrait être résolu.
@Etan: Oui, vérifier i in $-fonctionnerait également. Je devrais penser à quand vous auriez un shell interactif sans tty? Votre solution a une meilleure "sensation" pour une raison quelconque, je peux changer cela.
L' -entrée -bashsignifie "shell de connexion" mais oui, vous devrez en tenir compte dans les endroits où vous testez la valeur ou souhaitez l'afficher à quelqu'un.
Etan Reisner
0

Étant donné que les cas (1) et (2) sont résolus en recherchant mes variables d'environnement dans .bashrc et .profile, la vraie question est "quel est le nom du fichier où je source ces mêmes variables pour (3) et (4).

Il semble qu'il y ait une réponse à la partie (3) de la question (comment puis-je obtenir la variable d'environnement à importer dans le bureau Unity) sur askubuntu . La suggestion consiste à créer un fichier ~ / .xsessionrc qui proviendra de / etc / X11 / Xsession. (J'ai essayé cela, et cela semble fonctionner ... yay!)

Je suis toujours perplexe par quoi faire pour (4). Certes, si je crée un travail cron (ou démon), je peux remplacer '/ bin / foo' par quelque chose comme 'bash -i -c / bin / foo' pour le forcer à utiliser bash pour charger les bonnes variables d'environnement, mais cela signifie également que je devrai bricoler avec des outils tiers qui pourraient installer des tâches démon ou un travail cron en mon nom. Yuk.

Mickalot
la source