2014-03-25 33 views
7

我有while read line循環,即不執行我的清理功能幾個腳本時,我按下Ctrl C.例如:bash腳本沒有趕上SIGINT而在讀取循環

#!/bin/bash 

cleanup() { 
    stty echo 
    exit 0 
} 

trap cleanup SIGINT SIGHUP SIGTERM 

stty -echo 
while read -r line; do 
    echo "$line" 
done < /foo/bar 

cleanup 

當我按Ctrl- C,因爲stty -echo設置仍然有效,所以我的終端被搞亂了。我有許多其他腳本,我的清理功能完美無瑕。我似乎遇到問題的唯一時間是在腳本處於read循環中時按Ctrl-C。有沒有辦法確保當腳本在read循環中時按下Ctrl-C時cleanup函數會被調用?或者我在這裏錯過了一些明顯的東西?

更新:在我的腳本中還有其他事情正在進行。我運行了上面的確切腳本,並且我無法讓它以我其他腳本的方式失敗。我將不得不嘗試提煉出破損的腳本,以便我可以失敗,此時我會更新問題。

更新2:好的,我想通了。我從stty(我沒有看到,因爲我的真正的清理功能也清除屏幕)出現錯誤。錯誤是:stty: standard input: Inappropriate ioctl for device。我看起來很明顯是因爲撥打stty,而stdin從文件/foo/bar重定向。所以我改變了我的trap電話trap "break" SIGINT SIGHUP SIGTERM,它的工作。

+0

試試這個:https://stackoverflow.com/a/13058864/2591612 – Brian

+0

這是一個錯字。我的實際腳本使用'<'。抱歉。 –

+0

請將您的解決方案作爲答案發布,並儘可能地接受。 –

回答

4

原來,這個問題是由於這樣的事實,我cleanup功能打電話stty,並stty顯然不喜歡而stdin正在從一個文件重定向到被調用。因此,當我按Ctrl-C,而腳本執行read循環中,cleanup功能接到電話,就好像我已經從循環中調用它:

while read -r line; do 
    ... 
    cleanup 
    ... 
done < "$filename" 

這,反過來,意味着stty被執行死刑與重定向stdin,並與錯誤stty: standard input: Inappropriate ioctl for device死亡。

我能夠改變我的trap線,以解決這個問題:

trap "break" SIGINT SIGHUP SIGTERM 

因此,而不是讓它有效地插入到cleanup打電話到我的循環,當我按下Ctrl-C,它不是僅僅(有效)將break插入到循環中,從而跳出循環,然後在循環後通過該線路調用cleanup函數。