0

I searched a bit on how to do this, but I cannot find a solution. I am using process substitution cause of necessity. I want to wait for all the processing to finish before proceeding.

How do I get the PID of my 'runner' FUNCTION below so I can wait for it?

Basically what it does is execute, then log the stdout, then log errors & errors to stdout. Works well except for the out of sequence responses.

"${@}" 1> >(2log) 2> >(2log2scr | tee >&2) 
pid=????                                      # <<< HERE
while [ -e /proc/"$pid" ]; do sleep 0.1; done # <<< HERE

I tried things like the following but does not work:

  1. pid=$(exec sh -c "${@}" 1> >(2log) 2> >(2log2scr | tee >&2) )

  2. this works partially - it breaks my EVAL:

>     runner success &
>     while [ -e /proc/$! ]; do sleep 0.1; done

OUTPUTS

started running

FAILURE: **** 4.4.19(1)-release ****
 finished running

EVAL IS:

Your help is appreciated.

The full script follows if you need it for testing:

#!/bin/bash
logfile='test.log'
logprep() {
    local in=$(cat)
    in=$(echo "$in" | perl -pe 's/\**//smig')   # for proc subst
    # Return prepped string
    echo -e "preped for logging: '$in'"
}   
2log() {
    local in=$(cat)
    if [ "$in" != '' ]; then 
        echo -e "$in" | logprep >>"$logfile"    # out to logfile
    fi
    return 0    
}
2log2scr() {
    local in=$(cat)
    # 2scr
    if [ "'$in'" != '' ]; then echo -e "$in"; fi

    # 2log
    if [ "$in" != '' ]; then 
        echo -e "$in" > >(logprep >>"$logfile") # out to logfile
    fi
    return 0
}
runner () {
    echo -e "started running\n"
    "${@}" 1> >(2log) 2> >(2log2scr | tee >&2)      # <<< RUNNER
    #while [ -e /proc/15435 ]; do sleep 0.1; done   # <<< HERE
    echo -e "finished running\n"
}
success() {
    eval 'version=$(echo "SUCCESS: **** ${BASH_VERSION} ****")'
    echo -e "$version"; return 0
}
failure() {
    eval 'version=$(echo "FAILURE: **** ${BASH_VERSION} ****")'
    echo -e "$version" 1>&2; return 64
}

runner success  # to test a successful command
runner failure  # to test a command that errs

echo "EVAL IS: $version"
3
  • 1
    The script should already wait for it to finish before moving to the next line unless it is being sent to the background somehow.
    – jesse_b
    Commented Jun 13, 2019 at 17:17
  • its out of sequence
    – conanDrum
    Commented Jun 13, 2019 at 17:19
  • It's hard to successfully get stdout and stderr output properly interleaved as you would see it in your terminal: stdout is buffered but stderr is not, I think. Commented Jun 13, 2019 at 18:35

2 Answers 2

1

The pid of a background process can be retrieved from the $! environment variable if it has been put into the background (via adding a & to the end of your command), i.e.

my-cmd &
echo $!

Another option you could explore is using $$ (pid of current shell) within the executed shell, e.g.

exec sh -c 'echo $$ > t.pid && sleep 10' &
echo $!  # <-- pid of spawned shell
pid=$(cat t.pid)  # <-- pid of execed process in shell

Something like this will give you the pid in a temporary file named t.pid

2
  • Hey jjj thanks for you nice comment. I tried your suggestion (my-cmd & echo $!) already but for some reason it breaks my EVAL. see my comment section on what I tried.
    – conanDrum
    Commented Jun 13, 2019 at 17:43
  • Glad you got it working - thanks for posting your final result
    – jjj
    Commented Jun 13, 2019 at 18:06
0

The only way I got this working without breaking my EVAL was this:

runner () {
    echo -e "started running\n"
    "${@}" 1> >(2log) 2> >(2log2scr | tee >&2) 
    while [ -e /proc/$! ]; do sleep 0.1; done
    echo -e "$pid finished running\n"
}

The difference here is that I am just plainly accessing $! without any prior requirements. All suggestions everywhere mention that $! is accessed if we call our routine like so:

my-cmd &
echo $!

It seems that this is not a requirement and that we can plainly access $! after any complex routine such as "${@}" 1> >(2log) 2> >(2log2scr | tee >&2) without using the '&' anywhere

1
  • I wonder if $! is the pid of the stderr process substitution. That seems like it would be the last background process created. Commented Jun 13, 2019 at 18:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .