我正在尝试在Windows上使用类似下面的方法产生一个Ruby进程:
p1 = spawn('ruby', 'loop.rb', [:out, :err] => ['process.log', "w"], :new_pgroup => true)
我也通过以下方式脱离了这个过程:
p1.detach
这应该据我所知创造一个独立于父母的新过程。 我甚至使用new_pgroup参数来确保新进程获得自己的进程组。
当我执行我的脚本时,subprocess开始并继续运行。 产生子过程的脚本的执行也完成了。 但是,当我closures壳时,subprocess就会死亡。 我期望它继续运行(它在OS X和Linux上)。 我无法弄清楚这是否是在Windows上的Ruby运行时错误,或者这是Windows的限制,以及它如何处理进程。
为了完整,我正在尝试做的完整的Ruby代码:
spawner.rb :可以通过ruby spawner.rb
执行,并产生一个新的subprocess。 这个过程创build的是loop.rb ,这只是一个无限循环。 根据操作系统的不同,它为进程组创build指定了不同的参数。
require "tempfile" require 'rbconfig' class SpawnTest def self.spawn_process if os == :windows p1 = spawn('ruby', 'loop.rb', [:out, :err] => ['process.log', "w"], :new_pgroup => true) else p1 = spawn('ruby', 'loop.rb', [:out, :err] => ['process.log', "w"], :pgroup => true) end # Detach from the processes so they will keep running puts p1 Process.detach(p1) end def self.os @os ||= ( host_os = RbConfig::CONFIG['host_os'] case host_os when /mswin|msys|mingw|cygwin|bccwin|wince|emc/ :windows when /darwin|mac os/ :macosx when /linux/ :linux when /solaris|bsd/ :unix else raise Error::WebDriverError, "unknown os: #{host_os.inspect}" end ) end end if __FILE__ == $0 SpawnTest.spawn_process end
loop.rb
$stdout.sync = true $stderr.sync = true i = 0 while i < 10000 $stdout.puts "Iteration #{i}" sleep 1 i = i + 1 end $stdout.puts "Bye from #{Process.pid}"
我在调查过程中发现了win32进程的gem。 它似乎是使用win32 API调用来产生进程。 有谁知道这个库是否可以解决这个问题?
任何帮助赞赏。
除了将CTRL
事件分派给多个进程外,我无法在Windows中找到任何进程组的使用,因为它在“ 进程创建标志”MSDN文档中声明 :
GenerateConsoleCtrlEvent函数使用进程组来启用将CTRL + BREAK信号发送到一组控制台进程。
当CREATE_NEW_PROCESS_GROUP
标志被指定时实际发生的是…
…隐式调用SetConsoleCtrlHandler(NULL,TRUE)代表新进程; 这意味着新进程已禁用CTRL + C。 这让shell自己处理CTRL + C,并选择性地将该信号传递给子进程。 CTRL + BREAK没有被禁用,可以用来中断进程/进程组。
从CreateProcess MSDN文档 。
请注意,这与使用x
按钮关闭控制台窗口不同。 在后一种情况下,进程收到CTRL_CLOSE_EVENT
,
当用户关闭控制台时(通过在控制台窗口的窗口菜单上单击“关闭”,或单击“任务管理器”中的“结束任务”按钮命令),系统发送给连接到控制台的所有进程的信号。
从HandlerRoutine回调MSDN文档 。
在创建进程时SetConsoleCtrlHandler(NULL,TRUE)
处理此事件不会受到由CREATE_NEW_PROCESS_GROUP
标志设置的SetConsoleCtrlHandler(NULL,TRUE)
影响。
以上所有意思是CREATE_NEW_PROCESS_GROUP
标志与您所观察到的行为无关。
默认情况下,子进程继承父控制台窗口和IO句柄。 因此,当通过单击x
按钮关闭shell时,它会收到CTRL_CLOSE_EVENT
,并且没有不终止的选项。
为了避免这种情况,子进程不应该附加到父控制台。 这是通过向CreateProcess
Windows API提供DETACHED_PROCESS
标志完成的。
默认情况下,控制台进程继承其父控制台…如果使用CreateProcess和DETACHED_PROCESS创建控制台进程,则控制台进程不会附加到控制台。
从创建一个控制台MSDN文档 。
这是我相信Ruby的spawn
和win32-process
gem做不同。 我没有尝试去调试两者,以查看它们提供给CreateProcess
的标志的具体区别,虽然这将是一件有趣的事情。
还有其他方法可以创建一个子进程而不会继承父进程的控制台或IO句柄。 例子是CREATE_NO_WINDOW
或CREATE_NEW_CONSOLE
标志, 作业对象等