Экспорт переменной среды в Ruby - PullRequest
37 голосов
/ 18 апреля 2010

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

#!/usr/bin/ruby

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

Ответы [ 4 ]

36 голосов
/ 18 апреля 2010

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

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

35 голосов
/ 18 апреля 2010

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

Я только что попробовал это, и это выглядит хорошо.

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

0 голосов
/ 16 марта 2015

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

puts "export MYVAR=value"

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

$ `./myscript.rb` 

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...