Shell 更改Perl 6';s$*是否更改了子进程的标准输出?

Shell 更改Perl 6';s$*是否更改了子进程的标准输出?,shell,stdout,raku,Shell,Stdout,Raku,我正在玩shell,以及在调用程序中更改标准文件句柄时它的行为。说: $in、$out和$err是要启动程序的三个标准流,默认为“-”,这意味着它们从父进程继承流 据我所知,外部程序不使用相同的文件句柄: #!/Applications/Rakudo/bin/perl6 #`( make an external Perl 6 program the outputs to standard handles ) my $p6-name = 'in-out.p6'.IO; #END

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

$in、$out和$err是要启动程序的三个标准流,默认为“-”,这意味着它们从父进程继承流

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

#!/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
时,其标准输出变为原始标准输出:

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
对象并将文件句柄传递给它


是否还有其他问题?

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

shell
run
只要让生成的进程使用提供给Perl 6的低级标准输出文件,除非您另有指定

Perl 6在生成新进程之前不会改变任何外部环境


最简单的方法是将要使用的filehandle对象指定给带有命名参数的
shell
run
调用

#没有失败测试,因为默认情况下无论如何都会抛出错误
我的$p6 name='in out.p6'.IO;
结束$p6-name.unlink;
$p6 name.sprut(Q'put“STDOUT:@*ARGS[0]”;注意“STDERR:@*ARGS[0]”);
运行$*可执行文件,$p6 name,'run',:out(打开'/dev/null',:w);
{
temp$*OUT=open'/dev/null',:w;
shell“$*可执行文件“$p6名称”“shell”“”:err($*OUT);
}
这导致

STDERR:运行
标度:贝壳
在丢弃输出数据的特殊情况下,
:!退出
:!应改用err

run$*可执行文件,$p6名称,'no STDERR',:!犯错误
STDOUT:没有STDERR

如果您只想为自己截取数据,请执行以下操作:

my$fh=run($*可执行文件,$p6名称,'capture',:out);
打印“捕获:”,$fh.slurp-rest;
captured:STDOUT捕获

MoarVM中的相关代码似乎在。在Windows上,第一次运行脚本时,它找不到刚刚创建的文件。在第二次运行时,我观察到了相同的行为(将
/dev/null
替换为
NUL
)。文档中是否有讨论“基本上修改Perl 6中除%*ENV之外的任何变量都不会产生任何外部影响”的地方?这是一个设计目标还是一个实现问题?