当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Ruby Kernel.spawn用法及代码示例


本文简要介绍ruby语言中 Kernel.spawn 的用法。

用法

spawn([env,] command... [,options]) → pid
spawn([env,] command... [,options]) → pid

spawn 执行指定的命令并返回它的 pid。

pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
Process.wait pid

pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
Process.wait pid

此方法类似于 Kernel#system ,但它不等待命令完成。

父进程应使用 Process.wait 收集其子进程的终止状态,或使用 Process.detach 记录对其状态的不感兴趣;否则,操作系统可能会积累僵尸进程。

spawn 有很多选项来指定进程属性:

env: hash
  name => val : set the environment variable
  name => nil : unset the environment variable

  the keys and the values except for +nil+ must be strings.
command...:
  commandline                 : command line string which is passed to the standard shell
  cmdname, arg1, ...          : command name and one or more arguments (This form does not use the shell. See below for caveats.)
  [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
options: hash
  clearing environment variables:
    :unsetenv_others => true   : clear environment variables except specified by env
    :unsetenv_others => false  : don't clear (default)
  process group:
    :pgroup => true or 0 : make a new process group
    :pgroup => pgid      : join the specified process group
    :pgroup => nil       : don't change the process group (default)
  create new process group: Windows only
    :new_pgroup => true  : the new process is the root process of a new process group
    :new_pgroup => false : don't create a new process group (default)
  resource limit: resourcename is core, cpu, data, etc.  See Process.setrlimit.
    :rlimit_resourcename => limit
    :rlimit_resourcename => [cur_limit, max_limit]
  umask:
    :umask => int
  redirection:
    key:
      FD              : single file descriptor in child process
      [FD, FD, ...]   : multiple file descriptor in child process
    value:
      FD                        : redirect to the file descriptor in parent process
      string                    : redirect to file with open(string, "r" or "w")
      [string]                  : redirect to file with open(string, File::RDONLY)
      [string, open_mode]       : redirect to file with open(string, open_mode, 0644)
      [string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
      [:child, FD]              : redirect to the redirected file descriptor
      :close                    : close the file descriptor in child process
    FD is one of follows
      :in     : the file descriptor 0 which is the standard input
      :out    : the file descriptor 1 which is the standard output
      :err    : the file descriptor 2 which is the standard error
      integer : the file descriptor of specified the integer
      io      : the file descriptor specified as io.fileno
  file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
    :close_others => false  : inherit
  current directory:
    :chdir => str

cmdname, arg1, ... 表单不使用 shell 。但是,在不同的操作系统上,作为内置命令提供了不同的东西。这方面的一个例子是 +‘echo’+,它是 Windows 的内置程序,但在 Linux 和 Mac OS X 上是一个普通程序。这意味着 Process.spawn 'echo', '%Path%' 将显示 %Path% 环境变量的内容Windows,但 Process.spawn 'echo', '$PATH' 打印文字 $PATH

如果一个散列被指定为 env ,则在子进程中 envexec(2) 之前更新环境。如果env 中的一对具有 nil 作为值,则删除该变量。

# set FOO as BAR and unset BAZ.
pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, command)

如果一个哈希被指定为 options ,它指定进程组、创建新进程组、资源限制、当前目录、umask 和子进程的重定向。此外,可以指定清除环境变量。

options 中的 :unsetenv_others 键指定清除环境变量,而不是由 env 指定。

pid = spawn(command, :unsetenv_others=>true) # no environment variable
pid = spawn({"FOO"=>"BAR"}, command, :unsetenv_others=>true) # FOO only

options 中的:pgroup 键指定一个进程组。对应的值应该是 true、零、正整数或 nil。 true 和 0 使进程成为新进程组的进程领导。非零正整数会导致进程加入提供的进程组。默认值 nil 使进程保持在同一个进程组中。

pid = spawn(command, :pgroup=>true) # process leader
pid = spawn(command, :pgroup=>10) # belongs to the process group 10

options 中的 :new_pgroup 键指定将 CREATE_NEW_PROCESS_GROUP 标志传递给作为 Windows API 的 CreateProcessW()。此选项仅适用于 Windows。 true 表示新进程是新进程组的根进程。新进程已禁用 CTRL+C。该标志对于子进程上的Process.kill(:SIGINT, pid) 是必需的。 :new_pgroup 默认为假。

pid = spawn(command, :new_pgroup=>true)  # new process group
pid = spawn(command, :new_pgroup=>false) # same process group

:rlimit_ foo 键指定资源限制。 foo 应该是资源类型之一,例如 core 。对应的值应该是一个整数或具有一个或两个整数的数组:与 Process.setrlimit 的 cur_limit 和 max_limit 参数相同。

cur, max = Process.getrlimit(:CORE)
pid = spawn(command, :rlimit_core=>[0,max]) # disable core temporary.
pid = spawn(command, :rlimit_core=>max) # enable core dump
pid = spawn(command, :rlimit_core=>0) # never dump core.

options 中的 :umask 键指定 umask。

pid = spawn(command, :umask=>077)

:in、:out、:err、整数、 IO 和数组键指定重定向。重定向在子进程中映射一个文件说明符。

例如,stderr 可以合并到 stdout 中,如下所示:

pid = spawn(command, :err=>:out)
pid = spawn(command, 2=>1)
pid = spawn(command, STDERR=>:out)
pid = spawn(command, STDERR=>STDOUT)

哈希键指定由 spawn 启动的子进程中的文件说明符。 :err, 2 和 STDERR 指定标准错误流 (stderr)。

哈希值指定调用 spawn 的父进程中的文件说明符。 :out, 1 和 STDOUT 指定标准输出流 (stdout)。

在上面的例子中,没有指定子进程中的标准输出。所以它是从父进程继承的。

标准输入流 (stdin) 可以通过:in、0 和 STDIN 指定。

文件名可以指定为哈希值。

pid = spawn(command, :in=>"/dev/null") # read mode
pid = spawn(command, :out=>"/dev/null") # write mode
pid = spawn(command, :err=>"log") # write mode
pid = spawn(command, [:out, :err]=>"/dev/null") # write mode
pid = spawn(command, 3=>"/dev/null") # read mode

对于 stdout 和 stderr(以及它们的组合),它以写入模式打开。否则使用读取模式。

为了明确指定文件创建的标志和权限,使用数组代替。

pid = spawn(command, :in=>["file"]) # read mode is assumed
pid = spawn(command, :in=>["file", "r"])
pid = spawn(command, :out=>["log", "w"]) # 0644 assumed
pid = spawn(command, :out=>["log", "w", 0600])
pid = spawn(command, :out=>["log", File::WRONLY|File::EXCL|File::CREAT, 0600])

该数组指定文件名、标志和权限。标志可以是字符串或整数。如果标志被省略或为零,则假定为 File::RDONLY。权限应该是一个整数。如果权限被省略或为零,则假定为 0644。

如果将 IO 和整数数组指定为哈希键,则所有元素都将被重定向。

# stdout and stderr is redirected to log file.
# The file "log" is opened just once.
pid = spawn(command, [:out, :err]=>["log", "w"])

合并多个文件说明符的另一种方法是 [:child, fd]。 [:child, fd] 表示子进程中的文件说明符。这与 fd 不同。例如:err=>:out 表示将子stderr 重定向到父stdout。但是:err=>[:child,:out] 表示将子标准错误重定向到子标准输出。如果标准输出在子进程中被重定向,它们会有所不同,如下所示。

# stdout and stderr is redirected to log file.
# The file "log" is opened just once.
pid = spawn(command, :out=>["log", "w"], :err=>[:child, :out])

[:child, :out] 可用于将 stderr 合并到 IO.popen 中的 stdout 中。在这种情况下, IO.popen 将标准输出重定向到子进程中的管道,并且 [:child, :out] 指的是重定向的标准输出。

io = IO.popen(["sh", "-c", "echo out; echo err >&2", :err=>[:child, :out]])
p io.read #=> "out\nerr\n"

options 中的:chdir 键指定当前目录。

pid = spawn(command, :chdir=>"/var/tmp")

spawn 默认关闭所有非标准的未指定说明符。 “standard” 说明符是 0、1 和 2。此行为由:close_others 选项指定。:close_others 不影响仅在明确指定:close 时关闭的标准说明符。

pid = spawn(command, :close_others=>true)  # close 3,4,5,... (default)
pid = spawn(command, :close_others=>false) # don't close 3,4,5,...

:close_others 对于 spawn 和 IO.popen 默认为 false。

请注意,无论:close_others 选项如何,已设置close-on-exec 标志的fds 都将关闭。

所以 IO.pipe 和 spawn 可以用作 IO.popen

# similar to r = IO.popen(command)
r, w = IO.pipe
pid = spawn(command, :out=>w)   # r, w is closed in the child process.
w.close

:close 被指定为单独关闭 fd 的哈希值。

f = open(foo)
system(command, f=>:close)        # don't inherit f.

如果需要继承文件说明符,可以使用io=>io。

# valgrind has --log-fd option for log destination.
# log_w=>log_w indicates log_w.fileno inherits to child process.
log_r, log_w = IO.pipe
pid = spawn("valgrind", "--log-fd=#{log_w.fileno}", "echo", "a", log_w=>log_w)
log_w.close
p log_r.read

也可以交换文件说明符。

pid = spawn(command, :out=>:err, :err=>:out)

哈希键指定子进程中的文件说明符。哈希值指定父进程中的文件说明符。所以上面指定交换标准输出和标准错误。在内部,spawn 使用额外的文件说明符来解析这种循环文件说明符映射。

有关标准 shell ,请参见 Kernel.exec

相关用法


注:本文由纯净天空筛选整理自ruby-lang.org大神的英文原创作品 Kernel.spawn。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。