2014-11-26 19 views
8

È possibile banalmente uscita il vostro ambiente come uno script di shell eseguibile utilizzandoCome faccio ENV uscita come uno script di shell eseguibile

env > my_env 

... più avanti in un altro script ...

set -a 
source my_env 

Questo funziona per i casi più banali, ma fallisce se sono presenti caratteri speciali o spazi.

Come posso risolvere lo script precedente in modo che funzioni con elementi come a='"'"'"?

+1

esecuzione lo script non fa molto, anche se, dato come non appena è fatto in esecuzione esce, e l'ambiente del suo genitore non cambia un po '. 'source my_env' ha più senso, ma questo non richiede' chmod + x'. –

+0

buon punto rimuovendo il + x come rumore –

risposta

4

Uso set invece di env:

○ → set | grep LESS 
LESS=-R 
LESSCLOSE='/usr/bin/lesspipe %s %s' 
LESSOPEN='| /usr/bin/lesspipe %s' 

○ → env | grep LESS 
LESS=-R 
LESSOPEN=| /usr/bin/lesspipe %s 
LESSCLOSE=/usr/bin/lesspipe %s %s 

Grazie alla this similar question possiamo fare questo per ottenere variabili SOLO ambiente come segue:

○ → (set -o posix; set) | grep LESS 
LESS=-R 
LESSCLOSE='/usr/bin/lesspipe %s %s' 
LESSOPEN='| /usr/bin/lesspipe %s' 

Prova questo colosso che dovrebbe stampare solo la differenza da una shell "incontaminata". YMMV:

diff --old-line-format='%L' --unchanged-line-format= --new-line-format= \ 
    <(bash -c 'set -o posix; set' | sort) \ 
    <(env -i bash -c 'set -o posix; set' | sort) 
4

Di seguito utilizza bash di printf %q per sfuggire valori correttamente indipendentemente dal loro contenuto. È garantito gestire letteralmente qualsiasi valore possibile - virgolette, newline, ecc. A patto che la shell che si basa sull'output sia bash, e fintanto che il sistema operativo in uso supporta la funzione /proc/self/environ fornita da Linux per emettere il contenuto di l'ambiente come un flusso delimitato da NUL. Utilizza forme di citazione speciali come $'\n' come e dove appropriato, quindi il suo output non può essere onorato dagli interpreti POSIX puri.

#!/usr/bin/env bash 
while IFS= read -r -d '' kvname; do 
    k=${kvname%%=*} 
    v=${kvname#*=} 
    printf '%q=%q\n' "$k" "$v" 
done </proc/self/environ 

noti che si vorrà fonte l'uscita, viene eseguito come un eseguibile esterno, se si desidera che l'ambiente shell corrente per cambiare. Se non si desidera effettuare lo set -a prima del sourcing, aggiungere uno export iniziale alla stringa di formato.

+0

Ho appena provato (set -o posix; export) e sembra che faccia il trucco, questo esploderà su di me? –

+0

Dubito che tu abbia bisogno del 'set -o posix' lì, in realtà; 'export' da solo probabilmente sta bene. L'unica cosa che il codice precedente fa meglio delle soluzioni basate su shell nativa sta esponendo le variabili d'ambiente che * non sono * anche variabili di shell valide (ad esempio, quando impostate da linguaggi non shell con nomi non shell-legal), ma il modo in cui si comportano è ... molto variabile comunque. –

+1

@SamSaffron, ... che ha detto, leggendo la documentazione per 'export' (o, se vuoi essere più esplicito, 'export -p'), non lo vedo _garantire_ che il suo output è sicuro per la shell. 'printf '% q'' * garantisce * sicurezza. D'altra parte, affidarsi a '/ proc' è garantito per ridurre la portabilità, quindi questo approccio ha sicuramente le sue insidie, e l'implementazione nelle versioni di bash che sto guardando sembra essere completamente sicura, nonostante non lo garantisca nella documentazione . –

3

soluzione più semplice sembra essere

export -p > my_env 
Problemi correlati