我正在从网上抓取数据,并且我有几个并行运行刮刀的过程。
我希望每个进程的输出最终都在同一个文件中。只要文本行保持完整并且不会相互混淆,行的顺序无关紧要。在UNIX中,我可以使用>>将每个进程的输出通过管道传输到同一个文件中吗?操作
答案 0 :(得分:27)
没有。不能保证线条保持完整。它们可以混合在一起。
根据liori的回答,我发现this:
{PIPE_BUF}字节或更少字节的写请求不应与来自在同一管道上执行写操作的其他进程的数据交错。大于{PIPE_BUF}字节的写入可能在任意边界上交错数据,而其他进程的写入也是如此,无论文件状态标志的O_NONBLOCK标志是否已设置。
因此,不能保证长于{PIPE_BUF}字节的行保持不变。
答案 1 :(得分:11)
你可以做的一件可能有趣的事情就是使用gnu parallel:http://www.gnu.org/s/parallel/例如,如果你要抓住这些网站:
stackoverflow.com, stackexchange.com, fogcreek.com
你可以做这样的事情
(echo stackoverflow.com; echo stackexchange.com; echo fogcreek.com) | parallel -k your_spider_script
并且输出是并行缓冲的,因为-k选项按照上面站点列表的顺序返回给你。一个真实的例子(基本上是从第二个并行截屏视频复制而来):
~ $ (echo stackoverflow.com; echo stackexchange.com; echo fogcreek.com) | parallel -k ping -c 1 {}
PING stackoverflow.com (64.34.119.12): 56 data bytes
--- stackoverflow.com ping statistics ---
1 packets transmitted, 0 packets received, 100.0% packet loss
PING stackexchange.com (64.34.119.12): 56 data bytes
--- stackexchange.com ping statistics ---
1 packets transmitted, 0 packets received, 100.0% packet loss
PING fogcreek.com (64.34.80.170): 56 data bytes
64 bytes from 64.34.80.170: icmp_seq=0 ttl=250 time=23.961 ms
--- fogcreek.com ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 23.961/23.961/23.961/0.000 ms
无论如何,ymmv
答案 2 :(得分:7)
一般来说,没有。
在Linux上,这可能是可能的,只要满足两个条件:每行写入一个操作,并且该行不长于PIPE_SIZE(通常与PAGE_SIZE相同,通常为4096)。但是......我不会指望那个;这种行为可能会改变。
最好使用某种真实的日志记录机制,比如syslog。
答案 3 :(得分:3)
您需要确保在单次写入操作中编写整行(因此,如果您使用某种形式的stdio,则需要将其设置为行缓冲至少最长的时间您可以输出的行。)由于shell使用O_APPEND作为>>然后重定向然后所有的写入将自动附加到文件中,而不需要您采取进一步操作。
答案 4 :(得分:2)
使用临时文件并将它们连接在一起。这是做你想做的事情的唯一安全方式,并且(可能)可以忽略不计的性能损失。如果性能确实存在问题,请尝试确保/ tmp目录是基于RAM的文件系统并将临时文件放在那里。这样,临时文件存储在RAM而不是硬盘驱动器上,因此读/写它们几乎是即时的。
答案 5 :(得分:2)
绝对不行,我有一个日志管理脚本,我认为这样做有效,并且它确实有效,直到我将它移动到一个负载不足的生产服务器。不是一个美好的一天...但基本上你有时会完全混淆线条。
如果我试图从多个来源捕获,那么使用多文件“纸质路径”会更简单(也更容易调试),如果我需要一个全面的日志文件,则根据时间戳连接(你正在使用时间戳,对吗?)或正如liori所说,系统日志。
答案 6 :(得分:1)
简单地说,没有。 >>
不尊重多个流程。
答案 7 :(得分:0)
除了使用临时文件的想法之外,你还可以使用某种聚合过程,尽管你仍然需要确保你的写入是原子的。
用管道式日志记录来思考Apache2(如果你感觉雄心勃勃,可以在管道的另一端传播)。这就是它采用的方法,多个线程/进程共享一个日志记录过程。
答案 8 :(得分:0)
如上所述,它非常糟糕,但效果很好=)
( ping stackoverflow.com & ping stackexchange.com & ping fogcreek.com ) | cat
与'>>'相同:
( ping stackoverflow.com & ping stackexchange.com & ping fogcreek.com ) >> log
并在最后一个exec上保存一个进程:
( ping stackoverflow.com & ping stackexchange.com & exec ping fogcreek.com ) | cat