Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return to bash prompt after printing output from backgrounded function?

How can I return to my bash prompt automatically after printing output from a function that was put in the background?

For example, when I run the following script in a bash shell:

fn(){
        sleep 10
        echo "Done"
        exit
}
fn &

After running the script, it immediately returns my prompt. After 10 seconds, it prints "Done" and then displays a blinking cursor on a new line:

$ Done
▏

The script isn't running anymore, but I don't get my prompt back until I press Return.

Is there any way to force a return to the bash prompt after printing "Done"?

A related question is: Is there a way for a backgrounded task to inform the terminal to print a new prompt? However, that question asks about a backgrounded program. The answer supplied there applies to a program that is sent to the background, but doesn't seem to work for a function that is sent to the background (as in the example I supplied).

To clarify: I am looking to save the entire code snippet above (e.g., as myscript.sh) and then run it as a foreground script (e.g., as bash myscript.sh).

EDIT: The above is of course just a MWE. The context of this problem is:

  1. User runs script
  2. Script submits PBS job, starts tailing the output file in the background, and calls fn &
  3. User gets prompt back, may start doing other things.
  4. Job output appears on user's terminal when job starts running
  5. fn monitors the queue and kills tail when the job finishes.
  6. Users complain about not getting prompt back (i.e., having to press Enter) after this finishes.

Here's some less minimal code:

watch_queue(){
    until [  `qstat | grep $job | wc -l` -lt 1 ]; do
        sleep 2
    done
    kill -9 $pid
    tput setaf 7
    tput setab 0
    echo "Hit ENTER to return to your command prompt."
    tput sgr0
    exit 0
}

cmd="something complicated that is built at runtime"
outfile="ditto"
queue="selected at runtime, too"

job=`echo "cd \$PBS_O_WORKDIR  && $cmd >> $outfile " | 
     qsub -q $queue -e /dev/null -o /dev/null | 
     awk 'BEGIN { FS="." } { print $1 }'`

echo "Job $job queued on $queue: $cmd"
eval "tail -f -F $outfile 2>/dev/null &"
pid=$!
watch_queue &

Of course it would be a lot easier for me if my users could just pick up the job output from a separate file, or manipulate jobs between foreground and background on their own, but they can't. They can't even follow the instructions in the script to hit Enter to get the "look" of a prompt back... And I can't open another "window" - they do not have a display server.

like image 729
ff524 Avatar asked Apr 17 '14 05:04

ff524


People also ask

How do I run a command in the background in bash?

If you want to push a command into the background, using & at the end is an easy way to do that. This way, you can issue a command in the background and continue to use your terminal as it runs. It comes with a catch, though. Using & doesn't disconnect the command away from you; it just pushes it into the background.

How do I stop a background in bash script?

Assuming it's running in the background, under your user id: use ps to find the command's PID. Then use kill [PID] to stop it. If kill by itself doesn't do the job, do kill -9 [PID] .

How do I run a command in the background in Linux without output?

Use nohup if your background job takes a long time to finish or you just use SecureCRT or something like it login the server. Redirect the stdout and stderr to /dev/null to ignore the output. Just to add, sometimes there are arguments for the scripts then above command will return Ambiguous output redirect.


1 Answers

What is the problem you're trying to solve?

Right now, this is more or less a cosmetic problem. You're still in the shell, and the prompt is still there. Just type another command and it will be executed.

Alternatively, run the function in the foreground, or if you need to do something else in between, use wait:

$ fn & pid=$!
$ : something else
$ wait ${pid}
like image 184
Henk Langeveld Avatar answered Nov 15 '22 19:11

Henk Langeveld