Отдельный stdout приложения

Вопрос или проблема

У меня есть приложение, которое принимает несколько параметров командной строки, затем выводит некоторый текст в терминал, а затем начинает записывать данные в файл. У него есть параметр, который я могу использовать, чтобы определить имя файла, в который нужно записывать (например, -o some-file-name.bin).

Я хотел бы обрабатывать эти данные (в реальном времени) с помощью другого приложения, поэтому я попытался сделать так, чтобы программа выводила данные в stdout, указав -o -, и перенаправить вывод в другой инструмент. Однако, к сожалению, эта программа не умеет распознавать, что она записывает в stdout, и должна прекратить вывод текстовой информации в stdout (так как это нарушает бинарные данные).

Таким образом, обычно инструмент бы выводил текст в stdout (что меня не интересует) и данные в файл. Я хотел бы игнорировать весь текст, записываемый в stdout, и, вместо этого, чтобы он записывал данные в stdout, чтобы я мог перенаправить их в другой инструмент. Однако, когда я запускаю его с -o -, он записывает как (бинарные) данные, так и бесполезный текст в stdout, что портит данные.

Я пытался использовать -o >( my_other_tool ) вместо пайпа, но это привело к ошибке Couldn't open output: /dev/fd/63: /dev/fd/63: No such file or directory.

Существует ли другой способ – кроме перекомпиляции инструмента и удаления всех бесполезных вызовов printf – игнорировать оригинальный stdout и отправить данные, которые он записывал бы в файл, в stdout вместо этого?

ИЗМЕНЕНИЕ: Если это поможет, я говорю о nsntrace.

sudo bash -c 'nsntrace -o >(tshark -r-) uname'

У меня работает отлично.

Однако вы делали что-то вроде:

sudo nsntrace -o >(processor) cmd

Что не работает, потому что это расширяется в sudo nstrace -o /dev/fd/x cmd, где x – это дескриптор файла на стороне записи пайпа, из которого читает processor, но sudo закрывает все дескрипторы файлов выше 2, включая этот дескриптор x, который обычно будет выше 9 (см., например: sudo at -f <(echo “rm $file”) now + 2 hours yields at: /dev/fd/63: No such file or directory).

Тем не менее, если processor также необходим суперпользовательские привилегии, лучше не запускать его от имени root. То же самое касается cmd.

Один из вариантов – использовать возможность zsh изменять учетные данные пользователя:

sudo zsh -c 'nsntrace -o >(USERNAME=$SUDO_USER processor) -u $SUDO_USER cmd'

Это запустит nstrace от имени root, но processor и cmd от имени оригинального пользователя, который вызвал sudo, с восстановленными учетными данными от zsh и nsntrace соответственно.

Ответ или решение

Чтобы решить проблему с вывода данных в stdout приложения nsntrace, которое печатает ненужный текст в терминале, а затем записывает данные в файл, нужно использовать механизм, который позволит перенаправить стандартный вывод так, чтобы игнорировать текст, но получать бинарные данные. Вот несколько шагов и методов, которые можно применить:

  1. Проблема с выводом: Как вы уже заметили, использование -o - отправляет как текстовую, так и бинарную информацию в стандартный вывод, что вызывает проблемы при обработке данных.

  2. Использование process substitution: Ваша ошибка с -o >(my_other_tool) связана с тем, что sudo закрывает дескрипторы файлов выше 2, включая выходные дескрипторы, используемые для подстановки процессов. Это типичная проблема при работе с sudo.

  3. Решение с помощью zsh: Если вы используете оболочку zsh, вы можете использовать возможность изменения учетных данных пользователя. Это позволит вам выполнить nsntrace с повышенными привилегиями, а остальные команды (processor и cmd) как стандартному пользователю. Вот как это можно сделать:

    sudo zsh -c 'nsntrace -o >(USERNAME=$SUDO_USER my_other_tool) -u $SUDO_USER cmd'

    В этом случае nsntrace будет выполняться с правами суперпользователя, а my_other_tool и cmd будут выполняться от имени первоначального пользователя.

  4. Использование &> с дополнительной подстановкой: Если zsh не доступен, можно попробовать это в оболочке bash с использованием &>.

  5. stderr: Если приложение выводит текстовые сообщения в stderr, вы можете перенаправить stderr в /dev/null, но в этом случае бинарные данные все равно останутся в stdout.

    nsntrace -o - 2>/dev/null | my_other_tool

Этот подход не идеален, если приложение использует stdout для опубликованного бинарного вывода, но если все ваши сообщения об ошибках контролируются отдельно, это может помочь.

  1. Рассмотрите возможность обработки данных постфактум: Если никакой способ не решает проблему, возможно, лучше всего будет записать данные в файл и затем обработать файл с помощью вашего my_other_tool через другой этап выполнения, хотя это не будет в реальном времени.

Эти решения предоставляют гибкие способы обработки стандартного вывода приложения без необходимости замены кода исходного приложения nsntrace.

Оцените материал
Добавить комментарий

Капча загружается...