2010-04-18 4 views
36

Comment exporter une variable d'environnement depuis un script Ruby vers le shell parent? Par exemple, la mise en œuvre d'une mise en œuvre naïve du read intégrée Bash:Exportation d'une variable d'environnement dans Ruby

#!/usr/bin/ruby 

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

J'ai vu [une question similaire] (http://stackoverflow.com/questions/190168/persisting-an-environment-variable-through-ruby) mais j'ai ne suis pas satisfi ed avec la réponse spécifique à la plate-forme. – wilhelmtell

Répondre

34

Réponse simple: Vous ne pouvez pas. Réponse plus longue: Vous ne pouvez pas, sauf si l'environnement d'exploitation fournit des crochets pour le faire. La plupart ne le font pas. Le mieux que vous pouvez habituellement faire est d'imprimer les devoirs que vous voulez faire et que le parent les exécute.

+0

Regardez la réponse de Peterk, ça marche aussi sur Windows. Je l'ai essayé avec la commande sh de rake exécutant la commande de dos qui exige l'ensemble d'env dans le râteau. – kite

+5

@kite: "pour le shell parent" –

+1

comme alternative, envisagez de définir un fichier de données d'identification dans un répertoire approprié –

35

Vous ne pouvez pas exporter les variables d'environnement vers le shell dans lequel le script ruby ​​s'exécute, mais vous pouvez écrire un script ruby ​​qui crée un fichier bash source.

Par exemple

% 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 
% 

Une autre alternative est que l'utilisation ENV[]= ne définit les variables d'environnement pour les sous-couches ouvertes à partir du processus de rubis. Par exemple:

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 

Cela peut être très puissant si vous le combinez avec commande exec de la coque, qui remplacera la coque extérieure du processus rubis (de sorte que lorsque vous sortez de la coque intérieure, l'auto enveloppe extérieure -exite aussi, empêchant toute confusion "Je pensais que j'ai mis cette variable dans cette coquille").

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

J'ai juste essayé ceci et il semble bon.

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); 

Cela semble bien fonctionner - au moins sur MacOSX

Je reçois

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

Semble belle en elle restaure l'état avant automatiquement

Ok - essaya un autre comme cela ne génère pas 2 sous-processus

Use Process.spawn(env,command) 

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

Cela agit comme l'appel système C et vous permet de spécifier des tuyaux et tous ces autres trucs aussi.

0

Qu'en est-il ruby ​​l'impression de code standard d'exportation:

puts "export MYVAR=value" 

puis en utilisant backtick shell pour l'obtenir exécuté à comands shell:

$ `./myscript.rb` 

cela prendra la sortie du script et l'exécuter, fonctionne dans des shells modernes comme bash et zsh

+0

Malheureusement, cela ne fonctionne pas non plus, car il n'agit toujours pas directement dans le shell parent. – Julian

Questions connexes