Вопрос или проблема
У меня есть приложение, которое принимает несколько параметров командной строки, затем выводит некоторый текст в терминал, а затем начинает записывать данные в файл. У него есть параметр, который я могу использовать, чтобы определить имя файла, в который нужно записывать (например, -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
, которое печатает ненужный текст в терминале, а затем записывает данные в файл, нужно использовать механизм, который позволит перенаправить стандартный вывод так, чтобы игнорировать текст, но получать бинарные данные. Вот несколько шагов и методов, которые можно применить:
-
Проблема с выводом: Как вы уже заметили, использование
-o -
отправляет как текстовую, так и бинарную информацию в стандартный вывод, что вызывает проблемы при обработке данных. -
Использование
process substitution
: Ваша ошибка с-o >(my_other_tool)
связана с тем, чтоsudo
закрывает дескрипторы файлов выше 2, включая выходные дескрипторы, используемые для подстановки процессов. Это типичная проблема при работе сsudo
. -
Решение с помощью
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
будут выполняться от имени первоначального пользователя. -
Использование
&>
с дополнительной подстановкой: Еслиzsh
не доступен, можно попробовать это в оболочкеbash
с использованием&>
. -
stderr
: Если приложение выводит текстовые сообщения в stderr, вы можете перенаправить stderr в /dev/null, но в этом случае бинарные данные все равно останутся в stdout.nsntrace -o - 2>/dev/null | my_other_tool
Этот подход не идеален, если приложение использует stdout для опубликованного бинарного вывода, но если все ваши сообщения об ошибках контролируются отдельно, это может помочь.
- Рассмотрите возможность обработки данных постфактум: Если никакой способ не решает проблему, возможно, лучше всего будет записать данные в файл и затем обработать файл с помощью вашего
my_other_tool
через другой этап выполнения, хотя это не будет в реальном времени.
Эти решения предоставляют гибкие способы обработки стандартного вывода приложения без необходимости замены кода исходного приложения nsntrace
.