come esportare VAR da una subshell a una shell genitore?


10

Ho una sceneggiatura della 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

ora questi VAR vengono esportati solo in una subshell, ma voglio che siano impostati anche nella mia shell genitore, quindi quando sono al prompt quei vars sono ancora impostati correttamente.

Lo so

. .myscript.sh

ma c'è un modo per farlo senza "approvvigionamento"? come i miei utenti spesso dimenticano di "fonte".


EDIT1: rimuovere la parte "exit 0" - ero solo io a digitare senza pensare prima

EDIT2: per aggiungere maggiori dettagli sul perché ho bisogno di questo: i miei sviluppatori scrivono codice per (per semplicità) 2 app: ABC e DEF. ogni app viene eseguita in produzione da utenti separati usrabc e usrdef, quindi hanno impostato i loro $ BIN, $ CFG, $ ORA_HOME, qualunque cosa - specifici per le loro app.

così

  • ABC $ BIN = / opt / abc / bin # $ ABC_BIN nello script sopra
  • $ BIN di DEF = / opt / def / bin # $ DEF_BIN

eccetera.

ora, sulla scatola degli sviluppatori gli sviluppatori possono sviluppare contemporaneamente sia ABC che DEF con il proprio account utente 'justin_case', e li faccio sorgente del file (sopra) in modo che possano cambiare le loro impostazioni var ENV avanti e indietro. ($ BIN dovrebbe puntare a $ ABC_BIN alla volta e quindi devo passare a $ BIN = $ DEF_BIN)

ora, lo script dovrebbe anche creare nuovi sandbox per lo sviluppo parallelo della stessa app, ecc. Questo mi fa fare in modo interattivo, chiedendo il nome sandbox, ecc.

  • / Home / justin_case / sandbox_abc_beta2
  • / Home / justin_case / sandbox_abc_r1
  • / Home / justin_case / sandbox_def_r1

l'altra opzione che ho preso in considerazione è scrivere alias e aggiungerli al profilo di ogni utente

  • alias 'setup_env =. .myscript.sh'

ed eseguirlo con

  • setup_env parametro1 ... parametroX

questo ha più senso per me ora


Sì, puoi farlo con un alias o una funzione (preferisco le funzioni io stesso) in cui hai la funzione prod () {export VAR = snoopy; }; e la funzione dev () {export VAR = woodstock; };
chris,

Risposte:


11

Penso che sia un problema "no can do" ...

Primo: non vorrai creare lo script a causa dell'uscita 0 alla fine.

In secondo luogo, nessun processo figlio unix può modificare direttamente l'ambiente del genitore. Altrimenti sarebbe possibile ogni sorta di cose folli.

Potresti aggiungere qualcosa al loro ambiente con il profilo predefinito o i file bashrc o potresti scrivere un wrapper per qualunque programma stiano cercando di eseguire?

Mi permetta di elaborare il concetto di "wrapper".

Supponiamo che tu voglia eseguire il programma snoopy con PROD o DEV nella variabile di ambiente "OPTIONS" a seconda se desideri produzione o sviluppo. Se non è impostato, diciamo che snoopy fa qualcosa di divertente come cancellare il database per la produzione e lo sviluppo ...

rinominare "snoopy" in snoopy.bin (o .snoopy.bin)

quindi inserisci uno script nella stessa posizione denominata "snoopy" che contiene questo:

#!/bin/sh

export OPTIONS

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

#the binary is actually named snoopy.bin 

exec "$0.bin" "$@"

Se non vuoi confondere con il file reale, metti questo script da qualche parte nel filesystem che sarà davanti al programma snoopy reale nel PATH dell'utente e avrà un percorso completo al binario nell'istruzione exec dello script ...


5

La risposta è approvvigionamento. Il sourcing ti consente di includere variabili in uno script nella shell corrente , ma mai un genitore di quello. È vero, devi stare attento a non usare alcun comando di uscita o simile, perché ciò chiuderebbe la tua shell corrente.

Puoi creare uno script usando ".", Ad es

. ./myscript.ksh



3

Forse se provi ...

#!/bin/bash

mknod fifo p

(
       echo 'value' > fifo &
)

VARIABLE=`cat fifo`
rm fifo

Non è esattamente l'esportazione variabile, ma può fornire comunicazioni di base con il processo padre.


1

OK, non ridere adesso. La soluzione molto veloce e molto sporca è aggiungere

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

alla tua sceneggiatura.

Un altro approccio . Solo execun $ SHELL subordinato nel tuo script, magari con un prompt diverso (cambia $ PS1 per avvisare gli utenti in quale ambiente stanno lavorando per ridurre la confusione).

Un altro approccio (il mio preferito). Gli utenti dimenticano di creare il tuo script, perché? Il sourcing è esattamente il modo standard di procedere. Forse un buon modo per ricordare loro è quello di rimuovere la prima riga ( #!/bin/sh) e poi chmod a-x. Dopo ciò può essere ancora reperito, ma ovviamente non può essere erroneamente eseguito.

Rant : Tutto sommato, penso che tu abbia avuto una strana idea in primo luogo. Forse non strano ... Direi un po 'non-Unix in stile. Non ho mai avuto bisogno di esportare l'ambiente come genitore in vita mia. Una volta ho visto una situazione simile: accedi a .profile chiedendo quale dei tre diversi ambienti impostare per un singolo account Oracle. Pessima idea, alla fine si è scoperto che gli utenti preferivano migrare su sudo (hanno eseguito sudo su tre account oraxxx diversi). Cosa stai cercando di ottenere, se posso chiedere?

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.