0

This is probably a simple question but I haven't found the answer anywhere.

I want to start a program from a shell script, and then close it from the shell script a little later.

Once the program loads, the script hangs because the focus is now on the opened program.

How do I return the focus to the script?

3
  • It sounds like you want to return control to the script - rather than "focus" - if that's the case, then it should be a matter of placing the program in the shell's background. See for example How to start a GUI application from the terminal and return immediately? Commented Mar 10, 2019 at 1:07
  • @steeldriver Anything you want to add to my answer ? Commented Mar 10, 2019 at 5:28
  • For some reason, no matter how I try, putting the ampersand after the command does not free up the terminal for me. I've seen that explanation many times, but it's just not working. Thank you for the suggestion! Commented Mar 10, 2019 at 16:16

1 Answer 1

1

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .