jake9115
jake9115

Reputation: 4084

How to get a stdout message once a background process finishes?

I realize that there are several other questions on SE about notifications upon completion of background tasks, and how to queue up jobs to start after others end, and questions like these, but I am looking for a simpler answer to a simpler question.

I want to start a very simple background job, and get a simple stdout text notification of its completion.

For example:

cp My_Huge_File.txt New_directory &

...and when it done, my bash shell would display a message. This message could just be the completed job's PID, but if I could program unique messages per background process, that would be cool too, so I could have numerous background jobs running without confusion.

Thanks for any suggestions!

Upvotes: 3

Views: 5523

Answers (4)

Carl Norum
Carl Norum

Reputation: 224844

As I mentioned in my comment above, bash already does this kind of notification by default, as far as I know. Here's an example I just made:

$ sleep 5 &
[1] 25301
$ sleep 10 &
[2] 25305
$ sleep 3 &
[3] 25309
$ jobs
[1]   Done                    sleep 5
[2]-  Running                 sleep 10 &
[3]+  Running                 sleep 3 &
$ :
[3]+  Done                    sleep 3
$ :
[2]+  Done                    sleep 10
$ 

Upvotes: 0

xikkub
xikkub

Reputation: 1660

EDIT: user000001's answer separates commands with ;. I separated commands with && in my original example. The only difference I notice is that you don't have to surround your base command with braces if you use&&. Semicolons are a bit more flexible, so I've updated my examples.

The first thing that comes to mind is

{ sleep 2; echo "Sleep done"; } &

You can also suppress the accompanying stderr output from the above line:

{ { sleep 2; echo "Sleep done"; } & } 2>/dev/null

If you want to save your program output (stdout) to a log file for later viewing, you can use:

{ { sleep 2; echo "Sleep done"; } & } 2>/dev/null 1>myfile.log

Here's even a generic form you might use (You can even make an alias so that you can run it at any time without having to type so much!):

# dont hesitate to add semicolons for multiple commands
CMD="cp My_Huge_File.txt New_directory"
{ eval $CMD & } 2>/dev/null 1>myfile.log

You might also pipe stdout into another process using | in case you wish to process output in real time with other scripts or software. tee is also a helpful tool in case you wish to use multiple pipes. For reference, there are more examples of I/O redirection here.

Upvotes: 4

user000001
user000001

Reputation: 33307

You could use command grouping:

{ slow_program; echo ok; } &

or the wait command

slow_program &
wait
echo ok

Upvotes: 2

dtorgo
dtorgo

Reputation: 2116

The most reliable way is to simply have the output from the background process go to a temporary file and then consume the temporary file.

When you have a background process running it can be difficult to capture the output into something useful because multiple jobs will overwrite eachother

For example, if you have two processes which each print out a string with a number "this is my string1" "this is my string2" then it is possible for you to end up with output that looks like this:

"this is mthis is my string2y string1"

instead of:

this is my string1
this is my string2

By using temporary files you guarantee that the output will be correct.

Upvotes: 1

Related Questions