我想要一个Perl守护程序来监听,并且接受从客户端传入的连接,然后派生和 exec 另一个Perl程序来继续与客户端的对话。
我只是在进行 fork 时就可以做到这一点-守护程序代码中还包含 child 的代码。但是我看不到如何通过exec()将打开的套接字“传递”到另一个Perl程序。
不知何故,我觉得这在Unix(这是我的环境)中很容易,因此在Perl中也很容易。真的可以做到吗?
最佳答案
这可以通过大约三个步骤来完成:
1. Perl(默认情况下)在打开的文件描述符上设置close-on-exec标志。这意味着不会在
exec
中保留文件描述符。您必须先清除此标志:use Fcntl;
my $flags = fcntl $fh, F_GETFD, 0 or die "fcntl F_GETFD: $!";
fcntl $fh, F_SETFD, $flags & ~FD_CLOEXEC or die "fcntl F_SETFD: $!";
2. 现在,文件描述符将在
exec
上保持打开状态,您需要告诉程序它是哪个描述符:my $fd = fileno $fh;
exec 'that_program', $fd; # pass it on the command line
# (you could also pass it via %ENV or whatever)
3. 在另一侧恢复文件句柄:
my $fd = $ARGV[0]; # or however you passed it
open my $fh, '+<&=', $fd; # fdopen
$fh->autoflush(1); # because "normal" sockets have that enabled by default
现在,您又在
$fh
中有了一个Perl级别的句柄。附录:正如池上在评论中提到的那样,您还可以确保套接字使用三个“标准”文件描述符(0(stdin),1(stdout),2(stderr))之一。 exec的默认值; 2。具有已知编号,因此无需传递任何内容; 3。perl将自动为它们创建相应的句柄。
open STDIN, '+<&', $fh; # now STDIN refers to the socket
exec 'that_program';
现在
that_program
可以简单地使用STDIN
。即使输出也可以使用。文件描述符0、1、2没有固有的限制,它们只能用于输入或输出。只是所有Unix程序都遵循的约定。
关于Perl-在fork/exec上传递一个开放的套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14351147/