Хвост бинарного файла в Erlang добавляет таинственную битовую строку - PullRequest
1 голос
/ 28 апреля 2010

Я хочу запустить tail в именованном канале, чтобы облегчить некоторую обработку двоичного файла журнала. Проблема в том, что загадочные данные добавляются в начало потока. Я запускаю свои тесты, запуская процесс erlang с открытым портом (open_port), а затем использую другую оболочку для загрузки бина в именованный канал.

Вот простая функция для получения данных из порта:

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

Итак, у меня есть два способа получить одни и те же данные ...

  1. Создать именованную трубу

    mkfifo named_pipe

  2. Эта команда блокируется, пока вы не запустите "cat log.bin> named_pipe" из другой оболочки

    {ok, TailBin} = файл: файл чтения (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>>

Ответы [ 2 ]

2 голосов
/ 05 мая 2010

Спасибо за идею о бесконечно зацикливании кота / перезапуске мертвого порта. Похоже, что именованные каналы буферизуют немного, поэтому, если порт открывается достаточно быстро, процесс записи (другая программа) не завершится сбоем! Определенно рискованные вещи, но что касается хаков ... это работает.

Поскольку все сообщения в списке рассылки только что сказали, делайте это, делайте это без примеров, я собираюсь опубликовать, как работает мой! Если кто-то хочет предложить улучшения, пожалуйста, не стесняйтесь делать это. Мое решение:

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).
1 голос
/ 29 апреля 2010

Я обнаружил, что то же самое произошло за пределами Эрланга. Проблема в том, что tail пытается показать вам end файла, а не весь файл. Если вы используете его в обычном файле, все, что написано, будет новым и подхвачено -f , но в этом случае похоже, что tail ждет конца файла (eof, который идет через канал) и затем показывает последние 10 строк (рассматривая двоичный файл как текст).

tail -F -c 9999999

(при условии, что размер вашего журнала составляет 9999999 байт или меньше), вероятно, сработает.

Возможно, попробуйте использовать cat вместо tail -F , что, похоже, мне помогло. Тогда вам просто нужно избежать того факта, что cat выходит на eof, чего, я полагаю, вы пытались избежать, используя tail.

Итак, скрипт оболочки, который зацикливается cat бесконечно, может быть?

Или заставьте erlang перезапуститься близко и воссоздать порт, когда он умрет, так как вы все равно получаете сигнал eof. Или используйте флаг exit_status, чтобы open_port сигнализировал о выходе из процесса, если вам необходимо различить eof и выход из процесса. (Если вы используете и exit_status, и eof, eof никогда не приходит, краткий тест с cat </ dev / null </em> указывает)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...