2010-04-18 44 views
36

Làm cách nào để xuất biến môi trường từ bên trong tập lệnh Ruby sang trình bao gốc? Ví dụ: triển khai thực hiện ngây thơ của nội dung Bash read Bash:Xuất biến môi trường trong Ruby

#!/usr/bin/ruby 

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

Tôi đã nhìn thấy [một câu hỏi tương tự] (http://stackoverflow.com/questions/190168/persisting-an-environment-variable-through-ruby) nhưng tôi 'không thỏa mãn ed với câu trả lời theo nền tảng cụ thể. – wilhelmtell

Trả lời

34

Câu trả lời đơn giản: Bạn không thể.

Câu trả lời dài hơn: Bạn không thể, trừ khi môi trường hoạt động cung cấp móc để làm như vậy. Hầu hết thì không. Tốt nhất bạn thường có thể làm là in ra các bài tập bạn muốn thực hiện và có cha mẹ thực hiện chúng.

+0

nhìn vào câu trả lời của peterk nó hoạt động trên các cửa sổ quá. Tôi đã thử nó với lệnh dos thực hiện lệnh rake đòi hỏi bộ env trong vòng cào. – kite

+5

@kite: "vào trình bao" " –

+1

làm phương án thay thế, hãy xem xét đặt dấu chấm câu thông tin trong thư mục thích hợp –

35

Bạn không thể xuất biến môi trường vào vỏ tập lệnh ruby ​​chạy, nhưng bạn có thể viết tập lệnh ruby ​​tạo tệp bash nguồn có thể.

Ví dụ

% 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 
% 

Một lựa chọn khác là sử dụng ENV[]= không đặt biến môi trường cho subshells mở từ bên trong quá trình ruby. Ví dụ:

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 

này có thể khá mạnh nếu bạn kết hợp nó với exec lệnh của vỏ, sẽ thay thế bên ngoài vỏ với quá trình ruby ​​(để khi bạn thoát khỏi vỏ bên trong, bên ngoài vỏ ô tô -exits là tốt, ngăn chặn bất kỳ "Tôi nghĩ rằng tôi đặt biến trong vỏ này" nhầm lẫn).

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

Tôi vừa thử điều này và có vẻ tốt.

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); 

Điều này dường như làm việc tốt - ít nhất là trên MacOSX

tôi nhận được

FOO is "" 
In child process. parent pid is 1388 
FOO is "foo in sub process" 
Child (pid 1388) terminated with status 99 
FOO is "" 

vẻ đẹp trong nó khôi phục trạng thái trước khi tự động

Ok - bây giờ cố gắng một chương trình khác như điều này không sinh ra 2 quy trình con

Use Process.spawn(env,command) 

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

Hành vi này giống như cuộc gọi hệ thống C và cho phép bạn chỉ định đường ống và tất cả những thứ khác nữa.

0

gì về trong ruby ​​in ra mã số xuất tiêu chuẩn:

puts "export MYVAR=value" 

và sau đó sử dụng backtick vỏ để làm cho nó thực hiện tại comands shell:

$ `./myscript.rb` 

này sẽ đưa người ra của kịch bản và thực hiện nó, hoạt động trong các vỏ hiện đại như bash và zsh

+0

Thật không may, điều đó không hoạt động, bởi vì nó vẫn không hoạt động trực tiếp trong shell cha. – Julian

Các vấn đề liên quan