【问题标题】:Tailing a binary file in Erlang adds mysterious bit-string在 Erlang 中拖尾二进制文件会添加神秘的位串
【发布时间】:2010-05-06 00:40:37
【问题描述】:

我想在命名管道上运行 tail 以促进一些二进制日志文件的处理。问题是神秘数据被添加到流的开头。我通过使用打开的端口 (open_port) 启动 erlang 进程来运行我的测试,然后我使用另一个 shell 将 bin 放入命名管道中。

这是一个从端口获取数据的简单函数:

bin_from_tail() ->
  open_port({spawn,"/usr/bin/tail -F named_pipe"},
                             [binary,in,eof]),
  receive
  {_,{data,<<Data/binary>>}} -> Data
  end.

所以这里有两种方法可以让我获取相同的数据...

  1. 创建命名管道

    mkfifo 命名管道

  2. 此命令会阻塞,直到您从另一个 shell 运行“cat log.bin > named_pipe”

    {ok,TailBin} = 文件:read_file(log.bin)。

  3. 使用erlang文件库将整个文件读入内存 FileBin = file:read_file(log.in)。

但是 TailBin 和 FileBin 是不一样的! TailBin 开头有一个神秘的 120 字节字符串:

<<40,6,161,69,172,216,56,14,100,0,80,6,0,0,0>>

【问题讨论】:

    标签: erlang named-pipes tail


    【解决方案1】:

    感谢关于无休止循环猫/重启死端口的想法。似乎命名管道只是缓冲了一点点,所以如果端口打开得足够快,编写器进程(另一个程序)就不会崩溃!绝对有风险的东西,但就黑客而言......它有效。

    因为刚才说的所有邮件列表帖子都这样做,没有示例就这样做,我将发布我的工作原理!如果有人想提供改进,请随时这样做。我的解决方案:

    read() ->
      Port = open_port({spawn,"/bin/cat /path/to/pipe"},
                       [binary,in,eof]),
      do_read(Port).
    
    do_read(Port) ->
      receive
        {Port,{data,<<Data/binary>>}} ->
          case do_something:with(Data) of
            ok ->
              io:format("G") % Good
            Any ->
              io:format("B") % Bad
          end;
        {Port,eof} ->
          read();
        Any ->
          io:format("No match fifo_client:do_read/1, ~p~n",[Any])
      end,
      do_read(Port).
    

    【讨论】:

    • 大!感谢分享。正如你所说 - 每个人都在谈论它,没有人分享示例代码。
    【解决方案2】:

    我发现在 erlang 之外也发生了同样的事情。问题是 tail 试图向您显示文件的 end,而不是整个文件。如果你在一个普通文件上使用它,任何写入的东西都是新的,并被 -f 拾取,但在这种情况下,tail 似乎正在等待直到结束文件(通过管道传递的 eof),然后显示最后 10 行(将二进制文件视为文本)。

    tail -F -c 9999999
    

    (假设您的日志为 9999999 字节或更少)可能会起作用。

    也许尝试使用 cat 而不是 tail -F,这似乎对我有用。然后你只需要避免 cat 在 eof 时退出的事实,我假设你试图通过使用 tail 来避免。

    那么,可能是一个无限循环 cat 的 shell 脚本吗?

    或者让 erlang 重新启动关闭并在端口死亡时重新创建端口,因为无论如何您都会收到 eof 信号。或者在进程退出时使用 exit_status 标志来向 open_port 发出信号,以防您需要区分 eof 和进程退出。 (如果你同时使用exit_status和eof,eof永远不会出现,用cat/null的简短测试表明)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-25
      • 2010-09-18
      • 2010-09-30
      相关资源
      最近更新 更多