Migliorare un po 'la risposta di @ takeccho ... Controlli e alcuni fischi. Innanzitutto, l'ambiente di origine viene pulito tramite env -i
, che è una misura di sicurezza ma potrebbe non essere desiderato in alcuni casi. In secondo luogo, tramite set -a
, tutte le variabili impostate nel file vengono "esportate" dalla shell e quindi importate in ruby. Questo è utile per simulare/sovrascrivere il comportamento trovato nei file di ambiente usati con gli script init e i file systemd env.
def ShSource(filename)
# Inspired by user takeccho at http://stackoverflow.com/a/26381374/3849157
# Sources sh-script or env file and imports resulting environment
fail(ArgumentError,"File #{filename} invalid or doesn't exist.") \
unless File.exist?(filename)
_newhashstr=`env -i sh -c 'set -a;source #{filename} && ruby -e "p ENV"'`
fail(ArgumentError,"Failure to parse or process #{filename} environment")\
unless _newhashstr.match(/^\{("[^"]+"=>".*?",\s*)*("[^"]+"=>".*?")\}$/)
_newhash=eval(_newhashstr)
%w[ SHLVL PWD _ ].each{|k|_newhash.delete(k) }
_newhash.each{|k,v| ENV[k]=v } # ENV does not have #merge!
end
Principio di funzionamento: Quando rubino emette dell'oggetto ENV usando p
, lo fa in un modo che rubino può leggere nuovamente come un oggetto. Quindi usiamo la shell per generare il file di destinazione e ruby (in una sub-shell) per produrre l'ambiente in quella forma serializzabile. Quindi acquisiamo l'output di ruby e lo eval
all'interno del nostro processo di ruby. Chiaramente questo non è privo di rischi, quindi per mitigare il rischio, noi (1) convalidiamo il nome del file che è passato e (2) convalidiamo usando una regexp che la cosa che torniamo dalla sottotitola ruby è, infatti, una stringa hash serializzabile. Una volta sicuri, eseguiamo lo eval
che crea un nuovo hash. Quindi "manualmente" unire l'hash con ENV
, che è un Object
e non un normale Hash
. Se si trattasse di un hash, avremmo potuto utilizzare il metodo #merge!
.
MODIFICA: sh -a
elementi esportati come PATH
. Dobbiamo anche rimuovere SHLVL
e PWD
prima della hash-unione.
Cosa ottieni se cambi il tuo script con questo? #!/Usr/bin/env ruby mette ENV ['HAPPYTIMES'] – Henry
è una cosa degna di accedere alle funzioni di tipo di sistema operativo come l'impostazione dell'ambiente dalle lingue. Python ha os.environ, c'è un modulo simile in Ruby come in python? cf http://stackoverflow.com/questions/4906977/python-environment-variables e http://docs.python.org/2/library/os.html – bootload
possibile duplicato di [Uscire da ruby mentre si imposta una variabile di ambiente ] (http://stackoverflow.com/questions/8301294/shell-out-from-ruby-while-setting-an-environment-variable) – durron597