从Perl,生成一个shell,配置它,并分叉STDOUT

时间:2013-04-10 18:58:21

标签: perl shell fork pipe stdout

我使用Perl脚本配置和生成已编译的程序,需要以某种方式配置子shell,因此我使用$returncode = system("ulimit -s unlimited; sg ourgroup 'MyExecutable.exe'");

我想从中捕获并解析STDOUT,但是我需要它分叉,以便在作业仍在运行时检查输出。这个问题很接近: How can I send Perl output to a both STDOUT and a variable?评分最高的答案描述了一个名为backtick()的函数,该函数创建子进程,捕获STDOUT,并使用exec()在其中运行命令。

但是我的调用需要多行来配置shell。一种解决方案是创建一次性shell脚本:

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

然后我可以使用backtick(disposable.sh)open(PROCESS,'disposable.sh|')获得我需要的内容。

但我真的不想为此制作一个临时文件。 system()愉快地接受多行命令字符串。如何让exec()open()做同样的事情?

3 个答案:

答案 0 :(得分:1)

如果你想使用shell的强大功能(包括循环,变量,还有多个命令执行),你必须调用shell(open(..., 'xxx|')不这样做。)

您可以使用shell的-c选项将shell脚本传递给shell(另一种可能是将命令传递给shell,但这更难恕我自己)。 这意味着从另一个答案中调用backtick函数,如下所示:

backtick("sh", "-c", "ulimit -s unlimited; sg ourgroup 'MyExecutable.exe'");

答案 1 :(得分:0)

应该使用Expect,因为您与您的计划进行互动http://metacpan.org/pod/Expect 假设您的* nix上的/ bin / bash匹配类似 bash-3.2 $ 的内容,以下程序可用于使用$ exp->发送bash上的命令启动数量然后可以解析每个命令的控制台和输出以进行进一步的操作。

#!/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";

答案 2 :(得分:0)

带有反引号的系统tee会执行此操作,不是吗?

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

或修改Alnitak的backticks(所以它确实使用子shell)?

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