Bash

Zenity 進度對話框的取消按鈕功能如何?

  • February 7, 2016

在嘗試使CancelZenity--progress視窗上的按鈕適用於我的腳本時,我意識到我根本不了解CancelZenity 手冊頁面上給出的範例中的按鈕是如何工作的: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沒有exitbreak或任何其他命令可見時按下按鈕時程序停止?

我認為 Zenity 只是一個顯示圖形界面並返回退出程式碼的程序,可用於啟動所需的實際命令(如exit取消等),但似乎 Zenity 必須做一些更複雜的事情,因為沒有似乎是範例中的命令在按下按鈕時實際停止的任何原因。

Zenity 是在做一些更複雜的事情,還是我誤解了什麼?我是 bash/sh 腳本的新手,所以看起來我可能誤解了。如果它只是 Zenity 獨有的複雜功能,則無需對其工作原理進行完整的技術描述;我想要的只是足夠的解釋,因此可以可靠地使用它。謝謝你。

(我還想問一下為什麼官方手冊中的這個例子實際上不起作用

$$ on Ubuntu 14.04 $$因為--error從來沒有顯示 Zenity 視窗,但我認為 StackExchange 不喜歡聯合問題,所以沒關係,除非它與我可能會誤解有關。) 相關文章: 使用 zenity 進度條終止腳本(不回答我的問題,因為--auto-kill在此範例中,當程序取消而不使用時,上面的答案說要使用--auto-kill

腳本中的()語法sh允許您啟動subshel ​​l 。您可以將 subshel​​l 視為以下兩行相同的行:

(echo foo)
sh -c "echo foo"

即,在您的 shell 腳本中有第二個程序處理(). 通過管道符號(“ |”),該子外殼的標準輸出連接到 zenity 的標準輸入。

當您在 zenity 視窗中點擊“取消”按鈕時,將導致 zenity 立即退出。此時,子shell 的標準輸出變為無效。這不會立即殺死子shell;但是,當該echo子外殼中的下一個命令要寫入標準輸出時,它將收到一個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而不是。

引用自:https://unix.stackexchange.com/questions/260609