Bash/xdotool: Commands work, but not in a script

2

2

I am making a bash script for Linux which closes the terminal window if the window loses focus.

On the command line, I was able to do this:

termwin=$(xdotool getactivewindow)

while : 
do 
  if [[ $(xdotool getactivewindow) != $termwin ]]
  then 
    exit 
  fi 
done

It works typed manually into a terminal, but, if I put it into a script, instead of closing the window when focus is lost, the script simply stops. No error or anything, just back to a prompt.

I feel like I'm missing something basic.

EDIT

After reading this...: See here

I tried running this as ". test.sh" rather than "./test.sh" and it worked. The link describes the difference in these methods as running the script as a subprocess or as part of the main process, respectively. Can anyone just explain this, and/or modify the script to run successfully with "./" instead of ". ", in the latter creates issues?

Fruckubus Crunt

Posted 2012-05-16T15:57:28.803

Reputation: 35

shell script debug is my fun, hold on, I shall try to reproduce. I know xdotool its an automate tool. – Rony – 2012-05-16T16:08:42.110

My idea is a bit off-topic: do you know about "exotic" window managers? E.g. awesome (http://awesome.naquadah.org/) - you can do this or similar functions easily.

– uzsolt – 2012-05-16T16:35:06.073

@uzsolt, you are to? if me, I am mainly on awesome wm quite some years and now and all. – Rony – 2012-05-16T16:40:31.243

Yes :) In awesome this is only about 3 lines :) In bash... – uzsolt – 2012-05-16T16:47:19.383

@uzsolt dear, awesome wm has lua, homebrew widgets are candies :), bashlets is another playground :) – Rony – 2012-05-16T16:57:24.530

Please see edit. – Fruckubus Crunt – 2012-05-16T18:02:23.080

Does ./test.sh && exit work for you? Just exit or exit 0 when the condition is met in the script, and exit will be run in the terminal afterwards. – Daniel Andersson – 2012-05-17T12:00:59.917

Oh bloody hell, that's exactly what I had to do. I was too absorbed in the script itself to consider running it like that. – Fruckubus Crunt – 2012-05-17T14:16:54.837

scripting is somehow like building pieces as according to nix philosophy. xdotool is so useful. btw, hug@uzolt – Rony – 2012-05-17T17:35:51.453

@uzsolt 2 lines now ;) cheers. – Rony – 2012-05-17T17:36:53.090

@Rony if you calculate the parts of while it will about five lines. In awesome: you call a signal function to unfocus, call c:kill(), type end and that's all. It's three lines. And you shouldn't run a plus bash script which eats your CPU :) So awesome is the winner ;) – uzsolt – 2012-05-17T17:45:13.393

Answers

1

When you source the file with ., the commands will run just as if you had entered them in the command line. Thus exit will exit your currently running shell.

To exit the shell from which the script was executed when forking, you need to get the process id of the parent process. You can try running

kill ${PPID}

in the script instead of exit to kill the parent shell (tip: try just echoing the pid first and check which process it corresponds to so you don't kill your WM or something).

If ${PPID} doesn't do it for you, you can also try sending the pid as a parameter to the script, but it depends on how and where it's called.


You said you used urxtvd/urxvtc. With that combination, this script kills the terminal from which it was started:

#!/bin/sh
echo kill in 3
sleep 3
kill -1 ${PPID}

so you should be able to use kill -1 in this way to kill a single urxvtc instance.

Note that if you run this by sourcing, then the urxvtd instance will be $PPID for the currently running terminal, and all terminals will die. You don't want that.

Daniel Andersson

Posted 2012-05-16T15:57:28.803

Reputation: 20 465

Dan, the kill PPID method looks good, but fails with my particular terminal. Im using urxvt in a client/daemon setup (urxvtd and urxvtc). It seems that each terminal in this case has the same ppid, and s =o this method doesn't work.

What is different is the pty, as found with the tty command. You can directly tell a pty to do something, right? Something like (not working) "exit >>/dev/pts/0" – Fruckubus Crunt – 2012-05-16T19:34:26.280

@FruckubusCrunt: Each terminal has the same PPID (parent pid), but when you launch a script from a terminal, inside the script the launching terminal's pid will be PPID, so it sends the signal to the correct pid. However, -1 seems to be needed with urxvtc. I'll update my answer. – Daniel Andersson – 2012-05-17T12:06:15.430

This is great Dan, thank you. A good learning experience for me. And I certainly could not accept a situation where more terminals would die, as that would defeat the purpose of what I'm doing. So thanks for the solid explanation. – Fruckubus Crunt – 2012-05-17T14:21:42.647

0

Hope the script will work as needed:

#!/bin/sh

termwin=$(xdotool getactivewindow)
while : ; do
    [ $(xdotool getwindowfocus) = $termwin ] || kill -9 $PPID
done

Rony

Posted 2012-05-16T15:57:28.803

Reputation: 180

This yields the sme results for me, it works if typed in manually, and fails – Fruckubus Crunt – 2012-05-16T17:32:23.290

I am now wondering if "exit" is the problem. Typed into a terminal, 'exit' closes the terminal, but is it possible that "exit" has a different meaning in a script, that stops the script rather than closing the terminal? Or is this even possible? – Fruckubus Crunt – 2012-05-16T17:48:17.777

Please see edit. – Fruckubus Crunt – 2012-05-16T18:02:16.263

Refrain from using kill -9. A single kill is enough, and much nicer. kill -9 does nothing nice. – Daniel Andersson – 2012-05-17T11:58:05.550

@DanielAndersson thank you very much for your refreshment and very useful link. I use the -9 because my kill does not kill. I shall look into the matter. – Rony – 2012-05-17T12:51:08.760