perl - Perl,如何从 exec、system、Win32 和 Unix 上的打开函数中获取线程的 pid
问题描述
这个问题并不新鲜,https://www.perlmonks.org/?node_id=620645,但我没有找到解决问题的有效答案。简而言之,我想访问由 system、exec 或 open 等函数创建的线程/进程的 PID。我使用open函数发现的一个my $pid = open my $fhOut, "| the command ", or die ...;
,在Linux中,根据ps
命令实际PID值为$pid + 2
,但在wind32中,实际PID是负数(如-1284)。在这两种情况下,open 函数返回的 PID 都与 $pid 不同!!
同样,返回的 pidmy $pid = system 1, "command params"
与操作系统的 PID 不匹配。有人可以解释一下吗?退出从打开或系统函数调用的无限循环程序的正确方法是什么。这是我的测试代码:
my $pid = fork();
if( $pid == 0 )
{
my $mimperf_pid = open my $cmd, "mimperf -C $db > results/mimperf/mimperf.log |" or die $!;
sleep(10);
print $mimperf_pid;
kill 'KILL', $mimperf_pid;
exit 0;
}
在这段代码中,我试图杀死通过该open
函数创建的线程 ($mimperf_pid),但它没有成功。
解决方案
fork()
Windows 不支持,因此 Perl(很差)使用线程来模拟它。这些虚拟进程具有负 PID。如果可以的话,你应该避免fork()
在 Windows 上使用,如果没有别的,就使用线程。
不过,这与您的问题无关。虽然返回的 PIDfork
是负数,但返回的 PIDopen
不是。
一个人通常应该避免两个参数open
,所以
open my $cmd, "foo bar |"
相当于
open my $cmd, "-|", "foo bar"
这相当于
open my $cmd, "-|", "cmd", "/x", "/c", "foo bar"
您正在启动一个 shell 来执行一个 shell 命令,它是open
返回的 shell 的 PID。
也一样system 1, $shell_cmd
。
这意味着 Ctrl-Break 信号正在发送到 shell。(这就是 Perl 发送的代替不存在的 SIGKILL 的内容。)
现在,我没有,mimperf
所以我使用了替代程序而不是mimperf
( perl
),它收到了 Ctrl-Break 信号以及 shell。所以如果mimperf
没有退出,也许是因为它对 Ctrl-Break 没有响应?
如果要避免使用 shell,则需要自己进行输出重定向。为此,我推荐IPC::Run。它也处理超时。
use IPC::Run qw( run );
run [ "mimperf", "-C", $db ],
">", "results/mimperf/mimperf.log",
timeout(10);
推荐阅读
- c - 如何检查用户没有在C中输入十进制
- mysql - 如何在 SQL 代码中不使用 groupby 来选择最大行数?
- html - 使锚点填充父宽度和高度的 100%
- spring-data-jpa - Spring Data JPA 复合键作为 EmbeddedId 不起作用,在获取映射实体时出错
- python - Python 范围混淆
- java - 从 JPanel(包含)更新 JFrame(容器或所有者),无需显式引用
- r - 强制一个命名空间覆盖/优先于另一个而不改变加载顺序?
- c - 键入的代码与书中完全相同,返回错误
- python - 接收 AttributeError:“元组”对象没有属性“T”
- docker - 无法在 Windows 10 上减小 Docker 最大磁盘映像大小