perl - 如何在 perl 中禁用 stdout 重定向到文件缓冲?

标签 perl bash redirect buffering

这是一个启动 10 个进程的脚本,每个进程向其 STDOUT 写入 100,000 行,该 STDOUT 是从父进程继承的:

#!/usr/bin/env perl
# buffer.pl
use 5.10.0;
use strict;
use warnings FATAL => "all";
use autodie;

use Parallel::ForkManager;
my $pm = Parallel::ForkManager->new(4);

$|=1; # don't think this does anything with syswrite...

# start 10 jobs which write 100,000 lines each
for (1 .. 10 ) {
    $pm->start and next;

    for my $j (1 .. 100_000) {
        syswrite(\*STDOUT,"$j\n");
    }

    $pm->finish;
}
$pm->wait_all_children;

如果我通过管道传输到另一个进程,一切都很好..

$ perl buffering.pl | wc -l
1000000

但是如果我通过管道传输到磁盘,系统写入就会互相破坏。

$ perl buffering.pl > tmp.txt ; wc -l tmp.txt
457584 tmp.txt

此外,如果我在子进程中打开写入文件句柄并直接写入 tmp.txt:

#!/usr/bin/env perl
# buffering2.pl
use 5.10.0;
use strict;
use warnings FATAL => "all";
use autodie;

use Parallel::ForkManager;
my $pm = Parallel::ForkManager->new(4);

$|=1;

for (1 .. 10) {
    $pm->start and next;
    open my $fh, '>', 'tmp.txt';

    for my $j (1 .. 100_000) {
        syswrite($fh,"$j\n");
    }
    close $fh;

    $pm->finish;
}
$pm->wait_all_children;

tmp.txt 如预期有 1,000,000 行。

$ perl buffering2.pl; wc -l tmp.txt
100000 tmp.txt

那么通过“>”重定向到磁盘有某种缓冲,但重定向到进程则没有?这是怎么回事?

最佳答案

当你重定向整个 perl 脚本时,你会得到一个文件描述符(当你执行 > tmp.txt 时由 shell 创建并由 perl 继承为 stdout),即 dup送给每个 child 。当您明确 open在每个子文件中,您都会获得不同的文件描述符(不是原始文件的 dup )。如果您提升 open my $fh, '>', 'tmp.txt',您应该能够复制 shell 重定向情况。脱离你的循环。

管道情况之所以有效,是因为您正在与管道而不是文件进行通信,并且它没有偏移量的概念,正如我上面所描述的,偏移量可能会无意中在内核中共享。

关于perl - 如何在 perl 中禁用 stdout 重定向到文件缓冲?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6542199/

相关文章:

perl - 在 mojolicious 中测试 JSON PUT 请求

python - linux 文件中每行下面的总和行

c - makefile C 奇怪的 bash 命令行为

java - response.sendRedirect 应在新窗口中打开

asp.net-mvc - IIS7 网址重写 - 从 {any}.aspx 重定向到 {any}

perl - 分发 Perl 应用程序

perl - 数百万条目的 SQLite 优化?

regex - Perl 正则表达式压缩多个换行符

linux - Bash Shell - 引用问题

php - 页面是否可能知道已使用header()重定向到该页面?