更改 Perl 6 的 $*OUT 是否会更改子进程的标准输出? [英] Does changing Perl 6's $*OUT change standard output for child processes?

查看:42
本文介绍了更改 Perl 6 的 $*OUT 是否会更改子进程的标准输出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在玩 shell 以及当我更改调用程序中的标准文件句柄时它的行为.Proc 说:

I was playing around with shell and how it acts when I change the standard filehandles in the calling program. Proc says:

$in、$out 和 $err 是待启动程序的三个标准流,默认为-",表示继承父进程的流.

$in, $out and $err are the three standard streams of the to-be-launched program, and default to "-", which means they inherit the stream from the parent process.

据我所知,外部程序不使用相同的文件句柄:

As far as I can tell, the external program doesn't use the same file handles:

#!/Applications/Rakudo/bin/perl6

#`(
    make an external Perl 6 program the outputs to standard handles
    )
my $p6-name = 'in-out.p6'.IO;
#END try $p6-name.unlink; # why does this cause it to fail?
my $p6-fh = open $p6-name, :w;
die "Could not open $p6-name" unless ?$p6-fh;
$p6-fh.put: Q:to/END/;
    #!/Applications/Rakudo/bin/perl6

    $*ERR.say( qq/\t$*PROGRAM: This goes to standard error/ );
    $*OUT.say( qq/\t$*PROGRAM: This goes to standard output/ );
    END
$p6-fh.close;
say $p6-name.e ?? 'File is there' !! 'File is not there';
die "$p6-name does not exist" unless $p6-name.e;

{
#`(
    Start with some messages to show that we can output to
    the standard filehandles.
    )
$*OUT.put: "1. standard output before doing anything weird";
$*ERR.put: "2. standard error before doing anything weird";
shell( "perl6 $p6-name" ).so;
}

{
#`(
    This block assigns a new filehandle to $*OUT and prints a
    message to it. I expect that message to not show up in the
    terminal.

    It then calls run-them to fire off the external process. It
    should inherit the same standard out and its standard out
    messages should not show up. But, they do.
    )
temp $*OUT = open '/dev/null', :w;
$*OUT.put: "3. temp redefine standard output before this message";
shell( "perl6 $p6-name" ).so;
}

$*OUT.put: "4. everything should be back to normal";

输出显示,当我打开 /dev/null 并将其文件句柄分配给 $*OUT 时,当前程序的输出没有显示在终端中(没有以 3. 开头的输出).但是,当我调用 shell 时,它的标准输出会转到原始标准输出:

The output shows that when I open /dev/null and assign its filehandle to $*OUT, the output from the current program don't show up in terminal (there's no output starting with 3.). However, when I call shell, its standard output goes to the original standard output:

File is there
1. standard output before doing anything weird
2. standard error before doing anything weird
    in-out.p6: This goes to standard error
    in-out.p6: This goes to standard output
    in-out.p6: This goes to standard error
    in-out.p6: This goes to standard output
4. everything should be back to normal

我不担心如何做到这一点.我可以创建一个 Proc 对象并将文件句柄传递给它.

I'm not worried about how to make this happen. I can create a Proc object and pass filehandles to it.

还有什么事情吗?

推荐答案

默认情况下,$*OUT 中的 IO::Handle 绑定到操作系统提供的低级 STDOUT 文件句柄.

By default the IO::Handle that is in $*OUT is bound to the low-level STDOUT filehandle given by the operating system.

shellrun 只是让生成的进程使用提供给 Perl 6 的低级 STDOUT 文件,除非您另外指定.

shell and run just let the spawned process use the low-level STDOUT file that was given to Perl 6, unless you specify otherwise.

Perl 6 在产生新进程之前不会改变外部环境的任何内容.

Perl 6 doesn't change anything about the outside environment until the moment before it spawns a new process.

最简单的方法是将您要使用的文件句柄对象提供给带有命名参数的 shellrun 调用.

The simplest thing to do is to give the filehandle object you want to use to the shell or run call with a named argument.

# no testing for failure because the default is to throw an error anyway

my $p6-name = 'in-out.p6'.IO;
END $p6-name.unlink;

$p6-name.spurt(Q'put "STDOUT: @*ARGS[0]";note "STDERR: @*ARGS[0]"');

run $*EXECUTABLE, $p6-name, 'run', :out(open '/dev/null', :w);

{
  temp $*OUT = open '/dev/null', :w;
  shell "'$*EXECUTABLE' '$p6-name' 'shell'", :err($*OUT);
}

结果是

STDERR: run
STDOUT: shell

在丢弃输出数据的特殊情况下,应该使用 :!out:!err 代替.

In the particular case of throwing away the output data, :!out or :!err should be used instead.

run $*EXECUTABLE, $p6-name, 'no STDERR', :!err;

STDOUT: no STDERR

<小时>

如果您只想为您拦截数据 :out:err 就这样做;

my $fh = run( $*EXECUTABLE, $p6-name, 'capture', :out ).out;
print 'captured: ',$fh.slurp-rest;

captured: STDOUT capture

这篇关于更改 Perl 6 的 $*OUT 是否会更改子进程的标准输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆