9

我正在尝试通过 ruby​​ 为集成测试(实际上是规范)设置服务器,但不知道如何控制该过程。

所以,我想做的是:

  1. 为我的 gem 运行一个执行集成规范的 rake 任务
  2. 该任务需要首先启动一个服务器(我使用 webrick)然后运行规范
  3. 执行规范后,它应该杀死 webrick,所以我不会留下一些未使用的后台进程

webrick 不是必需的,但它包含在 ruby​​ 标准库中,因此能够使用它会很棒。

希望任何人都能够提供帮助!

附言。我在 linux 上运行,所以为 windows 工作不是我的主要优先事项(现在)。

4

3 回答 3

14

标准方法是使用系统函数 fork(复制当前进程)、exec(将当前进程替换为可执行文件)和 kill(向进程发送信号以终止它)。

例如 :

pid = fork do
  # this code is run in the child process
  # you can do anything here, like changing current directory or reopening STDOUT
  exec "/path/to/executable"
end

# this code is run in the parent process
# do your stuffs

# kill it (other signals than TERM may be used, depending on the program you want
# to kill. The signal KILL will always work but the process won't be allowed
# to cleanup anything)
Process.kill "TERM", pid

# you have to wait for its termination, otherwise it will become a zombie process
# (or you can use Process.detach)
Process.wait pid

这应该适用于任何类 Unix 系统。Windows 以不同的方式创建进程。

于 2010-01-02T23:07:40.343 回答
2

我只需要做类似的事情,这就是我想出的。@Michael Witrant 的回答让我开始了,但我改变了一些东西,比如使用 Process.spawn 而不是 fork (更新更好)。

# start spawns a process and returns the pid of the process
def start(exe)
    puts "Starting #{exe}"
    pid = spawn(exe)
    # need to detach to avoid daemon processes: http://www.ruby-doc.org/core-2.1.3/Process.html#method-c-detach
    Process.detach(pid)
    return pid
end

# This will kill off all the programs we started
def killall(pids)
  pids.each do |pid|
      puts "Killing #{pid}"
      # kill it (other signals than TERM may be used, depending on the program you want
      # to kill. The signal KILL will always work but the process won't be allowed
      # to cleanup anything)
      begin
        Process.kill "TERM", pid

        # you have to wait for its termination, otherwise it will become a zombie process
        # (or you can use Process.detach)
        Process.wait pid
      rescue => ex
        puts "ERROR: Couldn't kill #{pid}. #{ex.class}=#{ex.message}"
      end
  end
end

# Now we can start processes and keep the pids for killing them later
pids = []
pids << start('./someprogram')

# Do whatever you want here, run your tests, etc. 

# When you're done, be sure to kill of the processes you spawned
killall(pids)

这就是她写的所有内容,试一试,让我知道它是如何工作的。

于 2014-10-08T17:34:02.927 回答
0

我尝试过 fork,但是当 ActiveRecord 参与这两个过程时,它会出现一些问题。我建议 Spawn 插件(http://github.com/tra/spawn)。它只分叉,但会处理 ActiveRecord。

于 2010-01-03T09:32:23.773 回答