[bash] Раздельныое перенаправление stdout и stderr в другие программы
И да, вы только что получили абсолютно правильный и (почти) бесполезный ответ :-P

уточняю вопрос: и как же это сделать?
Самому написать. Программа - 30 строк (от души).
30 строк - много для такой задачи, поэтому хочется в одну )
/usr/bin/time ls > >(cat > stdout) 2> >(cat > stderr)


задумался ли ты например о том, что привычный пайп (x | y) завершается тогда, когда оба процесса x и y завершились
[xoft ~]$ time (sleep 3) | (sleep 5)
real 0m5.002s
user 0m0.004s
sys 0m0.008s
[xoft ~]$ time (sleep 5) | (sleep 3)
real 0m5.002s
user 0m0.000s
sys 0m0.004s
а вот конструкция (x > >(y) 2> >(z заканчивается вместе с x и процессы y и z продолжают висеть в воздухе.
[xoft ~]$ time (sleep 3 > >(sleep 5) 2> >(sleep 4
real 0m3.003s
user 0m0.000s
sys 0m0.004s
и поверь мне это лишь десятая часть предстоящих тебе открытий

> и процессы y и z продолжают висеть в воздухе.
Конец файла не спасает?
---
Q8: А где это есть и круче?
A8: В VMS!

простого перенаправления.
Я не понял, где ты видишь грабли, если таковыми не считать
гениальное решение в виде комбинации асинхронного сигнала и
признака конца файла.
---
Q7: А что за suxx?
A7: unix.
ну хотя бы то, что ты не можешь контролировать коды возврата. в обычном то пайпе код левой части теряется, ну это еще как-то можно стерпеть, типа часто если левая часть сломалась то и правая сломается и это можно заметить. а тут так вообще тебе возвращается код "x"-а, а "y" и "z" еще вообще не доработали. напихаешь чего-нибудь в sort, а ему потом места не хватит в /tmp/ чтобы досортироваться, ты об этом даже не узнаешь.
Ну так, он ведь так всегда делает, точно то же будет и длявот такое отработает
простого перенаправления.
type A | sort > q
type q | more
а вот такое, насколько я понял, уже может и не отработать (т.к. управление первая строка уже вернет, но запись q до конца еще не выполнится)
type A > (sort > q)
type q | more
а вот конструкция (x > >(y) 2> >(z заканчивается вместе с x и процессы y и z продолжают висеть в воздухе.задумался, конечно, собственно поэтому вопрос про пайп и был.
только вот я ее позапускал, с первого раза такое не заметил,
с концами всё в порядке у меня, еще посмотрю.
Расскажи, чем твоё "напихаешь чего-нибудь в sort" отличается от этого?
Ты уверен, что ты не переоцениваешь возможностей обычного sh?
Надеюсь, ты понимаешь, как эти конструкции сделаны на (v)fork+pipe?
Расскажешь, как такое сделать в sh и получить все коды завершения?
---
A44: Ламеры в гамаке пусть в тапках трахаются --- это их проблемы.
Я в своём гамаке хочу полноценно трахаться на лыжах.
Если ты не понимаешь вопроса, может, не стоит лезть со своими гаданиями?
Расскажи, что происходит на конвейере "P | C" в случаях:
а) когда P завершается раньше C;
б) когда C завершается раньше P.
---
"Vyroba umelych lidi, slecno, je tovarni tajemstvi."
именно из-за этого в баше добавили pipefail и PIPESTATUS чтоб не городить велосипеды ради простой конструкции.
> чем твоё "напихаешь чего-нибудь в sort" отличается от этого
да нет я ничего не говорю

produce | sort > x
ну хоть на том спасибо

я всю жизнь буду помнить как была программа
set -e
generate
process
distribute
(если кто не знает, set -e означает прерывать работу скрипта по первому плохому коду возврата. то есть не смогли успешно сgenerate-ить - не process-им, не смогли успешно с-process-ить - не distribute-им). а потом мне не понравилось что process слишком много мусора в stout сыплет, и я дописал ему
process | grep -v bullshit
ну и дальше неделю разбирались почему периодически всем рассылаются недостроенные данные :-\ grep то полюбому успешно завершается

> как такое сделать в sh и получить все коды завершения
ну как как
[xoft ~]$ cat ./xxx.sh
#!/bin/bash
rm /tmp/xxx && mkfifo /tmp/xxx
rm /tmp/yyy && mkfifo /tmp/yyy
bash -c "$1" >/tmp/xxx &
PID1=$!
bash -c "$2" </tmp/xxx >/tmp/yyy &
PID2=$!
bash -c "$3" </tmp/yyy &
PID3=$!
wait $PID1
CODE1=$?
wait $PID2
CODE2=$?
wait $PID3
CODE3=$?
echo $CODE1 $CODE2 $CODE3
[xoft ~]$ ./xxx.sh "true" "false" "true"
0 1 0
[xoft ~]$ ./xxx.sh "false" "true" "true"
1 0 0
[xoft ~]$ ./xxx.sh "echo a" "tee /dev/stdout" "tee /dev/stdout"
a
a
a
a
0 0 0
=) нет я правда не знаю другого способа. хотя это конешно уныло

Расскажи, что происходит на конвейере "P | C" в случаяхесли верит druxa, то конвеер ждет, когда завершится и P, и C.
[xoft ~]$ time (sleep 3) | (sleep 5)
real 0m5.002s
[xoft ~]$ time (sleep 5) | (sleep 3)
real 0m5.002s
или приведенные druxa факты не верны?
[xoft ~]$ (perl -e '$SIG{PIPE} = sub {warn "sigpipe!\n"}; sleep 2; $|=1; print "a\n";') | (sleep 1)
sigpipe!
Ну да. Теперь, когда мы выяснили, что в простом конвейере для
получения кода завершения любого процесса, кроме последнего,
надо прилагать заметные усилия, объясни, где ты увидел какие-то
_особенные_ грабли?
D> привычный пайп (x | y) завершается тогда, когда оба процесса
D> x и y завершились
Задумывался ли ты над тем, что вот это твоё утверждение может
быть неверным?
---
Q6: Я слышал есть такой мужик, вроде Бармин зовут,
и он придумал что-то такое после чего XXX не сосет.
> если верит druxa, то конвеер ждет, когда завершится и P, и C.
А если не верить? Что происходит на самом деле?
---
"Vyroba umelych lidi, slecno, je tovarni tajemstvi."
Задумывался ли ты над тем, что вот это твоё утверждение может быть неверным?а может быть и верным:
(trap "" PIPE; sleep 5; ps a|grep echo|grep -v grep|wc -l >/dev/stderr; sleep 5; trap - PIPE;)|echo kuku
Твой пример ничего не доказывает.
Что происходит, когда в случае "A & B | C" процесс "A"
завершается раньше "B", игнорирующего SIGPIPE?
---
"Narrowness of experience leads to narrowness of imagination."
P.S. Я не просто так спросил, мне лень копаться в исходниках bash,
тем более, что меня это не волнует, а в исходники sh я заглянул.
Там, как и ожидалось, "waitpid(-1, status, flags)".
"A & B | C"ёма-народ! это отличается как от (A & B) | C, так и от A & (B | C)

низнаю, ушёл ботать синтаксис
если убивать основной процесс, то те, которые поглащают его вывод, остаются висеть.
фигово.
всетаки придется писать на питоне или сях, правда жутко неохота.


да это для логов надо было. уже на питоне написал?
ты точно уверен что тебе команды tee не хватает?
есть программа, которая валит логи в stdout и stderr
по некоторым причинам, задача переписывать ее так, чтобы она нормально писала логи в файл, представляется нерешаемой.
более того, хочется писать логи не в файл, а в syslog, при этом дописывая к stderr-у, что это ошибки.
tee тут вроде не спасает никак.
если убивать основной процесс, то те, которые поглащают его вывод, остаются висеть.а можешь вот это пояснить? почему им EOF может не приходить?
которой основной процесс не ждёт завершения _команды_.
Там тоже "тот же запах затхловатый," то есть используется,
наверное, тот же waitpid(-1, ... но сделано оно даже не
как конвейер, а как простое перенаправление. Соответственно,
команда считается завершённой при выходе основного процесса,
а "перенаправления" остаются работать.
---
"This user is BSD-compliant."
Всегда казалось, что ждет он последнего процесса в конвейере.
Имеется в виду, что в их хвалёном bash сделана ошибка, из-заХм, ты уверен, что именно это имел в виду? Почему для него это важно? Если стоит задача как-то обработать логи с stdout и stderr, не всё ли равно, что будет наблюдаться в окружающем шелле, если после смерти основного процесса обработчики логов словят EOF и сдохнут?
которой основной процесс не ждёт завершения _команды_.
Всегда казалось, что ждет он последнего процесса в конвейере.*facepalm*
весь тред о том, что A > >(B) не ждёт завершения В
весь тред о том, что A > >(B) не ждёт завершения Вв общем да, я об этом и написал.
у меня процесс может завершиться, не послав конец файла.
судя по всему, при SIGTERM-е такое имеет место быть.
при других сигналах видимо тоже
у меня процесс может завершиться, не послав конец файла.Чего-чего? А нормальные процессы при завершении во все открытые файловые дескрипторы пишут магическую величину "конец файла"? Я всегда думал, что после смерти процесса операционка за ним всё подчищает, так что читающий из пайпа процесс естественным образом получает EOF после смерти писателя и опустошения пайпа.
судя по всему, при SIGTERM-е такое имеет место быть.
Можно какой-нибудь пример, демонстрирующий обратное поведение?
EOF придет, если закрыты все дескрипторы пайпа.
Ты вот это прочитал?
K> P.S. Я не просто так спросил, мне лень копаться в исходниках bash,
K> тем более, что меня это не волнует, а в исходники sh я заглянул.
K> Там, как и ожидалось, "waitpid(-1, status, flags)".
---
"Vyroba umelych lidi, slecno, je tovarni tajemstvi."
Если дескриптор, из которого ты читаешь, закрыт, приходит EBADF,
а не просто EOF.
---
"Vyroba umelych lidi, slecno, je tovarni tajemstvi."
EOF придет, если закрыты все дескрипторы пайпа.И что? Пусть каждый из дескрипторов пайпа открыт в одном процессе. Пишущий процесс умирает, операционка закрывает соответствующий fd.
>> которой основной процесс не ждёт завершения _команды_.
> Хм, ты уверен, что именно это имел в виду?
Он мог иметь в виду что-то другое, но мы-то знаем?
> Почему для него это важно? Если стоит задача как-то обработать
> логи с stdout и stderr, не всё ли равно, что будет наблюдаться
> в окружающем шелле, если после смерти основного процесса
> обработчики логов словят EOF и сдохнут?
Я не знаю, в чём проблема. Если от результата этой странной
команды ничего не зависит, не вижу особых причин не использовать
эту погнутую фичу. Мало ли сколько гнусных хаков приходится делать?
Проблемы будут, если у тебя есть какие-то блокировки, барьеры и т.п.
---
"Утверждаю, что с научной точки зрения, главное в профессии вора,
как и в профессии святого, конечно, это вовремя скрыться."
logger.sh
#!/bin/bash
./test.sh 1> >(logger -it out ) 2> >(logger -it err)
test.sh
#!/bin/bash
seq 1 10
sleep 3
seq 10 20 > /dev/stderr
sleep 3
seq 20 30
для проверки выполняем:
./logger.sh & sleep 1; killall test.sh; sleep 1 ; ps -A|grep logger
для проверки выполняем:И что? test.sh живёт после этого ещё 5 секунд, как и оба logger'a. Не понимаю, что должен был продемонстрировать этот пример, ведь пишущий процесс не умирал.
./logger.sh & sleep 1; killall logger.sh; sleep 1 ; ps -A|grep logger
да, да, это опечатка, надо test.sh убивать
да, да, это опечатка, надо test.sh убиватьну тогда и logger'ы с какой-то небольшой задержкой дохнут
ну то есть, ты действительно прав, они со временем отваливается и в первый раз когда я тестил,
от того и не заметил, что все-таки какое-то время они висят
в общем уже то, что больше 5 секунд висит - меня не устраивает )
Планировщик процессов должен пустить логгер на процессор, тот должен дочитать оставшиеся в ядерном буфере данные из пайпа, осознать, что писатель умер (получив EOF) и завершить выполнение. Таким образом, задержка зависит от того, сколько процессорного времени планировщик отдаёт логгеру, и сколько тому времени требуется на обработку оставшихся в пайпе данных.
поскольку за 10 секунд он у меня не успевал отвалиться,
проц не был загружен
поскольку за 10 секунд он у меня не успевал отвалиться,Если логгер специально спит по 10 секунд между обработками порций данных, противоречия нет
или если спит по секунде, но в буфере остаётся 10 порций данных
не спит логгер ни разу )
$ ./logger.sh & sleep 1; killall test.sh; sleep 1 ; sleep 1; ps -A|grep logger
[1] 8655
./logger.sh: line 2: 8657 Terminated ./test.sh > >(logger -it out ) 2> >(logger -it err)
[1]+ Exit 143 ./logger.sh
$

тогда хз, буду думать, где косячу
OH SHI~
$ ./logger.sh & sleep 1; killall test.sh; sleep 1; sleep 1; ps -A|grep logger
[1] 8736
./logger.sh: line 2: 8738 Terminated ./test.sh > >(logger -it out ) 2> >(logger -it err)
[1]+ Exit 143 ./logger.sh
$ ./logger.sh & sleep 1; killall test.sh; sleep 1; ps -A|grep logger
[1] 8750
./logger.sh: line 2: 8751 Terminated ./test.sh > >(logger -it out ) 2> >(logger -it err)
[1]+ Exit 143 ./logger.sh
8752 pts/11 00:00:00 logger.sh
8753 pts/11 00:00:00 logger
8755 pts/11 00:00:00 logger.sh
8756 pts/11 00:00:00 logger
$
Уму нерастяжимо.
А почему у вас "ps A" состояние процесса не выводит?
Так же вообще ничего не видно!
---
"This user is BSD-compliant."
$ ./logger.sh & sleep 1; killall test.sh; sleep 1; ps auwx|grep logger
[1] 9088
./logger.sh: line 2: 9090 Terminated ./test.sh > >(logger -it out ) 2> >(logger -it err)
[1]+ Exit 143 ./logger.sh
9091 0.0 0.0 10592 560 pts/11 S 16:56 0:00 /bin/bash ./logger.sh
9092 0.0 0.0 5096 612 pts/11 S 16:56 0:00 logger -it out
9093 0.0 0.0 10592 560 pts/11 S 16:56 0:00 /bin/bash ./logger.sh
9094 0.0 0.0 5096 516 pts/11 S 16:56 0:00 logger -it err
$ ./logger.sh & sleep 1; killall test.sh; sleep 2; ps auwx|grep logger
[1] 9101
./logger.sh: line 2: 9103 Terminated ./test.sh > >(logger -it out ) 2> >(logger -it err)
[1]+ Exit 143 ./logger.sh
9113 0.0 0.0 5348 692 pts/11 R+ 16:56 0:00 grep --colour=auto logger
$
Хм, двух секунд стабильно хватает, чтобы логгеры подохли.

[xoft ~]$ (sleep 1 1> >(echo a) 2> >(echo b
a
[xoft ~]$
а "b" куда подевалось? O_o
ага, никаких "особенных" граблей

Потенциальный хинт:
другой хинт:
$ exec > >(grep foo)
$ echo foo
foo
$ echo bar
$ echo foo bar
foo bar
Оставить комментарий
SCIF32
Такое можно сделать?типа пайпа "|" только два одновременно
как слить в один поток я знаю, но это не интересно