2010-04-18 12 views
36

Come esportare una variabile di ambiente da uno script Ruby alla shell padre? Ad esempio, l'implementazione di un'applicazione ingenua del builtin read Bash:Esportazione di una variabile di ambiente in Ruby

#!/usr/bin/ruby 

varname = ARGV[0] 
ENV[varname] = STDIN.gets # but have varname exported to the parent process 
+2

Ho visto [una domanda simile] (http://stackoverflow.com/questions/190168/persisting-an-environment-variable-through-ruby) ma io Non sono soddisfatto con la risposta specifica della piattaforma. – wilhelmtell

risposta

34

Risposta semplice: Non è possibile.

Risposta più lunga: non è possibile, a meno che l'ambiente operativo non fornisca hook per farlo. La maggior parte non lo fa. Il meglio che puoi fare solitamente è stampare i compiti che vuoi eseguire e farli eseguire dal genitore.

+0

guarda la risposta di peterk funziona anche su Windows. L'ho provato con il comando dos di esecuzione di rake's sh che richiede env set in rake. – kite

+5

@kite: "alla shell genitore" –

+1

in alternativa, si consideri l'impostazione di un file di credenziali in una directory appropriata –

35

Non è possibile esportare le variabili di ambiente nella shell in cui viene eseguito lo script ruby, ma è possibile scrivere uno script ruby ​​che crei un file bash sorgente.

Ad esempio

% echo set_var.rb 
#!/usr/bin/env ruby 
varname = ARGV[0] 
puts "#{varname}=#{STDIN.gets.chomp}" 
% set_var.rb FOO 
1 
FOO=1 
% set_var.rb BAR > temp.sh ; . temp.sh 
2 
% echo $BAR 
2 
% 

Un'altra alternativa è che usando ENV[]= non imposta variabili di ambiente per subshells aperte dall'interno del processo rubino. Per esempio:

outer-bash% echo pass_var.rb 
#!/usr/bin/env ruby 
varname = ARGV[0] 
ENV[varname] = STDIN.gets.chomp 
exec '/usr/bin/env bash' 
outer-bash% pass_var.rb BAZ 
quux 
inner-bash% echo $BAZ 
quux 

Questo può essere molto potente se si combinano con il comando exec della shell, che sostituirà l'esterno-shell con il processo di rubino (in modo che quando si esce dal guscio interno, il guscio automatico esterno -esulta pure, impedendo qualsiasi confusione di "Pensavo di impostare quella variabile in questa shell").

# open terminal 
% exec pass_var.rb BAZ 
3 
% echo $BAZ 
3 
% exit 
# terminal closes 
7

Ho appena provato questo e sembra buono.

cmd = "echo \"FOO is \\\"$FOO\\\"\"";         
system(cmd); 

# Run some Ruby code (same program) in the child process 
fork do 
    puts "In child process. parent pid is #$$" 
    ENV['FOO']='foo in sub process'; 
    system(cmd); 
    exit 99 
end 
child_pid = Process.wait 
puts "Child (pid #{child_pid}) terminated with status #{$?.exitstatus}" 

system(cmd); 

Questo sembra funzionare bene - almeno su MacOSX

ottengo

FOO is "" 
In child process. parent pid is 1388 
FOO is "foo in sub process" 
Child (pid 1388) terminated with status 99 
FOO is "" 

Sembra bello in esso ripristina stato precedente automaticamente

Ok - la società ha provato uno diverso come questo non genera 2 sottoprocessi

Use Process.spawn(env,command) 

pid = Process.spawn({ 'FOO'=>'foo in spawned process'}, cmd); 
pid = Process.wait(); 

Funziona come la chiamata di sistema C e consente di specificare pipe e tutte le altre cose.

0

Che dire in Ruby stampare il codice standard dell'esportazione:

puts "export MYVAR=value" 

e quindi utilizzando shell apice inverso per farlo eseguito al Comandi shell:

$ `./myscript.rb` 

questo richiederà l'output dello script e eseguirlo, funziona in shell moderne come bash e zsh

+0

Sfortunatamente, anche questo non funziona, perché non agisce ancora direttamente nella shell genitore. – Julian

Problemi correlati