在Ruby脚本中改变环境

时间:2010-04-04 04:02:14

标签: ruby scripting

这是我的剧本

#!/usr/bin/env ruby
if __FILE__ == $0
    `cd ..` 
    puts `ls` 
end

运行良好,但当它退出时,我回到了我开始的地方。如何“导出”我对环境所做的更改?

1 个答案:

答案 0 :(得分:6)

那是因为```运算符不适用于复杂的脚本。它对于运行单个命令(并读取其输出)很有用。它后面没有shell来存储其调用之间的环境变化 之后你的Ruby脚本终止。

在Linux系统上,每个进程都有自己的“当前目录”路径(可以在/ proc / / cwd中找到)。更改进程中的目录不会影响父进程(从中运行程序的shell)。如果cd内置的是二进制文件,它只能更改自己的当前目录,而不能更改父进程之一(这就是为什么cd命令只能内置)。


如果Ruby脚本必须从shell执行并且必须影响shell的当前目录路径,则可以制作“技巧”。不是从Ruby本身运行命令,而是将命令打印到stdout,然后将source打印到运行Ruby脚本的shell。命令将由shell的单独进程执行,因此所有cd s 在当前shell实例中生效。

所以,而不是

ruby run_commands.rb

在shell脚本中写下类似的内容:

source <(ruby prepare_and_print_commands.rb)

Shell class

但是在Ruby中有一个方便的命令行脚本工具 - Shell类!它为常用命令(例如cdpwdcatecho等)预定义了缩写,并允许定义自己的命令(它支持命令别名)!此外,它还透明地支持使用|><>><< Ruby运算符重定向输入/输出。

使用Shell大部分时间都是不言自明的。看看几个简单的例子。

创建“shell”对象并更改目录

sh = Shell.new
sh.cd '~/tmp'
# or
sh = Shell.cd('~/tmp')

在当前目录中工作

puts "Working directory: #{sh.pwd}"
(sh.echo 'test') | (sh.tee 'test') > STDOUT
# Redirecting possible to "left" as well as to "right".
(sh.cat < 'test') > 'triple_test'
# '>>' and '<<' are also supported.
sh.cat('test', 'test') >> 'triple_test'

(请注意,有时必须使用括号,因为“重定向”运算符的优先级。默认情况下,命令输出也不会打印到stdout,因此您需要指定使用> STDOUT或{{1}如果需要的话。)

测试文件属性

> STDERR

(与通常的shell中的puts sh.test('e', 'test') # or puts sh[:e, 'test'] puts sh[:exists?, 'test'] puts sh[:exists?, 'nonexistent'] 函数类似。)

定义自定义命令和别名

test

以后定义的命令的名称可以用来运行它,就像它对预定义的# name command line to execute Shell.def_system_command 'list', 'ls -1' # name cmd command's arguments Shell.alias_command "lsC", "ls", "-CBF" Shell.alias_command("lsC", "ls") { |*opts| ["-CBF", *opts] } echo一样。

使用目录堆栈

cat

(此处使用上面定义的自定义sh.pushd '/tmp' sh.list > STDOUT (sh.echo sh.pwd) > STDOUT sh.popd sh.list > STDOUT (sh.echo sh.pwd) > STDOUT 命令。)

顺便说一句,有一个有用的list命令可以在目录中运行多个命令,然后返回到之前的工作目录。

chdir

跳过一组命令的shell对象

puts sh.pwd
sh.chdir('/tmp') do
    puts sh.pwd
end
puts sh.pwd

其他功能

另外# Code above, rewritten to drop out 'sh.' in front of each command. sh.transact do pushd '/tmp' list > STDOUT (echo pwd) > STDOUT popd list > STDOUT (echo pwd) > STDOUT end 有:

  • Shell方法迭代文件中的行,或通过目录中的文件列表(取决于给定的路径指向文件或目录),
  • foreachjobs命令用来控制进程,
  • 一系列用于操作文件的命令(例如killbasenamechmodchowndeletedirname,{ {1}},rename),
  • stat方法”同义词列表(symlinkFiledirectory?executable?等),
  • 等同于exists?类方法'(readable?FileTestsyscopycopymovecomparesafe_unlink)。