点击Zenity进度窗口取消后,如何终止Bash脚本中的Ghostscript进程?
解决Ghostscript与Zenity进度条配合时,取消窗口后GS进程仍运行的问题
当你用管道将gs与zenity --progress连接时,点击取消按钮后zenity会退出,但gs进程会继续在后台运行——这是因为管道中的两个进程相互独立,zenity退出仅会关闭管道的输出端,gs不会自动终止,仍会完成PDF压缩。要解决这个问题,需要在zenity被取消时主动终止对应的gs进程。
可行方案:跟踪GS进程PID并在取消时终止
通过记录gs的进程ID(PID),在检测到zenity因取消退出(退出码为1)时,调用kill命令终止该gs进程。示例代码如下:
# 启动GS进程并通过管道连接到Zenity,将整个作业放入后台 gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile="$DESTINO.pdf" "$FILE" | zenity --progress --title="Processando" --auto-close --width=220 --text="Comprimindo PDF" --pulsate --percentage=0 & # 通过父进程PID查找GS的进程ID GS_PID=$(pgrep -P $!) # 等待Zenity进程结束,获取其退出状态 wait $! ZENITY_EXIT_CODE=$? # 如果Zenity是被取消退出,终止GS进程并退出脚本 if [ "$ZENITY_EXIT_CODE" -eq 1 ]; then kill "$GS_PID" 2>/dev/null exit 1 fi
方案说明
- 后台运行管道作业:将
gs | zenity整体放到后台(&),便于后续获取作业关联的进程ID。 - 定位GS进程:用
pgrep -P $!查找父进程为当前后台作业PID的进程,精准定位到gs进程。 - 检测取消操作:
wait $!等待zenity结束,获取其退出码——zenity被取消时退出码为1,正常完成时为0。 - 主动终止GS:一旦检测到取消操作,立即调用
kill终止gs进程,避免其继续占用资源。
替代方案:使用Bash协同进程(coproc)
Bash的coproc可以更清晰地管理协同进程,直接获取gs的PID:
# 启动GS作为协同进程 coproc GS { gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile="$DESTINO.pdf" "$FILE" } # 将GS的输出导向Zenity进度条 zenity --progress --title="Processando" --auto-close --width=220 --text="Comprimindo PDF" --pulsate --percentage=0 <&"${GS[0]}" # 获取Zenity退出码 ZENITY_EXIT_CODE=$? # 取消时终止GS进程 if [ "$ZENITY_EXIT_CODE" -eq 1 ]; then kill "${GS_PID}" exit 1 fi
内容的提问来源于stack exchange,提问作者samueldelorenzi
相关产品推荐
相关产品推荐

