Как экспортировать переменную среды из Ruby script в родительскую оболочку? Например, реализация наивной реализации read
Bash builtin:
#!/usr/bin/ruby
varname = ARGV[0]
ENV[varname] = STDIN.gets # but have varname exported to the parent process
Как экспортировать переменную среды из Ruby script в родительскую оболочку? Например, реализация наивной реализации read
Bash builtin:
#!/usr/bin/ruby
varname = ARGV[0]
ENV[varname] = STDIN.gets # but have varname exported to the parent process
Простой ответ: вы не можете.
Более длинный ответ: вы не можете, если только операционная среда не делает крючки для этого. Большинство нет. Лучшее, что вы обычно можете сделать, это распечатать задания, которые вы хотите сделать, и выполнить их родительский.
Вы не можете экспортировать переменные среды в оболочку, в которой работает ruby script, но вы можете написать ruby script, который создает исходный файл bash.
Например
% 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
%
Другой альтернативой является то, что использование ENV[]=
устанавливает переменные среды для подоболочек, открытых из рубинового процесса. Например:
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
Это может быть весьма сильным, если вы объедините его с командой shell exec
, которая заменит внешнюю оболочку рубиновым процессом (так что, когда вы выйдете из внутренней оболочки, внешняя оболочка автоматически выйдет, не допуская, что "я думал, что я установил эту переменную в этой оболочке" ).
# open terminal
% exec pass_var.rb BAZ
3
% echo $BAZ
3
% exit
# terminal closes
Я просто попробовал это, и он выглядит хорошо.
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);
Кажется, что это хорошо работает - по крайней мере, на MacOSX
Я получаю
FOO is ""
In child process. parent pid is 1388
FOO is "foo in sub process"
Child (pid 1388) terminated with status 99
FOO is ""
Кажется приятным в нем автоматически восстанавливать предыдущее состояние
Ok - теперь попробовал другой, так как это не порождает 2 подпроцесса
Use Process.spawn(env,command)
pid = Process.spawn({ 'FOO'=>'foo in spawned process'}, cmd );
pid = Process.wait();
Это действует как системный вызов C и позволяет вам указывать каналы и все другие вещи.
Как насчет в ruby распечатывать стандартный экспортный код:
puts "export MYVAR=value"
а затем используя обратную сторону оболочки, чтобы выполнить ее в командах оболочки:
$ `./myscript.rb`
это приведет к выходу script и выполнит его, работает в современных оболочках типа bash и zsh