我有一个名为my_bash.sh
的脚本,它调用perl脚本,并将perl脚本的输出附加到日志文件中。只有在perl脚本完成后才能写入文件吗?
my_bash.sh
#!/bin/bash
echo "Starting!" > "my_log.log"
perl my_perl.pl >> "my_log.log" 2>&1
echo "Ending!" >> "my_log.log"
问题是,当perl脚本正在运行时,我想在my_log.log
文件运行时操作它,但看起来该文件是空白的。有没有正确的方法来做到这一点?如果您想了解更多信息,请与我们联系。
my_perl.pl
...
foreach $component (@arrayOfComponents)
{
print "Component Name: $component (MORE_INFO)\n";
# Do some work to gather more info (including other prints)
#...
# I want to replace "MORE_INFO" above with what I've calculated here
system("sed 's/MORE_INFO/$moreInfo/' my_log.log");
}
sed
无法正常运行,因为print
语句尚未进入my_log.log
。
答案 0 :(得分:2)
此问题的答案取决于my_perl.pl
输出数据的方式以及输出的数据量。
如果您使用普通(缓冲)I / O来产生输出,那么只有在STDOUT缓冲区填充后才会写入my_log.log
。一般来说,如果你没有产生大量的输出,那就是程序结束并刷新缓冲区。
如果您正在产生足够的输出来填充输出缓冲区,那么在my_log.log
完成之前,您将在my_perl.pl
中获得输出。
此外,在Perl中,您可以使用以下代码使STDOUT无缓冲:
select STDOUT; $| = 1;
在这种情况下,您的输出将在脚本中生成的那一刻写入STDOUT(然后通过重定向写入my_log.log
。
答案 1 :(得分:2)
默认情况下,Perl会缓冲输出。禁用缓冲集$|
为非零值。添加
$|++;
位于perl脚本的顶部。
$|
如果设置为非零,则立即强制刷新并在每次写入或之后 在当前选定的输出通道上打印。默认值为0 (无论通道是否真的由系统缓冲或 不;
$|
仅告诉您是否已明确要求Perl进行刷新 每次写完后)。如果输出为STDOUT
,通常会进行行缓冲 到终端和否则缓冲块。设置此变量是 主要用于输出管道或插槽时,例如 当您在rsh下运行Perl程序并想要查看时 输出正在发生。这对输入缓冲没有影响。看到 getc为此。请参阅有关如何选择输出通道的选择。看到 还有IO :: Handle。助记符:当你想让你的烟斗滚烫时。
答案 2 :(得分:0)
根据您需要对日志文件执行的操作,谁可以从perl脚本读取每行输出,对该行执行某些操作,然后自己(或不)将其写入日志:
#!/bin/bash
echo "Starting!" > "my_log.log"
perl my_perl.pl | \
while read line; do
# do something with the line
echo "$line" >> "my_log.log"
done
echo "Ending!" >> "my_log.log"
答案 3 :(得分:0)
介于两者之间
print "Component Name: $component (MORE_INFO)\n";
和
system("sed 's/MORE_INFO/$moreInfo/' my_log.log");
你打印东西吗?如果没有,请延迟第一次打印,直至找到$moreInfo
my $header = "Component Name: $component (MORE_INFO)";
# ...
# now I have $moreInfo
$header =~ s/MORE_INFO/$moreInfo/;
print $header, "\n";
如果你打印东西,你可以随时“排队”它,直到你得到你需要的信息:
my @output;
foreach my $component (...) {
@output = ("Component Name: $component (MORE_INFO)");
# ...
push @output, "something to print";
# ...
$output[0] =~ s/MORE_INFO/$moreInfo/;
print join("\n", @output), "\n";