I want to start a program from a shell script, and then close it from the shell script a little later.
Scripts by nature are sequential, and any command executed in the script that is not built in, requires creating separate process and wait for that process to return control to the script. There's a few other intricate details, but that's the basic gist of how shell scripts work.
Now, what you're asking is to have a script start a process and use the same script to close the process. That means the command has to be independent from the script - separate process - and know what is that process somehow. Without going too much into details of multiple ways of how this can be done, most practical way is to create a .pid
file for the command.
For instance, here's a script that could do something like this:
#!/bin/sh
pid_file_exists()[ -f "$1" ]
pid_file='/tmp/mycommand.pid'
# Check if file exists, which may mean the process exists
if pid_file_exists "$pid_file" ; then
pid=$(cat "$pid_file" )
# Replace script with kill command. This will prevent going
# further in the script.
rm "$pid_file"
exec kill $pid
fi
# Save script's PID
echo $$ > "$pid_file"
# Replace script process with zenity, PID now
# is saved and we know it belongs to this command, not script
exec zenity --info "THIS IS A TEST"
If you start the script in one terminal tab you will see the popup created by zenity
utility. If you run the script in another tab - it will kill that popup. Now you will notice that the script retains control of the terminal in first tab. That's simply how the shell processes work. So in case you want to do that from the same terminal you might want to use either nohup
or setsid
command to detach the script when starting the desired app. For example, to start use
# &>/dev/null hides all output
setsid ./controller_script.sh &>/dev/null
and to close you can just do
./controller_script.sh
Note also that assumption here is that you want to control the app via script only. If the app that you want to control has exited already (closed by GUI button or by another process), you'll get an error but that's it - no harm done from the error. Now,if that PID is owned by another process already - that could be a problem, so if you're going to implement something truly portable you might also add checks for whether the process really belongs to the app you intended, for example via checking /proc/$pid/cmdline
file.