You can use the command wait PID
to wait for a process to end.
You can also retrieve the PID of the last command with $!
In your case, something like this would work:
command1 & #run command1 in background
PID=$! #catch the last PID, here from command1
command2 #run command2 while command1 is running in background
wait $PID #wait for command1, in background, to end
command3 #execute once command1 ended
Following your edit, as you have multiple PIDs and you know them, you can do that:
command1 & #run command1 in background
PID1=xxxxx
PID2=yyyyy
PID3=xxyyy
PID4=yyxxx
command2 #run command2 while command1 is running in background
wait $PID1 $PID2 $PID3 $PID4 #wait for the four processes of command1, in background, to end
command3 #execute once command1 ended
Hitting Enter the script ends the process remains in the background.
Almost! Actually, the script has already exited by the time you press Enter. However, that's how you can get your prompt back (because your shell prints its $PS1
all over again).
The reason why hitting Ctrl + C terminates both of them is because the two of them are linked. When you execute your script, your shell initiates a subshell in which to run it. When you terminate this subshell, your background process dies, probably from a SIGHUP
signal.
Separate the script, the background process and the subshell
Using nohup
, you might be able to get rid of this little inconvenience.
#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
nohup $cmd &
The disown
alternative
If you can switch from /bin/sh
to /bin/bash
, you can give a try to disown
as well. To know more, just type help disown
in a bash
instance.
disown -h $cmd &
Killing the background process "nicely"
Now, when it comes to killing your process, you can perfectly do a "Ctrl + C" using kill
. Just don't send a brutal SIGKILL
. Instead, you could use:
$ kill -2 [PID]
$ kill -15 [PID]
Which will send a nice SIGINT
(2) or SIGTERM
(15) to your process. You may also want to print the PID value after starting the process:
...
nohup $cmd &
echo $!
... or even better, make the script wait for a SIGINT
, and send it back to the background process (this will keep your script in the foreground though):
#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
nohup $cmd &
# Storing the background process' PID.
bg_pid=$!
# Trapping SIGINTs so we can send them back to $bg_pid.
trap "kill -2 $bg_pid" 2
# In the meantime, wait for $bg_pid to end.
wait $bg_pid
If a SIGINT
isn't enough, just use a SIGTERM
instead (15) :
trap "kill -15 $bg_pid" 2 15
This way, when your script receives a SIGINT
(Ctrl + C, kill -2
) or a SIGTERM
while wait
ing for the background process, it'll just relay the signals to it. If these signals do kill the sfk
instance, then the wait
call will return, therefore terminating your script as well :)
Best Answer
Well, the real question is what input you actually want to send to your SCRIPT. If you want it to have empty input, then run:
If you want to give it some particular input, like the contents of $size, then run:
If you want to type the input, then you will have to put it back in the forground to type your input, then put it into the background again. The ability to do that depends on whether your shell has job control (most do, but the original Bourne shell did not). Do do that:
fg %watcher
orfg %1
(using whatever job number you see after runningjobs -l
) to put the process into the foreground.stty -a
and check forsusp
to see what your stop character is).bg %1
(or whatever the number was).Yet another answer would be to have a named pipe. Here is an example (using
tr
in place of your script just to show):First you run the script taking it's input from the fifo (important to run the script first). Then
exec 6> ...
makes file descriptor 6 of the shell write to the fifo. Then, whenever you want to send output, write it to file descriptor 6 (via>&6
). Notice the final "HERE IS..." was not typed by me, it just was the output of tr.