shell 腳本是否等待在不同畫面中執行的命令?

shell 腳本是否等待在不同畫面中執行的命令?

我剛開始寫預定的 shell 腳本。目標是為 Minecraft 伺服器編寫一個簡單的備份腳本。伺服器以其自己的名稱運行螢幕

我假設我的腳本是否包含類似的內容

screen -S $(screen_name) -p 0 -X stuff "save-all^M"

伺服器命令將需要一些時間。我的問題是,腳本會立即繼續還是等到訪問畫面中的命令完成為止?如果它立即返回,我該如何等待(在這種情況下,該save-all命令保存當前世界。下一步是將文件複製到備份文件夾中,所以我顯然想等到世界正確保存) ?

答案1

不會screen -X stuff沒意識到它首先被要求運行一個命令,當該命令完成時更是如此——它所做的就是注入按鍵(這就是為什麼你必須^M手動添加)。一旦發送了假 tty 輸入,該命令就會返回並且您的腳本將繼續。

一般來說,作為終端模擬器,screen 不知道任何特定終端視窗中究竟發生了什麼事——沒有任何東西可以將 shell 提示字元(或任何其他互動式控制台提示字元)與常規輸出分隔開。

(這從根本上來說並不是不可能的——一些終端機模擬器允許 shell 輸出「輸出開始/結束」和「提示開始/結束」標記,例如VS程式碼將向 Bash 中註入特殊配置來實現這一目標 - 但它需要終端模擬器的支持與每個顯示輸入提示的程式合作,目前 Screen 和 Minecraft 都不會這樣做。

另一方面,您的腳本可能會更容易,因為它只處理單一程序,這意味著它只需要等待具體的出現提示,而不僅僅是一般的任何提示。您可以透過使用循環來查詢螢幕當前緩衝區「內容」來實現此目的-X hardcopy,並且如果該緩衝區的最後一行是不是Minecraft 提示尚未出現,請睡眠 1 秒並重複。

這與程式的工作原理類似expect:可以編寫一個 Expect 腳本來自動執行各種互動式輸入,但此類腳本的核心始終是一組 和expect "this"expect "that"即預先知道某些特定文本是“提示” ”並等待該文本。

[...]
expect "Password:" { send "$password\r" }
expect ">" { send "enable\r" }
expect "Password:" { send "$enablepwd\r" }
expect "#" { send "show run\r" }

其他 Minecraft 管理腳本的作用是什麼(例如這個項目,最近從 Screen 切換到 tmux)似乎是 1)立即盲目提交“save-all”和“stop”,2)等待伺服器處理 bot 命令,直到它自行退出。也就是說,而不是等待命令為了完成,他們等待結果該命令的。

同樣,如果您想等待節省要完成,您不需要等待“save-all”命令 - 您可以inotifywait等待,直到伺服器完成寫入特定檔案。正確執行此操作可能有些棘手(通常您需要使用“coproc”來啟動 inotifywait發出命令,這樣你就不會錯過該事件),但由於保存可能需要一段時間,所以大概之後就可以了。

echo "waiting..."
inotifywait -q -e close_write /path/to/game
echo "probably done!"

有些程式故意最後創建一個特定文件,以便其他工具可以等待它出現:

echo "waiting..."
until [ -e /path/to/marker_file ]; do sleep 1; done
echo "marker file showed up"

相關內容