web-dev-qa-db-fra.com

Exportation d'une variable d'environnement en Ruby

Comment exporter une variable d'environnement depuis un script Ruby vers le shell parent? Par exemple, implémentation naïve de la variable read Bash:

#!/usr/bin/Ruby

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

Réponse simple: vous ne pouvez pas.

Réponse plus longue: vous ne pouvez pas le faire, à moins que l'environnement d'exploitation ne le permette. La plupart n'en ont pas. Le mieux que vous puissiez faire est d’imprimer les tâches que vous voulez faire et de les faire exécuter par le parent.

36

Vous ne pouvez pas exporter de 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 pouvant être utilisé comme 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 de ENV[]= définit les variables d'environnement pour les sous-shell ouverts à partir du processus Ruby. 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 assez puissant si vous le combinez avec la commande exec du Shell, qui remplacera le processus Shell extérieur par le processus Ruby (de sorte que lorsque vous quittez le Shell intérieur, le Shell extérieur se ferme automatiquement, empêchant ainsi toute " J'ai mis cette variable dans ce shell "confusion".

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

Je viens d'essayer cela et ça a l'air bien.

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 - du 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 Nice en il restaure automatiquement l'état antérieur

Ok - maintenant essayé un autre, car 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 éléments.

7
peterk

Qu'en est-il de Ruby imprimant le code d'exportation standard: 

puts "export MYVAR=value"

puis en utilisant backtick Shell pour le faire exécuter sur les commandes Shell: 

$ `./myscript.rb` 

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

0
Seeder