在Ruby中导出环境变量

时间:2022-01-01 12:16:59

How do I export an environment variable from within a Ruby script to the parent shell? For example, implementing a naïve implementation of the read Bash builtin:

如何从Ruby脚本中将环境变量导出到父shell中?例如,实现read Bash内置的简单实现:

#!/usr/bin/ruby

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

4 个解决方案

#1


34  

Simple answer: You can't.

答案很简单:你不能。

Longer answer: You can't, unless the operating environment provides hooks to do so. Most do not. The best you can usually do is print out the assignments you want done and have the parent execute them.

更详细的回答是:你不能这样做,除非操作环境提供挂钩。大多数没有。通常你能做的最好的事情就是打印出你想要完成的作业,然后让父母执行它们。

#2


35  

You can't export environment variables to the shell the ruby script runs in, but you could write a ruby script that creates a source-able bash file.

您不能将环境变量导出到ruby脚本运行的shell中,但是您可以编写一个ruby脚本来创建一个可源代码的bash文件。

For example

例如

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

Another alternative is that using ENV[]= does set environment variables for subshells opened from within the ruby process. For example:

另一种选择是使用ENV[]=为ruby进程中打开的子shell设置环境变量。例如:

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 

This can be quite potent if you combine it with the shell's exec command, which will replace the outer-shell with the ruby process (so that when you exit the inner shell, the outer shell auto-exits as well, preventing any "I thought I set that variable in this shell" confusion).

如果您将它与shell的exec命令相结合,它将用ruby进程替换外壳(这样当您退出内部shell时,外壳也会自动退出,以避免出现“我以为我在这个shell中设置了这个变量”的混乱)。

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

#3


7  

I just tried this and it looks good.

我刚试过,看起来不错。

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

This seems to work well - at least on MacOSX

这似乎很管用——至少在MacOSX上是这样

I get

我得到

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

Seems nice in it restores prior state automatically

看起来不错,它自动恢复先前状态

Ok - now tried a different one as this doesn't spawn 2 subprocesses

现在尝试了另一种方法,因为它不会产生两个子进程

Use Process.spawn(env,command)

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

This acts like the C system call and allows you to specify pipes and all that other stuff too.

这就像C系统调用,允许你指定管道和其他的东西。

#4


0  

What about in ruby printing out standard export code :

在ruby打印输出标准出口代码:

puts "export MYVAR=value"

and then using shell backtick to get it executed at shell comands:

然后使用shell backtick在shell comands执行:

$ `./myscript.rb` 

this will take the output of the script and execute it, works in modern shells like bash and zsh

这将获取脚本的输出并执行它,在类似bash和zsh的现代shell中工作

#1


34  

Simple answer: You can't.

答案很简单:你不能。

Longer answer: You can't, unless the operating environment provides hooks to do so. Most do not. The best you can usually do is print out the assignments you want done and have the parent execute them.

更详细的回答是:你不能这样做,除非操作环境提供挂钩。大多数没有。通常你能做的最好的事情就是打印出你想要完成的作业,然后让父母执行它们。

#2


35  

You can't export environment variables to the shell the ruby script runs in, but you could write a ruby script that creates a source-able bash file.

您不能将环境变量导出到ruby脚本运行的shell中,但是您可以编写一个ruby脚本来创建一个可源代码的bash文件。

For example

例如

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

Another alternative is that using ENV[]= does set environment variables for subshells opened from within the ruby process. For example:

另一种选择是使用ENV[]=为ruby进程中打开的子shell设置环境变量。例如:

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 

This can be quite potent if you combine it with the shell's exec command, which will replace the outer-shell with the ruby process (so that when you exit the inner shell, the outer shell auto-exits as well, preventing any "I thought I set that variable in this shell" confusion).

如果您将它与shell的exec命令相结合,它将用ruby进程替换外壳(这样当您退出内部shell时,外壳也会自动退出,以避免出现“我以为我在这个shell中设置了这个变量”的混乱)。

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

#3


7  

I just tried this and it looks good.

我刚试过,看起来不错。

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

This seems to work well - at least on MacOSX

这似乎很管用——至少在MacOSX上是这样

I get

我得到

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

Seems nice in it restores prior state automatically

看起来不错,它自动恢复先前状态

Ok - now tried a different one as this doesn't spawn 2 subprocesses

现在尝试了另一种方法,因为它不会产生两个子进程

Use Process.spawn(env,command)

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

This acts like the C system call and allows you to specify pipes and all that other stuff too.

这就像C系统调用,允许你指定管道和其他的东西。

#4


0  

What about in ruby printing out standard export code :

在ruby打印输出标准出口代码:

puts "export MYVAR=value"

and then using shell backtick to get it executed at shell comands:

然后使用shell backtick在shell comands执行:

$ `./myscript.rb` 

this will take the output of the script and execute it, works in modern shells like bash and zsh

这将获取脚本的输出并执行它,在类似bash和zsh的现代shell中工作