在一些對安全性要求較高的情境下,ssh的逾時時間是管理員預先設定好的,在閑置一段時間後ssh串連會自動斷開。這種情況下如果通過ssh執行指令碼,而指令碼已耗用時間又比較長的話,會導致ssh用戶端和伺服器長時間無互動而逾時,命令執行失敗。
使用bash子進程可以解決這種問題,思路是由子進程執行具體的邏輯代碼,而由主進程來監控子進程的執行狀態,同時向控制台輸出字元來keep alive。
bash建立子進程有多重方式,這裡使用“()”,然後用“&”將其放在後台執行。雖然通過“job -p”可以擷取到後台進程的進程ID並使用“wait $PID”的方式能夠監控到子進程的返回狀態,如下面的代碼。但這種方式相當於阻塞了主進程,無法執行其他動作。
for pid in $(jobs -p); do wait $piddone
解決辦法是建立一個標誌檔案,並將子進程返回值儲存在另外一個臨時檔案中,主進程通過標誌檔案和返回值來擷取相關資訊,執行其餘邏輯。
簡化代碼如下,主進程在等待時會一直列印一個旋轉的進度標誌。
function doSomething(){ local retTmp=$(mktemp) local lock="/tmp/do.lock" touch $lock ( real script to do something echo $? > $retTmp rm -f $lock; )& while [ -f $lock ]; do sleep 0.1 printf "Please wait... %s \r" $f let "t=10#$(date +%N) / 100000000 % 4" case $t in 0) f="/";; 1) f="-";; 2) f="\\";; 3) f="|";; esac done echo local retcode=$(cat $retTmp) rm -f $retTmp return $retcode}
這種方式類似於通過fork函數實現相關邏輯,感覺上稍微有點笨重,不清楚bash是否有更簡便的方式來實現主子進程的資訊同步