11

This is what I need to happen:

  1. start process A in the background
  2. wait for x seconds
  3. start process B in the foreground

How can I make the wait happen?

I'm seeing that 'sleep' seems to halt everything and I don't actually want to 'wait' for process A to finish entirely. I've seen some time based loops but I'm wondering if there's something cleaner.

  • 4
    I suggest that you enhance this question by providing a simple example of what you've already tried. – Andy Dalton Dec 1 '17 at 15:25
  • 10
    Where do you get the impression that sleep halts process-A? Can you show the test process you're using, or output indicative of this? If process-A is halting, it's more likely that it's trying to read from the terminal while running in the background and getting halted for that reason, rather than anything related to sleep. – Charles Duffy Dec 1 '17 at 16:35
  • 3
    ...if that is the case, process_a </dev/null & will attach its stdin to /dev/null rather than the TTY, and that may be sufficient to avoid the problem. – Charles Duffy Dec 1 '17 at 16:38
  • From my experience sleep will only block the current process and thus not the process previously started in the background with & – MADforFUNandHappy Dec 1 '17 at 18:03
28

Unless I'm misunderstanding your question, it can simply be achieved with this short script:

#!/bin/bash

process_a &
sleep x
process_b

(and add an extra wait at the end if you want your script to wait for process_a to finish before exiting).

You can even do this as an one-liner, without the need for a script (as suggested by @BaardKopperud):

process_a & sleep x ; process_b
  • 6
    Note that you don't need bash for that, any shell will do including your system's sh, so you don't need to add a dependency on bash for your script. – Stéphane Chazelas Dec 1 '17 at 18:21
  • 4
    Or simply: process_a & sleep x ; process_b – Baard Kopperud Dec 2 '17 at 8:56
9

You can use the background control operator (&) to run a process in the background and the sleep command to wait before running a second process, i.e.:

#!/usr/bin/env bash
# script.sh

command1 &
sleep x
command2

Here is an example of two commands that print out some time-stamped messages:

#!/usr/bin/env bash

# Execute a process in the background
echo "$(date) - Running first process in the background..."
for i in {1..1000}; do
    echo "$(date) - I am running in the background";
    sleep 1;
done &> background-process-output.txt &

# Wait for 5 seconds
echo "$(date) - Sleeping..."
sleep 5 

# Execute a second process in the foreground
echo "$(date) - Running second process in the foreground..."
for i in {1..1000}; do
    echo "$(date) - I am running in the foreground";
    sleep 1;
done

Run it to verify that it exhibits the desired behavior:

user@host:~$ bash script.sh

Fri Dec  1 13:41:10 CST 2017 - Running first process in the background...
Fri Dec  1 13:41:10 CST 2017 - Sleeping...
Fri Dec  1 13:41:15 CST 2017 - Running second process in the foreground...
Fri Dec  1 13:41:15 CST 2017 - I am running in the foreground
Fri Dec  1 13:41:16 CST 2017 - I am running in the foreground
Fri Dec  1 13:41:17 CST 2017 - I am running in the foreground
Fri Dec  1 13:41:18 CST 2017 - I am running in the foreground
Fri Dec  1 13:41:19 CST 2017 - I am running in the foreground
Fri Dec  1 13:41:20 CST 2017 - I am running in the foreground
...
...
...
  • 2
    The question asks to "start process B in the foreground". – Sparhawk Dec 2 '17 at 1:34
  • 1
    @Sparhawk Wow. Totally misread that - no explanation. Thanks for the heads-up - code corrected. Serious nostalgia from your username, btw. – igal Dec 2 '17 at 1:45
  • 1
    No worries! (Also the username was originally a reference to this chap, but I only later realised it was an Eddings character! And makes me want to re-read those books…) – Sparhawk Dec 2 '17 at 1:47
5

I like @dr01's answer but he doesn't check the exit code and so you don't know if you were successful or not.

Here's a solution that checks the exitcodes.

#!/bin/bash

# run processes
process_a &
PID1=$!
sleep x
process_b &
PID2=$!
exitcode=0

# check the exitcode for process A
wait $PID1    
if (($? != 0)); then
    echo "ERROR: process_a exited with non-zero exitcode" >&2
    exitcode=$((exitcode+1))
fi

# check the exitcode for process B
wait $PID2
if (($? != 0)); then
    echo "ERROR: process_b exited with non-zero exitcode" >&2
    exitcode=$((exitcode+1))
fi
exit ${exitcode}

usually i store the PIDs in a bash array and then the pid checking is a for loop.

  • 2
    You may want to reflect those exit codes in the exit status of your script like A & sleep x; B; ret=$?; wait "$!" || exit "$ret" – Stéphane Chazelas Dec 1 '17 at 19:32
  • 1
    @StéphaneChazelas good idea. i updated the code to make sure a non-zero exitcode is returned if one or both fail. – Trevor Boyd Smith Dec 1 '17 at 20:52
  • The OP wants process_b running in the foreground. Presumably process_a could exit while process_b is running, but you can still wait for it and get the exit status after you've collected the exit status of the foreground process_b the normal way, with $? directly. – Peter Cordes Dec 2 '17 at 6:37

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.