LINUX.ORG.RU

Можно ли перенаправить стандартный поток одновременно в несколько приемников?

 , , , ,


2

2

Я читаю статьи про потоки в Linux, и не могу взять в толк: а имеется ли возможность перенаправить поток так, чтобы он попадал не в один приемник, а сразу в несколько? Например, направить какой-нибудь /dev/pts/15 в /dev/ttyS3 и одновременно в файл и одновременно в /dev/pts/32?

Все примеры в статьях крутятся вокруг того, что поток перенаправляется только в один приемник, и все.

Может быть есть какой-то специальный приемник, или стандартная утилита, через которые поток можно «разветвить»? Вроде как имеется утилита tee, но похоже, что она работает только через «|» (stdout левой в stdin правой команды), причем непонятно что она будет делать если у выполняемой команды перенаправлены потоки через «<» и «>».

Если что, вопрос возник вот в этом обсуждении: Xterm в Tk. Почему не каждый цветной терминальный вывод отображается через Popen+communicate? (комментарий)

★★★★★
Ответ на: комментарий от pfg

Процитирую сам себя:

Вроде как имеется утилита tee, но похоже, что она работает только через «|» (stdout левой в stdin правой команды), причем непонятно что она будет делать если у выполняемой команды перенаправлены потоки через «<» и «>».

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от pfg

Кстати, по ссылке кривой перевод. Вместо И написали ИЛИ:

tee - считывает данные из стандартного устройства ввода и записывает их на стандартное устройство вывода или в файл

Тем самым исказили смысл, закладываемый в работу утилиты, так что получилась белиберда.

Xintrea ★★★★★
() автор топика

В обычных оболочках такого нет. Но, тебе ничего не мешает написать программу/оболочку, которая будет запускать N процессов и дублировать данные каждому в stdin.

причем непонятно что она будет делать если у выполняемой команды перенаправлены потоки через «<» и «>».

Это я не понял.

urxvt ★★★★★
()
Ответ на: комментарий от Xintrea

нет. там все правильно.
можешь писать как в обычный файл так и в другой поток данных.
к примеру /dev/pts/0 /dev/ttyUSBx /proc/%pid%/fd/%number% или еще чего

pfg ★★★★★
()
Последнее исправление: pfg (всего исправлений: 2)
Ответ на: комментарий от Xintrea

а блин доперло что ты хотел сказать.
вощим, если поток ужо куда-то перенаправлен, то он пуст для последующих вычитываний. т.е.
ls -1 / > ./111 | tee ./222
запишет stdout в ./111 а tee увидит пустоту.

хотя можно было сделать и наобормот

pfg ★★★★★
()
Последнее исправление: pfg (всего исправлений: 1)

Вроде как имеется утилита tee, но похоже, что она работает только через «|» (stdout левой в stdin правой команды)

facepalm навылет

tee понятия не имеет, что за redirections происходят вокруг нее, tee работает со своим stdin. Если ты не удосужился почитать ман на свой шелл или чем ты там tee запускаешь, и подать ей на вход stderr, то виноват в этом, внезапно, не tee.

t184256 ★★★★★
()
Ответ на: комментарий от pfg

Перенаправление потока «с дублированием» через tee сработало, но появилась другая проблема:

Непонятно как получить код возврата приложения, которое запускается перед tee.

Ну то есть, tee - это перенаправлятор и копирователь потоков. Вспомогательный механизм как бы. Но так как это программа, то она «забивает» код возврата основной команды на свой.

Вот что происходит:

Без tee:
> ip abracadabra
Object "abracadabra" is unknown, try "ip help".
> echo $?
1

Через tee:
>ip abracadabra | tee /tmp/file.txt
Object "abracadabra" is unknown, try "ip help".
> echo $?
0

И как узнать код возврата основной команды?

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

И как узнать код возврата основной команды?

А какая команда тут, с Вашей точки зрения, основная?

А с точки зрения шелла?

PS По теме - запилить трубу и наливать куда захочешь

kindof
()
Последнее исправление: kindof (всего исправлений: 1)
Ответ на: комментарий от Xintrea

направить какой-нибудь /dev/pts/15 в /dev/ttyS3 и одновременно в файл и одновременно в /dev/pts/32

Для такого, я думаю, лучше socat использовать.

Непонятно как получить код возврата приложения, которое запускается перед tee.

Для bash:

ip abracadabra | tee /tmp/file.txt
echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"
1 0

DiMoN ★★★
()

cmd0 | tee >(cmd1 | grep aaa > cmd1.log) | tee >(cmd2) | tee file.log

Так ты можешь написать целое ветвистое из процессов

Ещё не забывай про cat <(cmd0) <(cmd1) ... чтобы объединять несколько выводов команд

bga_ ★★★★
()
Ответ на: комментарий от DiMoN

ip abracadabra | tee /tmp/file.txt
echo «${PIPESTATUS[0]} ${PIPESTATUS[1]}»
1 0

Хотел объеденить в одну команду, чтобы всегда возвращался код первой программы, но так не работает:

> ip abracadabra | tee /tmp/teeFile.txt | exit ${PIPESTATUS[0]}
Object "abracadabra" is unknown, try "ip help".
> echo $?
127
Почему?

Xintrea ★★★★★
() автор топика
Последнее исправление: Xintrea (всего исправлений: 1)
Ответ на: комментарий от Xintrea

ip abracadabra | tee /tmp/teeFile.txt | exit ${PIPESTATUS[0]}

Object «abracadabra» is unknown, try «ip help».

echo $?

127

В данном примере, в момент выполнения «exit ${PIPESTATUS[0]}» значение переменной не определено (тут перед «ip abracadabra» нет выполений с пайпом).

А так как «exit» - это встроенная команда в шелле, и её через пайп не вызвать - получается результат с кодом 127 - «файл не найден», так как такого бинарника нету.

DiMoN ★★★
()
Ответ на: комментарий от Xintrea

Если прям необходимо объединить в одну команду, почему бы не создать функцию?

Вот так, например:

#!/bin/bash -x

function my_func() {
    ip abracadabra | tee /tmp/teeFile.txt
    return ${PIPESTATUS[0]}
}

my_func
echo $?

DiMoN ★★★
()
Последнее исправление: DiMoN (всего исправлений: 1)
Ответ на: комментарий от DiMoN

В итоге, заработало вот так:

cmdLine="(%s) | tee %s ; echo ${PIPESTATUS[0]} | perl -e 'my $a=<STDIN>; exit($a)'" % (text, self.tty)

Да, через perl, но он в наших системах по-дефолту стоит.

Xintrea ★★★★★
() автор топика
Последнее исправление: Xintrea (всего исправлений: 1)
Ответ на: комментарий от Xintrea

Хех, долбаная нейросетка ChatGPT подсказала еще более короткое и правильное решение, которое не смогло дать все LOR-сообщество.

cmdLine="(%s) | tee %s ; (exit ${PIPESTATUS[0]})" % (text, self.tty)

Я в трансе.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от vel

Гм. Это что-то питонячее?

Ну да, потому что эта тема - это продолжение другой темы: Xterm в Tk. Почему не каждый цветной терминальный вывод отображается через Popen+communicate?

А ChatGpt ответчала на вопрос из второй темы (она тоже связанная): Как сгенерировать заданный код выхода (exit code) одной командой?

Xintrea ★★★★★
() автор топика