As you can probably tell there are lots of ways to do this.
Regarding your "UPDATE #2" -- generally speaking, terminating any process in a parent-child hierarchy will generally terminate all the associated processes. But there are many exceptions to this. Ideally, you want to terminate the final 'child' in a process tree, then the parent(s) of this child should exit if they have no other tasks to run. But if you kill a parent, the signal should be relayed down to children when the parent dies and the children should exit as well -- but there are cases where the children processes may ignore the signal (via traps or similar mechanisms) and may continue to run an will be inherited by the 'init' process (or similar.) But this subject of process behavior can get complex and I'll just leave it there...
One method I like if I don't want to use a control script (described next) is to use the 'screen' utility to start and manage the process. The 'screen' command is full of features and can take some time to master. I'd encourage you to read the 'screen' man page for a full explanation. A quick example to start a process in the background would be the command:
screen -d -m /path/to/program
This will start "/path/to/program" inside of a 'screen' session.
You can see your running session with the command:
screen -ls
And at any time you can reconnect to your running program with the command:
screen -r
And then just terminate it with a ^C or whatever.
Besides the beauty of being able to reconnect and disconnect from your process at will is that 'screen' will capture any stdout() that your program might produce.
But my personal preference in these matters is to have a control program that manages the starting and stopping of a process. This can get somewhat complicated and requires some arguably complicated scripting. And like any script, there are dozens of good ways to do it. I've included a bash example of a method I routinely use to start and stop applications. If your task is simple you can insert it directly into the control script -- or you can have this control script call another external program. Note that this example is by no means comprehensive in terms of managing the process. I've left out the possibility of scenarios such as: Making sure the script isn't already running when you use the "start" option, validating that the running PID is actually the process you started (e.g. your script hasn't died and another process been started using the same PID), and validating that the script actually responded (exited) at the first 'kill' request. Doing all these checks can get complicated and I didn't want to make the example too long and complex. You might want to modify the example to practice your shell scripting.
Save the following code to a file called "programctl", make it executable with the command:
chmod 755 programctl
Then edit the file and add your code/script in the case-section that begins with "myscript".
Once everything is in place, assuming the "programctl" is in the current directory, you can start your program with:
./programctl start
And stop it with:
./programctl stop
Cheers.
#!/bin/bash
# Description: A wrapper script used to stop/start another script.
#--------------------------------------
# Define Global Environment Settings:
#--------------------------------------
# Name and location of a persistent PID file
PIDFILE="/tmp/tmpfile-$LOGNAME.txt"
#--------------------------------------
# Check command line option and run...
# Note that "myscript" should not
# provided by the user.
#--------------------------------------
case $1
in
myscript)
# This is where your script would go.
# If this is a routine 'bash' shell script, you can enter
# the script below as illustrated in the example.
# Or you could simply provide the path and parameters
# to another script such as /dir/name/command -options
# Example of an embedded script:
while true
do
# do something over and over...
sleep 1
done
# Example of an external script:
/usr/local/bin/longrun -x
;;
start)
# Start your script in the background.
# (Note that this is a recursive call to the wrapper
# itself that effectively runs your script located above.)
$0 myscript &
# Save the backgound job process number into a file.
jobs -p > $PIDFILE
# Disconnect the job from this shell.
# (Note that 'disown' command is only in the 'bash' shell.)
disown %1
# Print a message indicating the script has been started
echo "Script has been started..."
;;
stop)
# Read the process number into the variable called PID
read PID < $PIDFILE
# Remove the PIDFILE
rm -f $PIDFILE
# Send a 'terminate' signal to process
kill $PID
# Print a message indicating the script has been stopped
echo "Script has been stopped..."
;;
*)
# Print a "usage" message in case no arguments are supplied
echo "Usage: $0 start | stop"
;;
esac
-9
option fromkill
and using justkill
will take the mess out of it.-9
option would be total over-kill
here. :Pkill
it you prefix the pgid with a minus:kill -- -<pgid>
,kill -9 -<pgid>
, etc.