2

I need to run an application called sc.exe as part of a build process in TeamCity. This little app opens a tunnel to Sauce Labs and the app itself works fine. One of the features of this application is when it's booted and ready to support testing on Sauce via the tunnel, it outputs the message Sauce Connect is up, you may now start your tests. The app needs to keep running locally to keep that tunnel open.

sc.exe doesn't exit out after the connection is made, but I need the build step to send an exit code so that it can know the tunnel is up and we're ready to go. I want the Perl script to exit with 0 and leave the sc.exe process running. I wrote this little runner script in 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.";

Now, keep in mind that system call in the backticks does work when I run it from the terminal and the output from sc.exe is as expected in that case. When I run this Perl script, the tunnel does in fact launch - I can log into Sauce Labs and see that the tunnel is active. However, this script neither exits with 0 nor does it die. What could it be doing?

I feel like I'm missing something so obvious, as usual.

Running on either Win 7 x64 or Windows Server 2008, same result.

kyoob
  • 499
  • 5
  • 23

1 Answers1

7

As the command in backticks never exits, it'll never return and won't populate $result. Try launching the command in a pipe and reading from it:

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;

Note the & at the end of the command to run the command in the background.

To get it to timeout after 60s, use an alarm:

local $SIG{ALRM} = sub { die "Did not detect open Sauce Connect tunnel." };
alarm 60;
RobEarl
  • 7,862
  • 6
  • 35
  • 50
  • Beautiful! It works! My saving grace is that I was not missing anything too obvious. – kyoob May 22 '14 at 17:05
  • Hmm, on second thought this does not seem to be exiting on Windows. The `close` in `exit()` is waiting around for `$sc` to be closed but it never does since `sc.exe` is still running in the background. How do I close this out while essentially orphaning that process to run after the Perl script has exited? – kyoob May 28 '14 at 21:16
  • Added code to forcefully kill the read process, see: http://stackoverflow.com/questions/23928271/interrupt-read-after-line-match – RobEarl May 29 '14 at 09:03
  • Won't that kill the `sc.exe` process itself? It seems like `$pid` has the `PID` for the tunnel app, which I want to keep running as an orphan after the Perl script exits. – kyoob May 29 '14 at 13:21
  • the `&` would only work in *nix. Looks like I'll have to find a way to get Perl to kick off this process in the background and wait for the message on that thread. – kyoob May 29 '14 at 21:28