2010-04-18 5 views
36

में एक पर्यावरण परिवर्तनीय निर्यात करना मैं रुबी स्क्रिप्ट के भीतर से मूल चर में पर्यावरण चर निर्यात कैसे करूं? उदाहरण के लिए, read बैश निर्मित की एक सीधी सादी कार्यान्वयन को लागू करने:रूबी

#!/usr/bin/ruby 

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

मैंने देखा [एक समान प्रश्न] (http://stackoverflow.com/questions/190168/persisting-an-environment-variable-through-ruby) लेकिन मैं मैं संतुष्ट नहीं हूँ मंच-विशिष्ट उत्तर के साथ एड। – wilhelmtell

उत्तर

34

सरल जवाब: आप नहीं कर सकते।

लंबा उत्तर: आप तब तक नहीं कर सकते जब तक ऑपरेटिंग वातावरण ऐसा करने के लिए हुक प्रदान नहीं करता। अधिकांश नहीं करते हैं। सबसे अच्छा आप आमतौर पर कर सकते हैं असाइनमेंट को मुद्रित करना चाहते हैं और माता-पिता उन्हें निष्पादित करते हैं।

+0

पीटरके के उत्तर को देखो यह विंडोज़ पर भी काम करता है। मैंने इसे रेक के शॉ निष्पादन डॉस कमांड के साथ करने की कोशिश की जिसके लिए रेक के भीतर एनवी सेट की आवश्यकता है। – kite

+5

@ पतंग: "पेरेंट खोल में" –

+1

वैकल्पिक रूप से, एक उपयुक्त निर्देशिका में एक क्रेडेंशियल डॉटफाइल सेट करने पर विचार करें –

35

आप रूबी स्क्रिप्ट में चलने वाले खोल के लिए पर्यावरण चर निर्यात नहीं कर सकते हैं, लेकिन आप एक रूबी स्क्रिप्ट लिख सकते हैं जो स्रोत-सक्षम बैश फ़ाइल बनाता है।

उदाहरण

% 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[]= का उपयोग कर रूबी प्रक्रिया के भीतर से खोला subshells के लिए वातावरण चर सेट करता है।

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 आदेश है, जो (ताकि जब आप भीतरी खोल से बाहर निकलने के माणिक प्रक्रिया के साथ बाहरी-खोल बदल देगा, बाहरी कवच ​​ऑटो के साथ गठबंधन काफी शक्तिशाली हो सकता है: उदाहरण के लिए - साथ ही, किसी भी को रोकने "मैंने सोचा कि मैं इस खोल में उस चर को सेट करता हूं" भ्रम)।

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

मैंने अभी यह कोशिश की और यह अच्छा लग रहा है।

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 subprocesses

Use Process.spawn(env,command) 

pid = Process.spawn({ 'FOO'=>'foo in spawned process'}, cmd); 
pid = Process.wait(); 
नहीं है 210

यह सी सिस्टम कॉल की तरह कार्य करता है और आपको पाइप और अन्य सभी सामान भी निर्दिष्ट करने की अनुमति देता है।

0

क्या रूबी में मानक निर्यात कोड बाहर प्रिंट करने के बारे:

puts "export MYVAR=value" 

और फिर खोल बैकटिक का उपयोग कर इसे खोल comands पर क्रियान्वित पाने के लिए:

$ `./myscript.rb` 

इस स्क्रिप्ट का उत्पादन लेने के लिए और होगा इसे निष्पादित करें, आधुनिक शैल जैसे bash और zsh

+0

दुर्भाग्य से, यह या तो काम नहीं करता है, क्योंकि यह अभी भी सीधे पैरेंट शैल में काम नहीं कर रहा है। – Julian