为何if语句会导致zenity的--auto-close参数立即关闭进度窗口?
为什么包含ping网络检查的if语句会导致带--auto-close的Zenity进度窗口立即关闭?
我为部署本地Docker容器的bash脚本制作了Debian包,添加了依赖检查和Zenity进度对话框来展示流程。但在加入网络检查的if语句后,带--auto-close参数的Zenity进度窗口会立即关闭。注释该if语句,进度窗口会正常在100%时关闭;保留if语句但移除--auto-close参数,流程也能正常执行。
示例代码:
#!/bin/bash condition=0 if [[ $condition ]]; then ( echo "0" # Check for internet if ping -c 3 -W 3 gcr.io; then echo "# Internet detected, starting updates..."; sleep 1 echo "10" else err_msg="# No internet detected. You may be missing some dependencies. Services may not function as expected until they are installed." echo $err_msg zenity --error --text="$err_msg" echo "100" exit 1 fi echo "15" echo "# Downloading a thing" ; sleep 1 echo "50" if zenity --question --text="Do you want to download a special thing?"; then echo "# Downloading special thing" ; sleep 1 else echo "# Not downloading special thing" ; sleep 1 fi echo "75" echo "# downloading big thing" ; sleep 3 echo "90" echo "# Downloading last thing" ; sleep 1 echo "100" ) | zenity --progress --title="Dependency Management" --text="downloading dependencies, please wait..." \ --percentage=0 --auto-close fi
问题根源
问题出在ping命令的默认输出会溜进Zenity的输入管道,打乱了它的解析逻辑:
- 当你执行
if ping ...; then时,ping的标准输出(比如那些ICMP响应的详情行)会直接进入子shell的stdout,也就是连到Zenity的管道里。 - Zenity进度窗口只认两种输入:纯数字(用来设置进度百分比)或者
#开头的文本(用来更新状态提示)。ping输出的内容既不是数字也不是#开头,属于无效输入。 - 一旦Zenity碰到无效输入,就会提前停止处理输入流。这时候
--auto-close参数检测到输入流已经结束,就直接把窗口关了,哪怕还没收到100的进度指令。
注释掉这个if语句后,没了ping的无效输出,Zenity就能正常解析所有进度指令,等收到100才关闭;要是去掉--auto-close,Zenity不会因为输入流结束自动关窗,得等用户手动关,所以流程看起来没问题。
修复方案
将ping的标准输出和标准错误都重定向到/dev/null,避免干扰Zenity的输入:
if ping -c 3 -W 3 gcr.io >/dev/null 2>&1; then
内容的提问来源于stack exchange,提问作者Jordy Mendoza
相关产品推荐
相关产品推荐

