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

How can I automatically return to a bash prompt after printing the output from a function placed in the background?

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

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

After running the script, it immediately returns my invitation. After 10 seconds, it prints โ€œFinishโ€ and then displays a flashing cursor on a new line:

  $ Done
 โ–

the script no longer works, but I do not receive the invitation back until I press Return .

Is there a way to force a bash request to return after printing "Finish"?

Related question: Is there a way for the background task to inform the terminal about printing a new invitation? However, this question is asked by the requested program. The answer attached to it relates to a program that is sent to the background, but does not seem to work for a function that is sent to the background (as in the example I provided).

To clarify: I want to save the entire code snippet above (for example, as myscript.sh ), and then run it as the foreground of the script (for example, as bash myscript.sh ).

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

  • User runs script
  • Script sends the PBS job, starts the tail of the output file in the background, and calls fn &
  • The user gets a hint back, can start to do other things.
  • Job exit appears on user terminal when job starts
  • fn controls the queue and kills tail when the job ends.
  • Users complain that they do not return (i.e., press Enter ) after completion.

Here is a slightly 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 much easier for me if my users could just get the task from a separate file or manage tasks between the background and the background on their own, but they cannot. They cannot even follow the instructions in the script to press Enter to get the โ€œviewโ€ of the prompt back ... And I cannot open another โ€œwindowโ€ - they do not have a display server.

+7
bash shell background-process pbs torque
source share
3 answers

Compile below code for a.out file

 #include <sys/ioctl.h> #include <sys/stat.h> #include <fcntl.h> int main(int argc, char *argv[]) { /* char buf[] = "date\n"; */ char buf[] = "\n"; /* Data to write on terminal */ int i; int fd = open(argv[1], O_WRONLY); /* Open terminal */ /* printf("fd = %d\n", fd); */ for (i = 0; i < sizeof buf - 1; i++) /* Write data */ ioctl(fd, TIOCSTI, &buf[i]); close(fd); /* Close file descriptor */ return 0; } 

This program expects a path as a command line argument. The program will open the path and write a new line on this path.

If this path contains the file descriptor of the terminal being written with a bash script, this will cause bash to catch a new prompt.

Change the shell script

 fn(){ sleep 10 echo "Done" ./a.out /proc/$PPID/fd/0 } fn & 

This script will do some work (presented as sleeping here) and then call a utility written earlier with an argument as the parent's input terminal. The parent terminal will receive a new line and catch a new prompt that discards the wandering command at that prompt, if any.

/proc contains directories for all processes. The folder name matches the pid of the process. The Inbuild PPID contains the parent pid. Inside the pid directory there is a fd directory containing open threads. 0 for input, 1 for output and 2 for error. There may be more open threads depending on the process. Here we are interested in stream 0 .

+3
source share

What is the problem you are trying to solve?

This is currently a more or less cosmetic problem. You are still in the shell, and the invitation still exists. Just enter 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} 
+3
source share

similar to the decision of Henk Langeveld.

Find the pid of your script
wait for it to complete.
echo line
Request back
Sorry, you will get this empty string

 #!/bin/bash fn(){ sleep 1 echo "Done" } fn & PID=$! wait $PID echo -e '' 
0
source share

All Articles