Har*_*rdy 6 ruby windows shell powershell spawn
我试图在Windows上使用以下内容生成Ruby进程:
p1 = spawn('ruby', 'loop.rb', [:out, :err] => ['process.log', "w"], :new_pgroup => true)
Run Code Online (Sandbox Code Playgroud)
然后我也通过以下方式脱离了这个过程:
p1.detach
Run Code Online (Sandbox Code Playgroud)
到目前为止,我应该理解创建一个独立于父进程的新进程.我甚至使用new_pgroup参数来确保新进程获得自己的进程组.
当我执行我的脚本时,子进程启动并继续运行.产生子进程的脚本的执行也完成了.但是,当我现在关闭shell时,子进程就会死掉.我希望它能继续运行(它在OS X和Linux上运行).我无法弄清楚这是否是Windows上Ruby运行时的错误,或者这是否是Windows的限制以及它如何处理进程.
为了完整性,我想要做的完整Ruby代码:
spawner.rb:可以通过执行ruby spawner.rb
并生成一个新的子流程.进程创建的是loop.rb,这只是一个无限循环.根据操作系统,它为进程组创建指定了不同的参数.
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
Run Code Online (Sandbox Code Playgroud)
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}"
Run Code Online (Sandbox Code Playgroud)
我在调查期间找到了win32-process gem.它似乎是使用win32 API调用生成进程.有谁知道这个库是否能解决这个问题?
任何帮助赞赏.
除了将事件分派到多个进程之外,我在 Windows 中找不到进程组的任何用途,如进程创建标志 MSDN 文档CTRL
中所述:
GenerateConsoleCtrlEvent 函数使用进程组来向一组控制台进程发送 CTRL+BREAK 信号。
CREATE_NEW_PROCESS_GROUP
指定标志时实际发生的情况是......
...代表新进程隐式调用 SetConsoleCtrlHandler(NULL,TRUE);这意味着新进程已禁用 CTRL+C。这让 shell 自己处理 CTRL+C,并有选择地将该信号传递给子进程。CTRL+BREAK 未禁用,可用于中断进程/进程组。
请注意,这与使用按钮关闭控制台窗口不同x
。在后一种情况下,进程接收到CTRL_CLOSE_EVENT
,
当用户关闭控制台(通过单击控制台窗口的窗口菜单上的“关闭”,或单击任务管理器中的“结束任务”按钮命令)时,系统向附加到控制台的所有进程发送的信号。
该事件的处理不受创建进程时标志SetConsoleCtrlHandler(NULL,TRUE)
设置的影响。CREATE_NEW_PROCESS_GROUP
以上所有内容都意味着CREATE_NEW_PROCESS_GROUP
flag 与您所观察到的行为无关。
默认情况下,子进程继承父进程的控制台窗口和 IO 句柄。因此,当您通过单击按钮关闭 shell 时x
,它会收到CTRL_CLOSE_EVENT
并且没有不终止的选项。
为了避免这种情况,子进程不应附加到父控制台。这是通过DETACHED_PROCESS
向 Windows API 提供标志来完成的CreateProcess
。
默认情况下,控制台进程继承其父级的控制台...如果控制台进程是使用带有DETACHED_PROCESS 的CreateProcess 创建的,则控制台进程不会附加到控制台。
我认为这就是 Rubyspawn
和win32-process
gem 的不同之处。我没有尝试调试两者来查看它们提供的标志的具体差异,CreateProcess
尽管这将是一件有趣的事情。
还有其他方法可以创建子进程而不继承父进程的控制台或 IO 句柄。示例有CREATE_NO_WINDOW
或CREATE_NEW_CONSOLE
标志、作业对象等。
归档时间: |
|
查看次数: |
420 次 |
最近记录: |