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"
  • 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 Jun 13 at 17:17
  • its out of sequence – conanDrum Jun 13 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. – glenn jackman Jun 13 at 18:35
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

  • 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 Jun 13 at 17:43
  • Glad you got it working - thanks for posting your final result – jjj Jun 13 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

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.