Bash – Get PID and return code from 1 line bash call

bashexit-statusprocesssubshell

Imagine we have a long command sleep 10 (for instance). We would like to execute it on another server using python (the ssh library paramiko to be specific).

I need a 1 line command that starts the command, prints the PID of the command, and then waits for it to finish and finally returns the exit status of the command.

What I've tried so far:

bash -c "echo $BASHPID ; exec sleep 10" ; echo $?

This prints the PID of the shell, then calls exec on the long command, and then waits and prints the exit status. The problem is $BASHPID prints the PID of the outer bash shell (possibly indicating calling bash -c cmd doesn't actually spawn a full new shell?).

If I call the above command in three lines, it works.

bash
echo $BASHPID ; exec sleep 10
echo $?

Any attempt using subshells hasn't worked for me either.

echo $(echo $BASHPID ; exec sleep 10) ; echo $?

This works, but the subshell pipes all of its output to echo, and echo prints it all at once, meaning the $BASHPID doesn't get print until after the sleep finishes. The PID must be print immediately.

Best Answer

When you run, for example:

bash -c "echo $BASHPID ; exec sleep 10"

or

echo $(echo $BASHPID ; exec sleep 10)

your current shell is interpolating the $BASHPID variable before the second bash (or subshell) sees it. The solution is to prevent the expansion of those variables by the current shell:

bash -c 'echo $BASHPID ; exec sleep 10'