bash - How to create an anonymous pipe between 2 child processes and know their pids (while not using files/named pipes)? -
please note questions edited after couple of comments received. wanted split goal smaller pieces make simpler (and perhaps expand knowledge on various fronts), seems went far simplicity :). so, here asking big question.
using bash, there way 1 can create anonymous pipe between 2 child processes , know pids?
the reason i'm asking when use classic pipeline, e.g.
cmd1 | cmd2 &
you lose ability send signals cmd1. in case actual commands running these
./my_web_server | ./my_log_parser &
my_web_server basic web server dump lot of logging information it's stdout my_log_parser log parser wrote reads through logging information receives my_web_server , selects values log (in reality stores whole log received it, additionally creates csv file values finds).
the issue having my_web_server never stops (it web server, don't want web server :)). after done, need stop myself. bash script when stop (the bash script), either via sigint or sigterm.
for this, traps way go. in essence create trap int , term , function call kill my_web_server, but... don't have pid , though know via ps, looking pretty solution :).
some of might say: "well, why don't kill my_log_parser , let my_web_server die on own sigpipe?". reason why don't want kill when kill process that's @ end of pipeline, output buffer of process before it, not flushed. ergo, lose stuff.
i've seen several solutions here , in other places suggested store pid of my_web_server in file. solution works. possible write pipeline fiddling filedescriptors bit. i, don't solution, because have generate files. don't idea of creating arbitrary files store 5-character pid :).
what ended doing this:
#!/bin/bash trap " " hup fifo="$( mktemp -u "$( basename "${0}" ).xxxxxx" )" mkfifo "${fifo}" <"${fifo}" ./my_log_parser & parser_pid="$!" >"${fifo}" ./my_web_server & server_pid="$!" rm "${fifo}" trap '2>/dev/null kill -term '"${server_pid}"'' int term while true; wait "${parser_pid}" && break done
this solves issue me not being able terminate my_web_server when script receives sigint or sigterm. seems more readable hackery fiddling file descriptors in order use file store my_web_server's pid, think good, because improves readability.
but still uses file (named pipe). though know uses file (named pipe) my_web_server , my_log_parser talk (which pretty reason) , file gets wiped disk shortly after it's created, it's still file :).
would of guys know of way task without using files (named pipes)?
from bash man
pages:
! expands process id of executed back- ground (asynchronous) command.
you not running background command, running process substitution read file descriptor 3.
the following works, i'm not sure if trying achieve:
sleep 120 & child_pid="$!" wait "${child_pid}" sleep 120
edit: comment was: i know can pretty silly 'while read i; blah blah; done < <( ./my_proxy_server )'-way, don't particularly fact when script using approach receives int or term, dies without telling ./my_proxy_server bugger off :)
so, seems problem stems fact not easy pid of proxy server. so, how using own named pipe, trap
command:
pipe='/tmp/mypipe' mkfifo "$pipe" ./my_proxy_server > "$pipe" & child_pid="$!" echo "child pid $child_pid" # tell proxy server bugger-off trap 'kill $child_pid' int term while read echo $reply # blah blah blah done < "$pipe" rm "$pipe"
you use kill %1
instead of using $child_pid
.
yae (yet edit):
ask how pids from:
./my_web_server | ./my_log_parser &
simples, sort of. test used sleep
, original.
sleep 400 | sleep 500 & jobs -l
gives:
[1]+ 8419 running sleep 400 8420 running | sleep 500 &
so question of extracting pids:
pid1=$(jobs -l|awk 'nr==1{print $2}') pid2=$(jobs -l|awk 'nr==2{print $1}')
i hate calling awk
twice here, else jumping through hoops.
Comments
Post a Comment