質問

I'm having problems with Perl on Windows (both ActivePerl and Strawberry), when redirecting a script STDOUT to a pipe, and using sleep(). Try this:

perl -e "for (;;) { print 'Printing line ', $i++, \"\n\"; sleep(1); }"

This works as expected. Now pipe it to Tee (or some file, same result):

perl -e "for (;;) { print 'Printing line ', $i++, \"\n\"; sleep(1); }" | tee

There's no output at all, tee captures nothing. However, the perl script is still running, only there's nothing on STDOUT until the script finishes, and then all output is dumped to tee. Except, if the STDOUT buffer fills the script might hang.

Now, if you remove the sleep(call), the pipe works as expected! What's going on?

I found a workaround; disabling the STDOUT buffering with $|=1 makes the pipe work when using the sleep, but... why? Can anyone explain and offer a better solution?

役に立ちましたか?

解決

You are suffering from buffering. Add $| = 1; to unbuffer STDOUT.

All file handles except STDERR are buffered by default, but STDOUT uses a minimal form of buffering (flushed by newlines) when connected to a terminal. By substituting the terminal for a pipe, normal buffering is reinstated.

Removing the sleep call doesn't change anything except to speeds things up. Instead of taking minutes to fill up the buffer, it takes milliseconds. With or without it, the output is still written in 4k or 8k blocks (depending on your version of Perl).

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top