在 perl 中重定向输出时 fork exec Kill 出现问题

发布于 2024-09-04 05:28:41 字数 1054 浏览 1 评论 0原文

我在 perl 中创建了一个脚本来运行带有超时的程序。如果正在执行的程序花费的时间比超时时间长,则脚本会终止该程序并返回消息“TIMEOUT”。

该脚本运行得很好,直到我决定重定向执行程序的输出。

当 stdout 和 stderr 被重定向时,脚本执行的程序不会被终止,因为它的 pid 与我从 fork 获得的 pid 不同。

看起来 perl 执行的 shell 在重定向的情况下执行我的程序。

我希望有输出重定向,但仍然能够在超时的情况下终止程序。

关于我如何做到这一点有什么想法吗?

我的脚本的简化代码是:

#!/usr/bin/perl

use strict;
use warnings;
use POSIX ":sys_wait_h";

my $timeout = 5;
my $cmd = "very_long_program 1>&2 > out.txt";

my $pid = fork();
if( $pid == 0 )
{
   exec($cmd) or print STDERR "Couldn't exec '$cmd': $!";
   exit(2);
}
my $time = 0;
my $kid = waitpid($pid, WNOHANG);
while ( $kid == 0 )
{
   sleep(1);
   $time ++;
   $kid = waitpid($pid, WNOHANG);
   print "Waited $time sec, result $kid\n";
   if ($timeout > 0 && $time > $timeout)
   {
      print "TIMEOUT!\n";
      #Kill process
      kill 9, $pid;
      exit(3);
   }
}

if ( $kid == -1)
{
   print "Process did not exist\n";
   exit(4);
}
print "Process exited with return code $?\n";
exit($?);

感谢您的帮助。

I created a script in perl to run programs with a timeout. If the program being executed takes longer then the timeout than the script kills this program and returns the message "TIMEOUT".

The script worked quite well until I decided to redirect the output of the executed program.

When the stdout and stderr are being redirected, the program executed by the script is not being killed because it has a pid different than the one I got from fork.

It seems perl executes a shell that executes my program in the case of redirection.

I would like to have the output redirection but still be able to kill the program in the case of a timeout.

Any ideas on how I could do that?

A simplified code of my script is:

#!/usr/bin/perl

use strict;
use warnings;
use POSIX ":sys_wait_h";

my $timeout = 5;
my $cmd = "very_long_program 1>&2 > out.txt";

my $pid = fork();
if( $pid == 0 )
{
   exec($cmd) or print STDERR "Couldn't exec '$cmd': $!";
   exit(2);
}
my $time = 0;
my $kid = waitpid($pid, WNOHANG);
while ( $kid == 0 )
{
   sleep(1);
   $time ++;
   $kid = waitpid($pid, WNOHANG);
   print "Waited $time sec, result $kid\n";
   if ($timeout > 0 && $time > $timeout)
   {
      print "TIMEOUT!\n";
      #Kill process
      kill 9, $pid;
      exit(3);
   }
}

if ( $kid == -1)
{
   print "Process did not exist\n";
   exit(4);
}
print "Process exited with return code $?\n";
exit($?);

Thanks for any help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

贵在坚持 2024-09-11 05:28:41

尝试将 $cmd 从 更改

my $cmd = "very_long_program 1>&2 > out.txt";

my $cmd = "exec very_long_program 1>&2 > out.txt";

exec 将告诉由 perl 生成的 shell 将其自身替换为very_long_program,而不是作为子进程运行very_long_program。

(在这种情况下,perl 生成 shell 的原因是因为 $cmd 包含重定向字符 - 而 perl 本身不知道如何处理它们。解决该问题的另一种方法是进行重定向在 Perl 本身中,在 fork() 之后但在调用 exec() 之前 - 但这有点棘手,所以首先尝试 exec 解决方法!)

Try changing $cmd from

my $cmd = "very_long_program 1>&2 > out.txt";

to

my $cmd = "exec very_long_program 1>&2 > out.txt";

The exec will tell the shell that gets spawned by perl to replace itself with very_long_program, rather than running very_long_program as a child.

(The reason perl spawns a shell in this case is because $cmd contains the redirect characters - and perl doesn't know how to handle them itself. An alternative way of solving the problem is to do the redirection in perl itself after the fork() but prior to calling exec() - but that's slightly trickier, so try the exec workaround first!)

旧街凉风 2024-09-11 05:28:41

另一种方法是在 fork 之后重定向 STDOUT 和 STDERR 并在不重定向的情况下运行命令:

open(STDOUT, ">", "out.txt") or die "Err: $!";
open(STDERR, ">&STDOUT");
exec("very_long_command");
die "Failed to exec very_long_command: $!";

An alternative is to redirect STDOUT and STDERR after the fork and run the command without the redirection:

open(STDOUT, ">", "out.txt") or die "Err: $!";
open(STDERR, ">&STDOUT");
exec("very_long_command");
die "Failed to exec very_long_command: $!";
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文