-e script 这个选项运行script中的代码,如果制定的-e选项多于一个,他们关联的脚本会被看作独立的代码行
ruby -e "puts 111" #输出111
-I path 这个选项把path中的目录加到全局$LOAD_PATH数组的起始处,load和require方法会在该数组包含的目录中搜索加载文件
ruby -I "/Users/fangxiang/work" xxx.rb
-r library 这个选项用于在运行程序前加载给定的library,作用就像在程序的首部增加如下代码行:
require 'library'
-d, –debug 这两个选项把全局变量$DEBUG和$VERBOSE设置为true,他们可以被程序或库代码使用,用来打印调试信息或别的操作
可以通过类似下面的代码在环境中检测预定义的模块、类和异常:
puts Module.constants.sort.select {|x| Object.const_get(x.to_s).instance_of? Module}
输出:
Comparable
Config
Enumerable
Errno
Exception2MessageMapper
FileTest
GC
Gem
IRB
Kernel
Marshal
Math
MonitorMixin
ObjectSpace
Process
RbConfig
Readline
RubyToken
Signal
获取类:
Module.constants.sort.select do |x|
c = eval(x.to_s)
c.is_a? Class and not c.ancestors.include? Exception
end
返回:
[:Array, :BasicObject, :Bignum, :Binding, :Class, :Complex, :ConditionVariable, :Data, :Date, :Dir, :Encoding, :Enumerator, :FalseClass, :Fiber, :File, :Fixnum, :Float, :Hash, :IO, :Integer, :MatchData, :Method, :Module, :Monitor, :Mutex, :NilClass, :Numeric, :Object, :Proc, :Queue, :Random, :Range, :Rational, :Regexp, :RubyLex, :RubyVM, :SizedQueue, :String, :Struct, :Symbol, :Thread, :ThreadGroup, :Time, :TrueClass, :UnboundMethod]
获取异常:
Module.constants.sort.select do |x|
c = eval(x.to_s)
c.is_a? Class and c.ancestors.include? Exception
end
返回:
[:ArgumentError, :EOFError, :EncodingError, :Exception, :FiberError, :FloatDomainError, :IOError, :IndexError, :Interrupt, :KeyError, :LoadError, :LocalJumpError, :NameError, :NoMemoryError, :NoMethodError, :NotImplementedError, :RangeError, :RegexpError, :RuntimeError, :ScriptError, :SecurityError, :SignalException, :StandardError, :StopIteration, :SyntaxError, :SystemCallError, :SystemExit, :SystemStackError, :ThreadError, :TypeError, :ZeroDivisionError]
获取环境中的顶级常量:
puts Module.constants.sort.reject{|x| eval(x.to_s).is_a? Module}
输出:
ARGF 一个IO对象,它把ARGV中指定的所有文件虚拟连接起来成为一个文件。如果ARGV为空,那么它表示标准输入。是$<的同义词
ARGV 一个数组,包含所有命令行指定的参数,是$*的同义词
CROSS_COMPILING
ENV 一个对象,其行为像一个哈希对象,可以通过它访问解释器中可用的环境变量
FALSE
NIL
RUBYGEMS_ACTIVATION_MONITOR
RUBY_COPYRIGHT
RUBY_DESCRIPTION
RUBY_ENGINE
RUBY_PATCHLEVEL 用于指示解释器补丁号的字符串
RUBY_PLATFORM 用于指示ruby解释器运行平台的字符串
RUBY_RELEASE_DATE 用于指示ruby解释器发布日期的字符串
RUBY_REVISION 用于指示解释器支持的ruby语言版本号的字符串
RUBY_VERSION
STDERR 标准错误流,是$stderr变量的默认值
STDIN 标准输入流,是$stdin变量的默认值
STDOUT 标准输出流,是$stdout的默认值
TOPLEVEL_BINDING 一个Binding对象,用于表示顶级范围的绑定
TRUE
获取ruby解释器预定义的全局变量列表:
global_variables.sort
返回:
[:$!, :$", :$$, :$&, :$', :$*, :$+, :$,, :$-0, :$-F, :$-I, :$-K, :$-W, :$-a, :$-d, :$-i, :$-l, :$-p, :$-v, :$-w, :$., :$/, :$0, :$1, :$2, :$3, :$4, :$5, :$6, :$7, :$8, :$9, :$:, :$;, :$<, :$=, :$>, :$?, :$@, :$DEBUG, :$FILENAME, :$KCODE, :$LOADED_FEATURES, :$LOAD_PATH, :$PROGRAM_NAME, :$SAFE, :$VERBOSE, :$\, :$_, :$`, :$binding, :$load_modules, :$stderr, :$stdin, :$stdout, :$~]
$* ARGV常量的同义词
$$ 当前ruby进程的进程ID,只读的
$? 最后一个结束程序的退出状态,它是只读且线程局部的
$DEBUG, $-d 如果在命令行中设置了-d或–debug属性,这两个变量值为true
$LOADED_FEATURES, $” 一个字符串数组,表示已加载的文件名,只读的
$LOAD_PATH, $:, $-I 一个包含一组目录名的字符串数组,在使用load和require方法来加载文件时,会在这些目录下进行查找
$PROGRAM, $O 表示当前执行的ruby程序文件名
$SAFE 当前执行程序的安全级别
$! 最后抛出的异常对象
$@ 最后一个异常对象的调用对战,等价于$!.backtrace
$_ Kernel模块方法gets和readline所读的最后一个字符串,这个值是线程局部且方法局部的
$< ARGF流的一个只读同义词
$stdin 标准输入流,初始值是常量STDIN,不过很多ruby程序不从它读取信息,而是使用ARGF或$<进行读取
$stdout, $> 标准输出流,是Kernel模块中各种打印方法的目标流:比如puts、print、printf等
$stderr 标准错误,它的初始值是常量STDERR
$FILENAME ARGF当前所读取的文件名,等价于ARGF.filename,只读的
$. 从当前输入文件中最后读取行的行号,等价于ARGF.lineno
$/, $-0 输入记录分隔符(默认是换行符),gets和readline方法默认使用这个值来确定行边界,可以通过解释器选项-0来设定这个值
$\ 输出记录分隔符,默认值是nil,如果设置了非nil值,在每次调用print(不过其他输出方法不会如此,比如puts)后,会打印这个分隔符
$, print方法打印输出各个参数间的分隔符,也是Array.join方法的默认分隔符,默认值是nil
$;, $-F split方法使用的默认字段分隔符,默认值是nil
$~ 最后一次模式匹配操作所生成的MatchData对象,它是线程局部且方法局部的。
$& 最近匹配的文本,等价于$~[0],只读的,而且是线程局部、方法局部的,继承自$~
$` 最新匹配的文本之前的字符串,等价于$~.pre_match,只读的,而且是线程局部、方法局部的,继承自$~
$+ 最后一次模式匹配中最后一个成功匹配分组的字符串,只读的,而且是线程局部、方法局部的,继承自$~
在ruby中另一种实现并发性的方式是使用多个ruby进程,这可以通过fork函数或同义词方法Process.fork来实现:
fork {
puts "hello from child process: #{$$}"
}
puts "hello from the parent process: #{$$}"
通过这种方式,原始的ruby进程继续执行代码块之后的代码,而新创建的ruby进程则执行代码块中的代码。
如果不使用代码块,fork的行为会有所不同。在父进程中,对fork函数的调用会返回一个整数值,它代表新创建子进程的ID;而在子进程中,同样对fork的调用则返回nil。
pid = fork
if pid
puts "hello from parent process: #{$$}"
puts "created child process #{pid}"
else
puts "hello from child process: #{$$}"
pid2 = fork
puts "child fork pid: #{pid2}"
end
输出:
hello from parent process: 2042
created child process 2043
hello from child process: 2043
child fork pid: 2044
child fork pid:
进程和线程的一个十分重要的区别在于进程不共享内存。当调用fork时,新创建的ruby进程会精确复制父进程。但是任何对进程状态的修改都在自身的地址空间中完成,子进程不能修改父进程的数据结构,而父进程也不能修改子进程中的数据结构。
如果想让父进程和子进程进行通信,可以使用open函数,并用“|-”作为它的第一个参数。这个函数为新创建的ruby进程打开一个管道,在父进程和子进程中都会把控制权交给open所关联的代码块。在子进程中,代码块所接收的参数为nil;而在父进程中,代码块接收一个IO对象,对这个IO对象进行读取可以得到子进程所写的数据;而对这个IO对象中写入的数据可以通过子进程的标准输入读出:
open("|-", "r+") do |child|
if child
#this is the parent process
child.puts "hello world" #发送数据到子进程
response = child.gets #读取子进程输出的数据
puts "child said: #{response}"
else
#this is the child process
from_parent = gets #从父进程读取数据
STDERR.puts "parent said: #{from_parent}"
puts "hi mon!" #发送数据到父进程
end
end
输出:
parent said: hello world
child said: hi mon!
Kernel.exec函数在与fork或open配合使用时有特别的用途。前面我们看到可以使用`和system向操作系统发送任意的命令,不过这两个方法都是同步方式的,在命令完成前不会返回。如果想在一个单独的进程中执行系统命令,首先要使用fork来创建子进程,然后调用在子进程中的exec来运行命令。对exec的调用永远不会返回,它用新创建的进程替代当前进程。exec的参数与system的相同。如果只有一个参数,该参数被当作外壳命令处理;如果有多个参数,第一个参数被当作可执行命令,剩下的参数成为可执行命令的“ARGV”变量:
open("|-", "r") do |child|
if child
#this is the parent process
files = child.readlines #read the output of our child
puts "files:", files.inspect
child.close
else
#this is the child process
exec "ls", "-l" #
end
end
输出:
files:
["total 152\n", "-rw-r--r-- 1 fangxiang staff 5481 2 9 13:29 acceptance_test.rb\n", "-rw-r--r-- 1 fangxiang staff 1657 12 4 10:16 update_google_hosts.rb\n"]
绝大多数操作系统支持对当前运行的进程发送异步信号。当用户键入Ctrl+C来中止一个程序时,所发生的事情就是异步信号的一个例子。大多数的外壳程序在接收到Ctrl+C后,将发送一个名为“SIGINT”(用于中断运行)的信号,该信号的默认的处理方式是中止程序,ruby允许程序捕获信号并定义自己的信号处理程序。这是通过Kernel.trap方法(或同义词方法Signal.trap)实现的。
例如,如果不想让用户使用Ctrl+C退出程序,可以这样:
trap "SIGINT" {
puts "Ignoring SIGINT"
}
除了给trap方法传递一个代码块,也可以给他传递一个等价的Proc对象。如果只是想简单忽略一个信号,可以用字符串“IGNORE”作为第二个参数。如果用“DEFAULT”作为第二个参数,操作系统将恢复该信号的默认处理方式。
一些相关的Kernel方法用于结束程序或相关的动作,exit函数是最直接的,它抛出一个SystemExit异常,如果该异常没有被捕获,则导致程序退出。不过在退出前,END块及任何用Kernel.at_exit注册的处理方法被执行。如果要立刻退出,可以使用exit!方法,该方法不会执行END块等。这两个方法接受一个整数参数,它代表进程退出码,将被提供给操作系统。Process.exit和Process.exit!是这两个Kernel函数的同义词函数。
abort函数向标准输出流打印指定的错误信息,然后调用exit(1)
abort "aaa"
fail是raise的同义词方法,它一般在捕获到须要程序结束的异常时使用。像abort一样,fail在程序退出时显示一个消息,例如:
fail "the end"
warn函数与abort和fail有点关系:它向标准错误流打印一个警告消息(除非通过-WO选项显示禁止警告)。不过这个函数不会抛出异常或退出程序。
warn "aaa"
sleep不会让程序退出,只是让程序(或至少是程序当前运行的线程)暂停指定的秒数。