Подтвердить что ты не робот

Экспорт переменной среды в Ruby

Как экспортировать переменную среды из Ruby script в родительскую оболочку? Например, реализация наивной реализации read Bash builtin:

#!/usr/bin/ruby

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

Ответ 1

Простой ответ: вы не можете.

Более длинный ответ: вы не можете, если только операционная среда не делает крючки для этого. Большинство нет. Лучшее, что вы обычно можете сделать, это распечатать задания, которые вы хотите сделать, и выполнить их родительский.

Ответ 2

Вы не можете экспортировать переменные среды в оболочку, в которой работает 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

Ответ 3

Я просто попробовал это, и он выглядит хорошо.

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 и позволяет вам указывать каналы и все другие вещи.

Ответ 4

Как насчет в ruby ​​распечатывать стандартный экспортный код:

puts "export MYVAR=value"

а затем используя обратную сторону оболочки, чтобы выполнить ее в командах оболочки:

$ `./myscript.rb` 

это приведет к выходу script и выполнит его, работает в современных оболочках типа bash и zsh