Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

shell - How can I get both the process id and the exit code from a bash script?

I need a bash script that does the following:

  • Starts a background process with all output directed to a file
  • Writes the process's exit code to a file
  • Returns the process's pid (right away, not when process exits).
  • The script must exit

I can get the pid but not the exit code:

$ executable >>$log 2>&1 &
pid=`jobs -p`

Or, I can capture the exit code but not the pid:

$ executable >>$log;
# blocked on previous line until process exits
echo $0 >>$log;

How can I do all of these at the same time?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The pid is in $!, no need to run jobs. And the return status is returned by wait:

$executable >> $log 2>&1 &
pid=$!
wait $!
echo $?  # return status of $executable

EDIT 1

If I understand the additional requirement as stated in a comment, and you want the script to return immediately (without waiting for the command to finish), then it will not be possible to have the initial script write the exit status of the command. But it is easy enough to have an intermediary write the exit status as soon as the child finishes. Something like:

sh -c "$executable"' & echo pid=$! > pidfile; wait $!; echo $? > exit-status' &

should work.

EDIT 2

As pointed out in the comments, that solution has a race condition: the main script terminates before the pidfile is written. The OP solves this by doing a polling sleep loop, which is an abomination and I fear I will have trouble sleeping at night knowing that I may have motivated such a travesty. IMO, the correct thing to do is to wait until the child is done. Since that is unacceptable, here is a solution that blocks on a read until the pid file exists instead of doing the looping sleep:

{ sh -c "$executable > $log 2>&1 &"'
echo $! > pidfile
echo   # Alert parent that the pidfile has been written
wait $!
echo $? > exit-status
' & } | read

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...