在尝试使Cancel
Zenity--progress
窗口上的按钮适用于我的脚本时,我意识到我根本不明白Cancel
Zenity 手册页面上给出的示例中的按钮是如何工作的:https://help.gnome.org/users/zenity/stable/progress.html.en
#!/bin/sh
(
echo "10" ; sleep 1
echo "# Updating mail logs" ; sleep 1
echo "20" ; sleep 1
echo "# Resetting cron jobs" ; sleep 1
echo "50" ; sleep 1
echo "This line will just be ignored" ; sleep 1
echo "75" ; sleep 1
echo "# Rebooting system" ; sleep 1
echo "100" ; sleep 1
) |
zenity --progress \
--title="Update System Logs" \
--text="Scanning mail logs..." \
--percentage=0
if [ "$?" = -1 ] ; then
zenity --error \
--text="Update canceled."
fi
Cancel
当该脚本运行时,为什么在没有exit
或break
任何其他命令可见的情况下按下按钮时进程会停止?
我认为 Zenity 只是一个显示图形界面并返回退出代码的程序,可用于启动所需的实际命令(例如exit
取消等),但看起来 Zenity 必须做一些更复杂的事情,因为没有似乎是示例中的命令在按下按钮时实际停止的任何原因。
Zenity 是否在做更复杂的事情,或者我误解了什么?我是 bash/sh 脚本编写的新手,所以看来我可能误解了。如果它只是 Zenity 独有的复杂功能,那么就没有必要对其工作原理进行完整的技术描述;我想要的是足够的解释,以便它可以可靠地使用。谢谢。
(我还想问为什么这个例子来自官方手册实际上不起作用[在 Ubuntu 14.04 上] 因为--error
从未显示过 Zenity 窗口,但我认为 StackExchange 不喜欢联合问题,所以没关系,除非它与我可能会产生误解有关。)
相关帖子:
使用 zenity 进度条终止脚本(没有回答我的问题,因为那里的最高答案说要使用,--auto-kill
在此示例中,进程被取消而不使用--auto-kill
答案1
()
脚本中的语法允许sh
您启动子外壳。您可以将子 shell 视为相同的以下两行:
(echo foo)
sh -c "echo foo"
即,您的 shell 脚本中有第二个进程,用于处理()
.通过管道符号(“ |
”),该子 shell 的标准输出连接到 zenity 的标准输入。
当您单击 zenity 窗口中的“取消”按钮时,将导致 zenity 立即退出。此时,子 shell 的标准输出将变得无效。这不会立即杀死子 shell;但是,当echo
该子 shell 中的下一个命令想要写入 stdout 时,它将收到一个SIGPIPE
信号,表明它尝试写入的管道没有读取器。进程的标准行为SIGPIPE
是终止。
您会注意到,如果您从终端启动脚本并单击“取消”按钮后更新已发送至 zenity,您的 shell 提示不会立即返回;由于 sleep 命令仍在运行,并且 sleep 不会产生输出,因此需要一段时间才能产生任何输出并SIGPIPE
发出 。
如果您不希望出现这种行为,那么您应该告诉 shell 在收到 SIGPIPE 后不要退出:
#!/bin/sh
(
trap -- '' PIPE
echo "10"; sleep 1
# ... etc, your normal script goes here
) |
zenity --progress ...
这个版本将忽略SIGPIPE
,并在 zenity 退出时愉快地继续。但请注意,在这种情况下,“取消”按钮会让用户感到非常困惑;它将导致 zenity 退出,但它会不是导致操作中止。直接通过可能会更好--no-cancel
。
答案2
取消时 zenity 发出 1 (echo $?)
#!/bin/sh
(
echo "10" ; sleep 1
echo "# Updating mail logs" ; sleep 1
echo "20" ; sleep 1
echo "# Resetting cron jobs" ; sleep 1
echo "50" ; sleep 1
echo "This line will just be ignored" ; sleep 1
echo "75" ; sleep 1
echo "# Rebooting system" ; sleep 1
echo "100" ; sleep 1
) |
zenity --progress \
--title="Update System Logs" \
--text="Scanning mail logs..." \
--percentage=0
if [ $? -eq 1 ] ; then
zenity --error \
--text="Update canceled."
fi