2011-11-28 6 views
18

Tôi cần phải trình bao ra một quá trình trong khi thiết lập một biến môi trường cho nó. Tôi đã thử một lớp lót này:Shell ra khỏi ruby ​​trong khi thiết lập một biến môi trường

system "RBENV_VERSION=system ruby extconf.rb" 

Cú pháp này hoạt động trong tập lệnh shell chứ không phải từ ruby. (Cập nhật:. quay ra cú pháp này hoạt động từ ruby ​​sau khi tất cả, nhưng tôi không thể nhìn thấy ảnh hưởng của nó do sử dụng hợp cụ thể nói riêng của tôi)

Vì vậy, tôi đang làm điều này:

rbenv_version = ENV['RBENV_VERSION'] 
ENV['RBENV_VERSION'] = 'system' 
begin 
    system "ruby extconf.rb" 
ensure 
    ENV['RBENV_VERSION'] = rbenv_version 
end 

Tôi bị buộc phải biểu hiện lâu như vậy bởi vì tôi không muốn ghi đè biến môi trường vĩnh viễn nếu nó đã có một giá trị.

Bất kỳ điều gì ngắn hơn bạn nghĩ đến?

Trả lời

63
system({"MYVAR" => "42"}, "echo $MYVAR") 

system chấp nhận bất kỳ đối số mà Process.spawn chấp nhận.

+1

Bạn da man. \ o/ – mislav

+0

Đây là một câu trả lời tuyệt vời. Tài liệu cho ['Kernel # system'] (http://ruby-doc.org/core-1.9.3/Kernel.html#method-i-system) không đủ rõ ràng về chức năng này. Rất đẹp. – Phrogz

+0

Đối với ruby ​​1.8, hãy xem @ rtomayko's POSIX :: Spawn, được liên kết trong một bình luận khác. – alxndr

2

Điều này có thể hoạt động?

system <<-CMD 
export VARNAME=123 
other_command 
CMD 
+1

Điều đó có hiệu quả. Một dòng: 'hệ thống 'xuất VARNAME = 123 && other_command'' – mislav

6

Ruby 1.9 bao gồm Process::spawn cho phép băm môi trường được cung cấp.

Process::spawn cũng là nền tảng cho system, exec, popen vv
Bạn có thể vượt qua một môi trường để mỗi người.

Dưới Ruby 1,8, bạn có thể muốn xem xét các thư viện POSIX::Spawn,
cung cấp các giao diện tương tự

+0

Điều cần biết! Tuy nhiên, lời kêu gọi này khá phức tạp: 'Process.wait Process.spawn ({" MYVAR "=>" 42 "}," echo $ MYVAR ")' cho các nhu cầu đơn giản của tôi. Hóa ra 'system' func cũng hỗ trợ đối số băm tùy chọn này! – mislav

+0

'system' chấp nhận tất cả các đối số mà' Process.spawn() 'chấp nhận. Xem câu trả lời của tôi cho ví dụ. – Avdi

3

Sử dụng phương pháp tương tự của bạn, nhưng quấn lên như một phương pháp khối tạm thời làm thay đổi môi trường (như dạng khối của Dir.chdir):

def with_environment(variables={}) 
    if block_given? 
    old_values = variables.map{ |k,v| [k,ENV[k]] } 
    begin 
     variables.each{ |k,v| ENV[k] = v } 
     result = yield 
    ensure 
     old_values.each{ |k,v| ENV[k] = v } 
    end 
    result 
    else 
    variables.each{ |k,v| ENV[k] = v } 
    end 
end 

with_environment 'RBENV_VERSION'=>'system' do 
    `ruby extconf.rb` 
end 
+0

Tôi sử dụng cách tiếp cận này thường xuyên trong các thử nghiệm, nhưng ở đây nó là một quá mức cần thiết. – mislav

+0

@AnonymousDownvoter Tôi khuyến khích bạn downvote câu trả lời là _wrong_, và upvote câu trả lời được _better_ hơn những người khác.Downvoting một (chính xác) câu trả lời có lẽ vì có câu trả lời khác được tốt hơn (dễ dàng hơn, ngắn hơn) không phải là trong tinh thần của Stack tràn, IMHO. – Phrogz

+0

+1 trước tiên, để nhận được sự phản đối không công bằng. Thứ hai, bởi vì đây là câu trả lời yêu thích của tôi. Tôi đã vui mừng hơn cho đến khi tôi nhận ra bạn đã xác định: with_environment. Thật buồn, bởi vì đó là phương pháp nên tồn tại trong Ruby. –

3

Thực ra điều đó đã hiệu quả đối với tôi.

[email protected] ~ » irb                                  
1.9.3p0 :001 > system %{SHAIGUITAR=exists ruby -e 'puts ENV["SHAIGUITAR"]'} 
exists 
=> true 

Nhưng nếu không, bạn có thể thử thêm "env" vào bất kỳ biến nào bạn cần. Ví dụ.

system(%{env SHAIGUITAR=exists ruby bla.rb}) 
+0

Nó cũng làm việc cho tôi. Tôi là một thằng ngốc, tôi đã thử nó và loại bỏ nó sau khi tôi đã không nhận được hiệu ứng mong muốn, nhưng đó là vì trường hợp sử dụng cụ thể của tôi và không phải vì điều này không được hỗ trợ. Cảm ơn! – mislav

+0

Điều duy nhất không hoạt động với điều này - và điều này rất lạ - là ví dụ "echo". Đó là lý do tại sao tôi đánh dấu câu trả lời khác là đúng - nó bao gồm nhiều trường hợp hơn. – mislav