0

I'm trying to close a yad window from within bash script using kill command, but pids do allways mismatch. Same on command line.

$ yad & pid_01=$!
$ kill $pid_01
bash: kill: (31879) - Kein passender Prozess gefunden
$ echo $(pidof yad)
31880
$ echo $!
31879

No other yad processes running.

  1. What's going on here? Why is this pid allways wrong? (so the window fails to get closed)
  2. How can I find reliably the pid of a specific yad window when more than one yad process is running? Or is there another way to close this yad window from within a bash script? Since “kill $(pidof yad)” will probably randomly close another yad window.

I'm confused a little since I didn't notice before other programs to have this issue.

Any help appreciated.


GNU bash, Version 5.0.3(1)-release (i686-pc-linux-gnu) yad --version 0.40.0 (GTK+ 3.24.5)

MI605
  • 3
  • 2
  • I'm not familiar with yad, but if pids always mismatch, chance are yad created another process, e.g. bring up GUI, and then terminated itself. You may want to monitor the pid of yad after calling it. I wonder if pid would change at some point. Try this command `yad & for i in {1..100}; do pidof yad; done` – Taylor G. Apr 19 '21 at 05:08
  • Thanks, I tried the command. Here is the outcome: `$ yad & for i in {1..100}; do pidof yad; done [1] 22495 22497 22497 22497 22497 ... ` and so on, PID doesn't change anymore, but `$ echo $! 22495` does still report another PID, which is always not the yad PID from last run, but a PID which is never found. Seems you are right about assuming yad creating more than one process for a single window. But then how can I close this safely from within a script? (Note the first output line shows another PID, headed by [1].) – MI605 Apr 19 '21 at 10:58
  • You can get pid just before killing it, e.g. `kill $(pidof yad)`, rather than record pid after creating the process (which in your case pid is not immediately finalized after calling yad) – Taylor G. Apr 19 '21 at 16:25
  • If you have multiple yad windows opened and wish to kill only specific yad, you will need a way to distinguish them first, e.g. one is `yad --calendar` and another one is `yad --color`. Then use `ps x | grep 'yad --calendar'` will give you process detail of the calendar yad, from which you can extract pid and kill it specifically. – Taylor G. Apr 19 '21 at 16:25
  • Thank you very much, Taylor G., for setting me on the right trail. After analysing the output of ps it turned out yad is actually called by a helper script, so $! returns a pid not matching the yad-window recently opened. More details in my solution below. – MI605 Apr 20 '21 at 02:51

1 Answers1

0

1.) Simple answer: No, the pid itself is correct, but doesn't match the yad process running the window. There are two pids for yad always since yad obviously is called by some wrapper script rather than direcly when entering “yad” from command line or from within a script. This may be distro specific.

$ yad -- info & echo $!
29523

$ pidof yad
29524

$ ps x | grep 'yad' | grep -v 'grep'
29523 pts/0    S      0:00 /bin/bash /usr/local/bin/yad -- info
29524 pts/0    S      0:00 /usr/bin/yad -- info

Verification:

$ cat /usr/local/bin/yad
#!/bin/bash

/usr/bin/yad "$@" 2>/dev/null

so option -x will show both pids.

$ pidof -x yad
29524 29523

This doesn't help out when dealing with more than one instance of yad present (e.g. user calls script more than once); some identical pairs of yad processes are present in ps:

$ yad -- info
$ yad
$ yad -- info

$ ps x | grep 'yad' | grep -v 'grep'
22928 pts/0    S      0:00 /bin/bash /usr/local/bin/yad -- info
22929 pts/0    S      0:00 /usr/bin/yad -- info
23131 pts/0    S      0:00 /bin/bash /usr/local/bin/yad
23132 pts/0    S      0:00 /usr/bin/yad
24633 pts/0    S      0:00 /bin/bash /usr/local/bin/yad -- info
24634 pts/0    S      0:00 /usr/bin/yad -- info

2.) My solution to find reliably both pids of the specifc yad window, derived from the analysis above is:

# get yad pid of specific yad window
yad_pid_before="$(pidof -x yad) "
yad --info & \
sleep 1
yad_pid="$(pidof -x yad)"
if [ "$yad_pid_before" != " " ]; then
    while read -d' ' item
    do
        yad_pid="$(echo "$yad_pid" | sed "s/$item//g")"
    done <<<"$yad_pid_before"
fi

#testing
echo -e "yad recent window pids:\t$yad_pid\nsleeping 6s before closing."
sleep 6
kill $yad_pid

Problem description:

Yad is started using a wrapper script in at least some distros. So “kill $!” will fail. Alternative “ps x” doesn't provide sufficient information to distinguish between multiple yad windows called with identical options.

Explanation of solution:

The pids of all existing yad processes are stored in “$yad_pid_before”, immediately before new yad window is executed. The blank suffix character is intentionally and needed in order to find the last item in string. Option -x for getting script pids is mandatory.

The second (significant) pid is not immediately present, and will fail to get registered early, so “sleep 1” to wait for it.

Storing all yad pids present in “$yad_pid” after new yad window is started.

Removing any pid wich lives in “$yad_pid_before” from “yad_pid” while looping through list from here-string.

Loop is needed and to be executed merely when at least one item in “$yad_pid_before” exists, otherwise sed command will fail. Conditional branch takes care of this.

The resulting variable “$yad_pid” contains both recent pids and can now be used for kill command within script to close the specific yad window opened on second line. No other yad windows neither opened before or nor after are affected.

Works at least on bash and yad version specified in original question.

If somebody can provide a more elegant solution for this, please explain.

MI605
  • 3
  • 2