【问题标题】:Make script terminate when background zenity dialog is closed关闭后台zenity对话框时使脚本终止
【发布时间】:2018-07-20 12:55:14
【问题描述】:

我在这里编写了一个相当简单的脚本,旨在使用zenity 显示一个文本信息对话框,并不断地从远程 TCP 连接读取数据并将其显示在对话框中。这行得通...但是,如果我关闭zenity 对话框,我希望整个脚本终止。

有没有办法做到这一点?我认为我无法检查 while 循环中的任何内容,因为脚本可能会在从远程 TCP 连接读取数据时停止。

#!/bin/bash

on_exit() {
        zenity --display=:0 --error --text="Script has exited." &
}

# Options
while getopts "a:p:t:" OPTION; do case "$OPTION" in
        a) address="$OPTARG";;
        p) port="$OPTARG";;
        t) title="$OPTARG";;
esac; done

exec &> >(zenity --display=:0 --text-info --title=$title || exit)
                               # doesn't make a difference?  ↑
                               # also tried &&
trap "on_exit" EXIT

while read data < /dev/tcp/$address/$port; do
        echo $data
        # ...
        # do some other stuff with the information
        # ...
done

注意:这将在 IGEL Linux 上运行。我没有安装其他软件包的选项。所以,理想情况下,我正在寻找的解决方案是 Bash 原生的。


更新

我只需进行此修改即可继续使用exec。或者@BachLien 使用命名管道的回答也有效。

PID=$$
exec &> >(zenity --display=:0 --text-info --title=$title; kill $PID)

【问题讨论】:

  • 是否可以将 Zenity 执行放在一个等待其终止并随后杀死目标脚本的包装器中?
  • &gt;(...) 内部调用exit 意味着退出子shell。您需要 kill 父 PID 来终止父 shell。请考虑使用命名管道(我相信不需要安装任何额外的东西)以便于编码。

标签: bash zenity


【解决方案1】:

我没有安装zenity,所以我尝试了这个脚本来说明这个想法。

程序terminal+cat(模拟zenity)由后台运行的函数_dspMsg(子进程)执行; cat 连续显示来自命名管道文件 ($m) 的消息;当terminal+cat 退出时,父进程为killed。

与此同时,另一个cat 进程将消息写入管道$m(模拟TPC 信息源);当_dspMsg 退出时它会被杀死。

#!/bin/bash
                              # 1) named pipe
m=`mktemp -u /tmp/msg-XXXX=`  #    get a temporary filename (for named pipe)
mkfifo "$m"                   #    create that named pipe
trap "echo END; rm $m" EXIT   #    remove that file when exit
                              # 2) zenity
_dspMsg(){                    #    continuously display messages
  urxvt -e bash -c "cat <$m"  #    terminal+cat is used in place of zenity
  kill $1                     #    kill parent pid
}                             #    to be run in background
_dspMsg $$ &                  #    $$ = proccess id
                              # 3) TCP info feeds
cat >>"$m"                    #    feeding messages using cat
                              #    cat is used in placed of TCP data feed

注意:

  1. 命名管道用作父进程和子进程之间通信的一种方式。
  2. 要测试该脚本,您可能需要将 urxvt 更改为 xtermiTerm 或您计算机中可用的任何其他终端仿真器。

所以,也许这就是你所需要的(未经测试):

#!/bin/bash

while getopts "a:p:t:" OPTION; do case "$OPTION" in
  a) address="$OPTARG";;
  p) port="$OPTARG";;
  t) title="$OPTARG";;
esac; done

m=`mktemp -u /tmp/msg-XXXX=`
mkfifo "$m"
trap "zenity --display=:0 --error --text='Script has exited.' & rm $m" EXIT

_dspMsg(){
  zenity --display=:0 --text-info --title="$title" <"$m"
  kill $1
}

_dspMsg $$ &

while read data < /dev/tcp/$address/$port; do
  echo $data >>"$m"
done

【讨论】:

  • 这看起来很有希望! $$ 对我来说是新的。我不知道有这样一种方法可以获取 PID 当前脚本。不过我必须在星期一试一试。今天的时间到了。
【解决方案2】:

您可以将 while 循环的所有输出通过管道传输到 zenity,从而摆脱对 exec &amp;&gt; 的需求。

while read data < "/dev/tcp/$address/$port"; do
        echo "$data"
done | zenity --display=:0 --text-info --title="$title"

【讨论】:

  • 有额外的处理来代替我没有提到的 echo 语句。我应该有。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-02
  • 1970-01-01
  • 1970-01-01
  • 2018-04-30
  • 2012-08-22
  • 2018-02-20
相关资源
最近更新 更多