- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图在 bash 脚本中逐行收集多个子进程的输出,以便将其转发给另一个进程。
我发现没有任何东西可以保证子流程的输出不会混合,但对我来说重要的是每条输出线都正确地输出。输出之间的顺序无关紧要。
这是一个混合/乱码输出的例子:
#!/bin/bash
for i in {1..1000}; do
( { echo BEGIN; dmesg; echo END; } | tr -d '\n'; echo ) &
done
wait
运行这个:
$ ./test_output.sh | perl -ne 'print "$1\n" if m/(.{1,20}BEGIN.{0,20})/' | head
0.000000] SRAT: PXMBEGIN[ 0.000000] Initi
ME through PCIe PME BEGIN[ 0.000000] Initi
ME through PCIe PME BEGIN[ 0.000000] Initi
[ 0.209816] pci 0BEGIN[ 0.000000] Initi
ciehp 0000:00:16.1:pBEGIN[ 0.000000] Initi
CI: Updating contextBEGIN[ 0.000000] Initi
l family 2[ 0.588BEGIN[ 0.000000] Initi
ME through PCIe PME BEGIN[ 0.000000] Initi
CI: Updating contextBEGIN[ 0.000000] Initi
3922 pages, LIFO batBEGIN[ 0.000000] Initi
你可以看到几行混合内容。
当然,没有 &
一切都很好。
所以现在,我别无选择,只能将每个 child 的输出重定向到一个文件,然后在一个很大的wait
之后,cat
所有这些文件。
使用 GNU parallel 运行相同的程序可以完成部分工作,但在我的环境中这不是一个选项。
GNU parallel makes sure output from the commands is the same output as you would get had you run the commands sequentially. This makes it possible to use output from GNU parallel as input for other programs.
因此 GNU parallel 将在每个作业完成后立即写入每个作业输出,并且注意不要混合输出。那挺好的。但我也有兴趣尽快获得每项工作的输出,即不等待工作退出。有一个“-u”开关,但它会混合作业输出。
我需要使用 fifo、select 甚至编写 perl 脚本吗?
--
我想我已经找到了输出在 man 7 管道中混合的原因/方式/时间
POSIX.1-2001 says that write(2)s of less than PIPE_BUF bytes must be atomic: the output data is written to the pipe as a contiguous sequence. Writes of more than PIPE_BUF bytes may be nonatomic: the kernel may interleave the data with data written by other processes. POSIX.1-2001 requires PIPE_BUF to be at least 512 bytes. (On Linux, PIPE_BUF is 4096 bytes.)
最佳答案
这是我的第一次抽奖。这是一个简单的脚本,它在后台启动 stdin 上给出的所有命令(不确定这是我想要的)并逐行收集这些命令的输出。
#!/usr/bin/env perl
use strict;
use warnings;
use IO::Select;
use POSIX qw(strftime);
my $SELECT_TIMEOUT = 1;
my $TAG_SEPARATOR = '|';
my $TAG_TIMESTAMP_FORMAT = '%Y-%m-%dT%H:%M:%S';
sub multiplex {
my @commands = @_;
my %tags = (); # fd -> cmd
my $sel = IO::Select->new();
for my $cmd (@commands) {
$cmd =~ s/^\s+|\s+$//g;
my $fd;
if (!open($fd, "-|", $cmd)) {
warn "Cannot start '$cmd': $!";
next;
}
else {
$tags{$fd} = $cmd;
$sel->add($fd);
}
}
while ($sel->handles > 0) {
my @handles = $sel->can_read($SELECT_TIMEOUT);
# maybe something went wrong
if (!@handles) {
for my $fd ($sel->has_exception($SELECT_TIMEOUT)) {
$sel->remove($fd);
}
next;
}
my $now = strftime($TAG_TIMESTAMP_FORMAT, localtime(time()));
for my $fd (@handles) {
if (defined(my $line = <$fd>)) {
if ($TAG_SEPARATOR) {
$line = join($TAG_SEPARATOR, $now, $tags{$fd}, $line);
}
print $line;
}
else {
# EOF
$sel->remove($fd);
}
}
}
}
multiplex(<STDIN>);
关于bash - 后台作业的乱码输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16509345/
我是一名优秀的程序员,十分优秀!