在Ruby脚本中改变环境

Dan*_*ark 2 ruby scripting

这是我的剧本

#!/usr/bin/env ruby
if __FILE__ == $0
    `cd ..` 
    puts `ls` 
end
Run Code Online (Sandbox Code Playgroud)

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

ib.*_*ib. 6

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

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


注意

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

所以,而不是

ruby run_commands.rb
Run Code Online (Sandbox Code Playgroud)

在shell脚本中写下这样的东西:

source <(ruby prepare_and_print_commands.rb)
Run Code Online (Sandbox Code Playgroud)

Shell

但是Ruby中有一个方便的命令行脚本工具 - Shell类!它已经预先定义常用命令的起酥油(如cd,pwd,cat,echo等),并允许定义自己的(它支持的命令别名)!此外,它透明地支持使用输入/输出的重定向|,>,<,>>,<<Ruby操作符.

Shell大多数情况下,使用是不言自明的.看看几个简单的例子.

创建"shell"对象并更改目录

sh = Shell.new
sh.cd '~/tmp'
# or
sh = Shell.cd('~/tmp')
Run Code Online (Sandbox Code Playgroud)

在当前目录中工作

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'
Run Code Online (Sandbox Code Playgroud)

(注意,有时必须使用括号,因为"重定向"运算符的优先级.默认情况下,命令输出不会打印到stdout,因此您需要指定使用> STDOUT,或者> STDERR如果需要.)

测试文件属性

puts sh.test('e', 'test')
# or
puts sh[:e, 'test']
puts sh[:exists?, 'test']
puts sh[:exists?, 'nonexistent']
Run Code Online (Sandbox Code Playgroud)

(与test普通shell中的函数类似.)

定义自定义命令和别名

#                        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] }
Run Code Online (Sandbox Code Playgroud)

定义的命令的名称稍后可以用来精确地运行它以同样的方式,因为它适用于预定义echocat,例如.

使用目录堆栈

sh.pushd '/tmp'
sh.list > STDOUT
(sh.echo sh.pwd) > STDOUT
sh.popd
sh.list > STDOUT
(sh.echo sh.pwd) > STDOUT
Run Code Online (Sandbox Code Playgroud)

(这里list使用上面定义的自定义命令.)

顺便说一下,有一个有用的chdir命令可以在目录中运行几个命令,然后返回到之前的工作目录.

puts sh.pwd
sh.chdir('/tmp') do
    puts sh.pwd
end
puts sh.pwd
Run Code Online (Sandbox Code Playgroud)

跳过一组命令的shell对象

# 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
Run Code Online (Sandbox Code Playgroud)

附加功能

另外Shell还有:

  • foreach 迭代文件中的行或通过目录中的文件列表的方法(取决于给定的路径指向文件或目录),
  • jobskill控制进程的命令,
  • 用于与文件操作一串命令(如basename,chmod,chown,delete,dirname,rename,stat,symlink),
  • 的列表File的方法的同义词(directory?,executable?,exists?,readable?,等等),
  • 等同物的FileTest类的方法(syscopy,copy,move,compare,safe_unlink,makedirs,install).