代码之家  ›  专栏  ›  技术社区  ›  conradlee

使用>将多个并行进程的输出传输到一个文件是否安全?

  •  33
  • conradlee  · 技术社区  · 15 年前

    我正在从网络上抓取数据,我的抓取程序有几个并行运行的过程。

    我希望每个进程的输出结果都在同一个文件中。只要文本行保持完整,并且不相互混淆,那么行的顺序就不重要。在UNIX中,我可以使用>>操作符将每个进程的输出通过管道传输到同一个文件吗?

    9 回复  |  直到 12 年前
        1
  •  25
  •   Mark Byers    15 年前

    不,不能保证线路保持完好。它们可以混合在一起。

    根据我找到的Liori的答案进行搜索 this :

    不应将管道字节或更小字节的写入请求与在同一管道上进行写入的其他进程的数据交错。大于管道字节的写入可能在任意边界上与其他进程的写入交错,无论是否设置了文件状态标志的O_nonblock标志。

    因此,长度超过管道字节的线路不能保证完好无损。

        2
  •  10
  •   rainkinz    14 年前

    您可以做的一件有趣的事情是使用GNU并行: 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

        3
  •  6
  •   liori    15 年前

    一般来说,没有。

    在Linux上,这可能是可能的,只要满足两个条件:每行只写一个操作,并且行大小不超过管道大小(通常与页大小相同,通常为4096)。但是…我不指望,这种行为可能会改变。

    最好使用一些真正的日志记录机制,比如syslog。

        4
  •  3
  •   Neil    15 年前

    您将需要确保在单次写入操作中写入整行(因此,如果您使用某种形式的stdio,则需要将其设置为行缓冲,缓冲长度至少为您可以输出的最长行的长度)。因为shell使用o ou append进行>>重定向,所以所有写入操作随后都将自动附加到fil。没有你的进一步行动。

        5
  •  2
  •   Max E.    15 年前

    使用临时文件并将它们连接在一起。这是做你想做的事情的唯一安全的方法,这样做的性能损失(可能)可以忽略不计。如果性能确实存在问题,请尝试确保/tmp目录是基于RAM的文件系统,并将临时文件放在那里。这样,临时文件存储在RAM中而不是硬盘上,因此读/写它们几乎是即时的。

        6
  •  2
  •   Bolster    15 年前

    当然不是,我有一个日志管理脚本,我认为它可以工作,它可以工作,直到我将它移到一个低负载的生产服务器。今天不好…但基本上你最终会得到一些完全混淆的线条。

    如果我试图从多个源捕获,拥有多个文件的“书面跟踪”就简单多了(而且更容易调试),如果我需要一个全面的日志文件,根据时间戳连接(您使用的是时间戳,对吗?)或者像莱奥里说的,系统日志。

        7
  •  1
  •   Brian Agnew    15 年前

    简单地说,没有。 >> 不尊重多个流程。

        8
  •  0
  •   Duncan    15 年前

    除了使用临时文件之外,您还可以使用某种聚合过程,尽管您仍然需要确保您的写入是原子的。

    想象一下Apache2和管道日志(如果你有雄心壮志的话,可以在管道的另一端进行扩展)。这就是它所采用的方法,多个线程/进程共享一个日志记录进程。

        9
  •  0
  •   lemonsqueeze    12 年前

    如上所述,这是一个相当大的黑客,但工作得很好=)

    ( ping stackoverflow.com & ping stackexchange.com & ping fogcreek.com ) | cat
    

    与“>>”相同:

    ( ping stackoverflow.com & ping stackexchange.com & ping fogcreek.com ) >> log
    

    在执行最后一个时,保存一个进程:

    ( ping stackoverflow.com & ping stackexchange.com & exec ping fogcreek.com ) | cat
    
    推荐文章