comment exporter des VAR d'un sous-shell vers un shell parent?

10

J'ai un script shell Korn

#!/bin/ksh
# set the right ENV
case $INPUT in
abc)
  export BIN=${ABC_BIN}
  ;;
  def)
  export BIN=${DEF_BIN}
  ;;
  *)
  export BIN=${BASE_BIN}
  ;;
esac
# exit 0 <- bad idea for sourcing the file

maintenant ces VAR sont exportés uniquement dans un sous-shell, mais je veux qu'ils soient également définis dans mon shell parent, donc quand je suis à l'invite, ces vars sont toujours définis correctement.

Je connais

. .myscript.sh

mais existe-t-il un moyen de le faire sans «sourcing»? car mes utilisateurs oublient souvent de «source».


EDIT1: supprimer la partie "exit 0" - c'était juste moi qui tape sans y penser d'abord

EDIT2: pour ajouter plus de détails sur la raison pour laquelle j'ai besoin de cela: mes développeurs écrivent du code pour (par souci de simplicité) 2 applications: ABC et DEF. chaque application est exécutée en production par des utilisateurs distincts usrabc et usrdef, donc ont configuré leurs $ BIN, $ CFG, $ ORA_HOME, peu importe - spécifiques à leurs applications.

donc

  • ABC $ BIN = / opt / abc / bin # $ ABC_BIN dans le script ci-dessus
  • DEF $ BIN = / opt / def / bin # $ DEF_BIN

etc.

maintenant, sur la boîte de développement, les développeurs peuvent développer à la fois ABC et DEF en même temps sous leur propre compte utilisateur 'justin_case', et je leur fais source le fichier (ci-dessus) afin qu'ils puissent changer leurs paramètres var var d'avant en arrière. ($ BIN doit pointer vers $ ABC_BIN à la fois, puis je dois passer à $ BIN = $ DEF_BIN)

maintenant, le script devrait également créer de nouveaux bacs à sable pour le développement parallèle de la même application, etc. cela me fait le faire de manière interactive, en demandant le nom du bac à sable, etc.

  • / accueil / justin_case / sandbox_abc_beta2
  • / accueil / justin_case / sandbox_abc_r1
  • / accueil / justin_case / sandbox_def_r1

l'autre option que j'ai envisagée est d'écrire des alias et de les ajouter au profil de chaque utilisateur

  • setup_env d'alias =. .myscript.sh '

et l'exécuter avec

  • setup_env paramètre1 ... paramètreX

cela a plus de sens pour moi maintenant

webwesen
la source
Oui - vous pouvez le faire avec un alias ou une fonction (je préfère les fonctions moi-même) où vous avez la fonction prod () {export VAR = snoopy; }; et la fonction dev () {export VAR = woodstock; };
chris

Réponses:

11

Je pense que c'est un problème "non possible" ...

Tout d'abord - vous ne voudriez pas source ce script à cause de la sortie 0 à la fin.

Deuxièmement, aucun processus enfant Unix ne peut modifier directement l'environnement du parent. Sinon, toutes sortes de choses folles seraient possibles.

Pourriez-vous ajouter quelque chose à leur environnement avec le profil par défaut ou les fichiers bashrc, ou pourriez-vous écrire un wrapper pour le programme qu'ils essaient d'exécuter?

Permettez-moi de développer le concept de "wrapper".

Supposons que vous souhaitiez exécuter le programme snoopy avec PROD ou DEV dans la variable d'environnement "OPTIONS" selon que vous souhaitez la production ou le développement. SI elle n'est pas définie, disons que snoopy fait quelque chose de loufoque comme effacer la base de données pour la production et le développement ...

renommer "snoopy" en snoopy.bin (ou .snoopy.bin)

puis placez un script au même endroit nommé "snoopy" qui contient ceci:

#!/bin/sh

export OPTIONS

case "$OPTIONS" 
in
  PROD) ;;
  DEV) ;;
  *) OPTIONS=DEV ;;
esac

#the binary is actually named snoopy.bin 

exec "$0.bin" "$@"

Si vous ne voulez pas fouiller avec le fichier réel, placez ce script quelque part dans le système de fichiers qui sera en avance sur le programme snoopy réel dans le PATH de l'utilisateur et ayez un chemin complet vers le binaire dans l'instruction exec du script ...

chris
la source
5

La réponse est le sourcing. Le sourcing vous permet d'inclure des variables dans un script dans le shell courant , mais jamais un parent de cela. C'est vrai, vous devez faire attention à ne pas utiliser de commande de sortie ou similaire, car cela fermerait votre shell actuel.

Vous pouvez source un script en utilisant le ".", C'est-à-dire

. ./myscript.ksh

txwikinger
la source
3

Peut-être que si vous essayez ...

#!/bin/bash

mknod fifo p

(
       echo 'value' > fifo &
)

VARIABLE=`cat fifo`
rm fifo

Ce n'est pas exactement l'exportation de variables, mais cela peut fournir une communication de base avec le processus parent.

oscar
la source
1

OK, ne riez pas maintenant. La solution très rapide et très sale consiste à ajouter

echo "Please copy and paste this command:"
echo ""
echo "export BIN=\"$BIN\""

à votre script.

Une autre approche . Juste execun $ SHELL subordonné dans votre script, peut-être avec une invite différente (changez $ PS1 pour informer les utilisateurs dans quel environnement ils travaillent pour réduire la confusion).

Une autre approche (ma préférée). Les utilisateurs oublient de se procurer votre script, pourquoi? L'approvisionnement est précisément la voie à suivre standard. Peut-être qu'un bon moyen de leur rappeler est de supprimer la première ligne ( #!/bin/sh) puis la chmod a-x. Il peut encore être obtenu par la suite, mais il ne peut évidemment pas être exécuté par erreur.

Rant : Dans l'ensemble, je pense que vous avez eu une idée étrange en premier lieu. Peut-être pas étrange ... Je dirais un style non Unix. Je n'ai jamais eu besoin d'exporter l'environnement pour devenir parent dans ma vie. J'ai vu une fois une situation similaire - connexion .profile demandant lequel des trois environnements différents définir pour un seul compte oracle. Mauvaise idée, au final, il s'est avéré que les utilisateurs préféraient migrer vers sudo (ils ont créé sudo'd vers trois comptes oraxxx différents). Qu'essayez-vous de réaliser, si je puis me permettre?

kubanczyk
la source