Экспортировать переменную окружения в Ruby



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



#!/usr/bin/ruby

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

4 ответов:

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

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

Вы не можете экспортировать переменные среды в оболочку, в которой выполняется скрипт ruby, но вы можете написать сценарий ruby, который создает исходный файл 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[]= устанавливает переменные среды для вложенных ячеек, открытых из процесса ruby. Например:

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 

Это может быть довольно мощным, если вы объедините его с командой оболочки exec, которая заменит внешнюю оболочку процессом ruby (так что когда вы выходите из внутренней оболочки, внешняя оболочка также автоматически выходит, предотвращая любую путаницу "я думал, что установил эту переменную в этой оболочке").

# 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 ""

Кажется приятным в нем восстанавливает предыдущее состояние автоматически

Ок-теперь попробовал другой, так как это не порождает 2 подпроцесса

Use Process.spawn(env,command)

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

Это действует как системный вызов C и позволяет вам указывать трубы и все остальное тоже.

Как насчет в ruby печати стандартного кода экспорта:

puts "export MYVAR=value"

И затем, используя Shell backtick, чтобы он выполнялся в командах shell:

$ `./myscript.rb` 

Это возьмет вывод скрипта и выполнит его, работает в современных оболочках, таких как bash и zsh

Comments

    Ничего не найдено.