【问题标题】:Why does this Perl script not exit or die after 60 seconds?为什么这个 Perl 脚本在 60 秒后不退出或死掉?
【发布时间】:2014-05-22 16:40:35
【问题描述】:

我需要在 TeamCity 的构建过程中运行一个名为 sc.exe 的应用程序。这个小应用程序打开了通往 Sauce Labs 的隧道,应用程序本身运行良好。此应用程序的功能之一是当它启动并准备好支持通过隧道对 Sauce 进行测试时,它会输出消息 Sauce Connect is up, you may now start your tests. 该应用程序需要继续在本地运行以保持该隧道打开。

sc.exe 在建立连接后不会退出,但我需要构建步骤来发送退出代码,以便它可以知道隧道已启动并且我们准备好了。我希望 Perl 脚本与 0 一起使用 exit 并让 sc.exe 进程运行。我用 Perl 写了这个小运行脚本:

#!/user/bin/perl

use strict;
use warnings;

my $result = `sc -v --pac file://browsermob.js -u $ENV{SAUCE_USER_NAME} -k $ENV{SAUCE_API_KEY}`;

for (my $i = 0; $i < 60; $i++) {
    if ($result =~ /Sauce Connect is up, you may start your tests\./) {
        print $result;
        exit 0;
        }
    sleep(1);
    }

die "Did not detect open Sauce Connect tunnel.";

现在,请记住,当我从终端运行它时,反引号中的系统调用确实有效,并且sc.exe 的输出在这种情况下与预期的一样。当我运行这个 Perl 脚本时,隧道确实启动了——我可以登录到 Sauce Labs 并看到隧道处于活动状态。但是,此脚本既不会以0 退出,也不会以die 退出。它能做什么?

像往常一样,我觉得我错过了一些如此明显的东西。

在 Win 7 x64 或 Windows Server 2008 上运行,结果相同。

【问题讨论】:

  • perl 等待 sc 完成。

标签: windows multithreading perl process exit


【解决方案1】:

由于反引号中的命令永远不会退出,它永远不会返回并且不会填充$result。尝试在管道中启动命令并从中读取:

open(my $sc, "-|", "sc -v --pac file://browsermob.js -u $ENV{SAUCE_USER_NAME} -k $ENV{SAUCE_API_KEY} &");
while (<$sc>) {
    print && exit 0 if /Sauce Connect is up, you may start your tests\./;
}
close $sc;

注意命令末尾的&amp;,以便在后台运行命令。

要让它在 60 秒后超时,请使用 alarm

local $SIG{ALRM} = sub { die "Did not detect open Sauce Connect tunnel." };
alarm 60;

【讨论】:

  • 漂亮!有用!我的可取之处在于我没有遗漏任何太明显的东西。
  • 嗯,再想想这似乎并没有在 Windows 上退出。 exit() 中的 close 正在等待 $sc 关闭,但它永远不会关闭,因为 sc.exe 仍在后台运行。在 Perl 脚本退出后基本上孤立该进程以运行时,如何关闭它?
  • 添加了强制终止读取进程的代码,参见:stackoverflow.com/questions/23928271/…
  • 这不会杀死sc.exe 进程本身吗?似乎$pid 有隧道应用程序的PID,我想在 Perl 脚本退出后继续作为孤儿运行。
  • &amp; 仅适用于 *nix。看来我得想办法让 Perl 在后台启动此进程并等待该线程上的消息。
猜你喜欢
  • 1970-01-01
  • 2010-11-05
  • 2016-09-19
  • 1970-01-01
  • 1970-01-01
  • 2019-11-10
  • 2015-05-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多