0

I use a Perl script to configure and spawn a compiled program, that needs a subshell configured a certain way, so I use $returncode = system("ulimit -s unlimited; sg ourgroup 'MyExecutable.exe'");

I want to capture and parse the STDOUT from that, but I need it forked, so that the output can be checked while the job is still running. This question comes close: How can I send Perl output to a both STDOUT and a variable? The highest-rated answer describes a function called backtick() that creates a child process, captures STDOUT, and runs a command in it with exec().

But the calls I have require multiple lines to configure the shell. One solution would be to create a disposable shell script:

#disposable.sh
    #!/bin/sh
    ulimit -s unlimited
    sg ourgroup 'MyExecutable.exe'

I could then get what I need either with backtick(disposable.sh) or open(PROCESS,'disposable.sh|').

But I'd really rather not make a scratch file for this. system() happily accepts multi-line command strings. How can I get exec() or open() to do the same?

Community
  • 1
  • 1
Ed Hyer
  • 1,385
  • 2
  • 13
  • 19

3 Answers3

1

If you want to use shell's power (that includes loops, variables, but also multiple command execution), you have to invoke the shell (open(..., 'xxx|') doesn't do that).

You can pass your shell script to the shell with the -c option of the shell (another possibility would be to pipe the commands to the shell, but that's more difficult IMHO). That means calling the backtick function from the other answer like this:

backtick("sh", "-c", "ulimit -s unlimited; sg ourgroup 'MyExecutable.exe'");
jpalecek
  • 47,058
  • 7
  • 102
  • 144
0

Expect should be used as you are interacting with your program: http://metacpan.org/pod/Expect Assuming /bin/bash on your *nix matches something like bash-3.2$ the below program can be used to launch number of commands using $exp->send on bash console and output from each command can then be parsed for further actions.

#!/usr/bin/perl
use Expect;
my $command="/bin/bash";
my @parameters;
my $exp= new Expect;
$exp->raw_pty(1);
$exp->spawn($command);
$exp->expect(5, '-re', 'bash.*$');
$exp->send("who \n");
$exp->expect(10, '-re', 'bash.*$');
my @output = $exp->before(); 
print "Output of who command is @output \n";
$exp->send("ls -lt \n");
$exp->expect(10, '-re', 'bash.*$');
my @output = $exp->before(); 
print "Output of ls command is @output \n";
szabgab
  • 6,202
  • 11
  • 50
  • 64
0

The system tee with backticks will do this, no?

my $output = `(ulimit -s unlimited; sg ourgroup 'MyExecutable.exe') | tee /dev/tty`;

or modify Alnitak's backticks (so it does use a subshell)?

my $cmd = "ulimit -s unlimiited ; sg ourgroup 'MyExecutable.exe'";
my $pid = open(CMD, "($cmd) |");
my $output;
while (<CMD>) {
   print STDOUT $_;
   $output .= $_;
}
close CMD;
mob
  • 117,087
  • 18
  • 149
  • 283