如何在Ruby中模拟execl() 我有一个C++应用程序,我正在移植到Ruby。< /P>

如何在Ruby中模拟execl() 我有一个C++应用程序,我正在移植到Ruby。< /P>,ruby,linux,process,exec,file-descriptor,Ruby,Linux,Process,Exec,File Descriptor,代码的一部分使用execl(),以便在维护打开的文件描述符的同时,用自身的[n更新]副本替换进程(此应用程序是网络服务) if(execl(“./my app”,“-restart”,fd.c_str(),NULL)true:不继承 因此,在我看来,以下内容应该会产生一个新的进程,该进程可以访问父进程的所有打开的文件描述符: server\u fd=@server.to\u i 环境={ “应用程序重新启动”=>“正确”, “APP_SERVER_FD”=>SERVER_FD.to_s, } c

代码的一部分使用
execl()
,以便在维护打开的文件描述符的同时,用自身的[n更新]副本替换进程(此应用程序是网络服务)

if(execl(“./my app”,“-restart”,fd.c_str(),NULL)<0){
没过多久就发现Ruby没有与之相当的
execl()
,但您可以使用
Process::spawn
:close_others
选项部分伪造它。或者,至少我可以根据以下条件:

文件描述符继承:是否关闭未重定向的非标准FD(3、4、5…) :close_others=>true:不继承

因此,在我看来,以下内容应该会产生一个新的进程,该进程可以访问父进程的所有打开的文件描述符:

server\u fd=@server.to\u i
环境={
“应用程序重新启动”=>“正确”,
“APP_SERVER_FD”=>SERVER_FD.to_s,
}
command=“ruby my app.rb”
选项={
:in=>:in,
:out=>:out,
:err=>:err,
:close_others=>false,
}
pid=Process.spawn环境、命令、选项
进程分离pid
这将允许子进程访问描述符…但是,如果不关闭所有描述符,我无法确定如何
退出父进程。换句话说,如果我在代码末尾导致父进程
退出

server\u fd=@server.to\u i
环境={
“应用程序重新启动”=>“正确”,
“APP_SERVER_FD”=>SERVER_FD.to_s,
}
command=“ruby my app.rb”
选项={
:in=>:in,
:out=>:out,
:err=>:err,
:close_others=>false,
}
pid=Process.spawn环境、命令、选项
进程分离pid
退出#添加了这一行
然后,描述符也为孩子关闭

我觉得这更像是我的流程管理方法的问题,而不是Ruby特有的问题,但我不知道我做错了什么



EDIT1 在调用
Process.spawn
(或@mata指出的
Process.exec
)之前,我有一个诊断输出:

system'lsof-c ruby'
在我的
recover\u from\u reboot
方法中还有一个调用。这是输出预重新启动的尾部,您可以在最后两行中看到侦听服务器端口和连接的客户端:

ruby    8957 chris    0u   CHR    136,1      0t0        4 /dev/pts/1
ruby    8957 chris    1u   CHR    136,1      0t0        4 /dev/pts/1
ruby    8957 chris    2u   CHR    136,1      0t0        4 /dev/pts/1
ruby    8957 chris    3r  FIFO      0,8      0t0 12213372 pipe
ruby    8957 chris    4w  FIFO      0,8      0t0 12213372 pipe
ruby    8957 chris    5r  FIFO      0,8      0t0 12213373 pipe
ruby    8957 chris    6w  FIFO      0,8      0t0 12213373 pipe
ruby    8957 chris    7u  IPv4 12213374      0t0      TCP localhost.localdomain:boks-servc (LISTEN)
ruby    8957 chris    8u  IPv4 12213423      0t0      TCP localhost.localdomain:boks-servc->localhost.localdomain:45249 (ESTABLISHED)
这是我在重启后看到的:

ruby    8957 chris    3r  FIFO    0,8      0t0 12203947 pipe
ruby    8957 chris    4w  FIFO    0,8      0t0 12203947 pipe
ruby    8957 chris    5r  FIFO    0,8      0t0 12203948 pipe
ruby    8957 chris    6w  FIFO    0,8      0t0 12203948 pipe
这也是我是否尝试
spawn
exec


EDIT2 根据我的诊断输出,我看到服务器保持绑定到FD7,客户端保持绑定到8

7=>7,
8 => 8,

对于我的
选项
阵列,我能够使用
exec
在重新启动期间成功地保留这些套接字。我可以手动添加服务器和
[client1,client2,…]
fd
s选项散列,但是当
关闭其他人
应该为我做繁重的工作时,这看起来非常脏。

这当然不是我想要的解决方案,但是在没有任何关于
的披露的情况下:关闭选项
散列和
进程。生成
进程。exec
,,最后,我手动将我关心的所有文件描述符添加到
选项
s数组中,实现了以下目的:

server\u fd=self.server.to\u i
client_fds=self.clients.map{| c | c.get_fd}
环境={
“应用程序重新启动”=>“正确”,
“APP_SERVER_FD”=>SERVER_FD.to_s,
“APP_CLIENT_FDS”=>封送处理转储(CLIENT_FDS),
}
选项={
:in=>:in,
:out=>:out,
:err=>:err,
:close_others=>false,
}
#将服务器套接字添加到选项哈希中。
选项[server\u fd]=server\u fd
#将所有客户端套接字添加到选项哈希中。
@clients.each{c|options[c.get_fd]=c.get_fd}
#重新开始。
Process.exec env,App.binary.to_,options

我会暂时不接受这个答案,以防有人来澄清事实。

为什么不直接使用它呢?它完成了
execl
在C中所做的一切…很好的呼叫@mata,不幸的是,我仍然看到相同的结果。
ruby    8957 chris    3r  FIFO    0,8      0t0 12203947 pipe
ruby    8957 chris    4w  FIFO    0,8      0t0 12203947 pipe
ruby    8957 chris    5r  FIFO    0,8      0t0 12203948 pipe
ruby    8957 chris    6w  FIFO    0,8      0t0 12203948 pipe