
我正在嘗試自動執行透過 SSH 連接到遠端伺服器來執行的幾個常見任務。為此,我在幾個已儲存的會話中使用 PuTTY 及其「遠端命令」選項(連接 > SSH)。我的遠端命令如下所示:
~/scripts/test; $SHELL -l
每個已儲存的會話執行的腳本都不同,並執行不同的任務。$SHELL -l
腳本執行完畢後,保持 PuTTY 會話處於活動狀態。
所有這一切對於我正在運行的大多數腳本來說都非常有效。但是,我有一個使用 while 迴圈來執行一系列命令,直到用 Ctrl+C 終止為止。腳本啟動正常,但 PuTTY shell 在終止後不會保持活動。$SHELL -l
似乎沒有被執行。
具有此行為的範例腳本如下:
while true; do
echo "."
sleep 2
done
以下工作正常手動執行,我看到第二個命令的預期輸出:
~/scripts/test; echo "done"
但是,PuTTY“遠端命令”的第二個命令不執行。事實上,如果我更改遠端命令以包含echo
,它就不會顯示。
~/scripts/test; echo "done"; $SHELL -l
所以我想我的問題是:為什麼清單中的第二個命令不是由遠端命令執行,而是在手動執行時執行?更重要的是,我能做些什麼呢?
如果相關的話,我正在 Ubuntu 14.04 上運行 PuTTY。
答案1
當您運行putty
或ssh
(我認為在這種情況下沒有任何區別)在遠端系統上運行命令時,遠端 ssh 伺服器會將該命令作為 shell 命令運行:
/bin/bash -c '~/scripts/test; $SHELL -l'
因此,您bash
在遠端系統上有一個執行此管道的實例。您還有另一個bash
實例,由第一個實例啟動,執行此「測試」腳本。
當您鍵入 Control-C 時,請將該putty
字元傳送到遠端系統,並由您的 TTY 將其解釋為中斷字元。這會導致向附加到 TTY 的進程發送 SIGINT(中斷訊號)。這會中斷這兩個 shell 進程,導致它們都退出。您希望父 shell 實例忽略 SIGINT。
忽略 SIGINT 的 bash 指令是:
trap "" INT
因此,要停用管道的 SIGINT,您可以將原始命令變更為:
trap '' INT; ~/scripts/test; $SHELL -l
但這也會停用子程序的 SIGINT,這將使「測試」腳本不受 Ctrl-C 的影響。因此,您需要為測試腳本重新啟用 SIGINT。其命令為:
trap INT
您可以將該行新增至測試腳本本身,也可以將其新增至管道:
trap '' INT; ( trap INT; ~/scripts/test ); $SHELL -l
現在,當您按下 Ctrl-C 時,您應該中斷「測試」進程,而不是正在執行命令管道的父進程。
您可以在不使用 putty 或 ssh 的情況下對此進行測試。只需執行這些命令並嘗試在「睡眠」執行時按 Ctrl-C:
bash -c 'sleep 15; echo foo' # Ctrl-C kills sleep; doesn't print "foo"
bash -c 'trap "" INT ; sleep 15; echo foo' # Ctrl-C has no effect
bash -c 'trap "" INT; ( trap INT; sleep 15 ); echo foo' # Kills sleep, prints "foo"
答案2
putty 遠端命令的 ctrl+c 實際上會中斷 ssh 會話,因此應該預期它不會執行剩餘的遠端命令。如果您的目標只是讓會話繼續保持活動狀態,那麼您的無限循環就足夠了。