2013-12-11 61 views
3

(問題修訂,現在我更多地瞭解所發生的情況)爲什麼我的bash腳本需要這麼長時間才能在後臺運行時響應kill?

我已經在後臺運行的腳本,定期做一些工作,然後睡30秒:

echo "background script PID: $$" 
trap 'echo "Exiting..."' INT EXIT 
while true; do 
    # check for stuff to do, do it 
    sleep 30 
done & 

如果我試圖通過killkill INT殺死此腳本,則需要30秒才能響應該信號。

下面我會回答這個問題,因爲我找到了一個很好的解釋網上。

我原來的,令人尷尬的聯合國研究問題

這個問題是一個bash腳本,其中包括以下陷阱:

trap 'echo "Exiting...">&2; kill $childPID 2>/dev/null; exit 0' \ 
SIGALRM SIGHUP SIGINT SIGKILL SIGPIPE SIGPROF SIGTERM \ 
SIGUSR1 SIGUSR2 SIGVTALRM SIGSTKFLT 

如果我在前臺運行腳本,並擊中 CTRL - C,它立即得到信號並退出 (在一秒內)。

如果我在後臺(&)運行相同的腳本,並且經由 killkill -INT殺死它,它獲取信號之前需要30秒。

這是爲什麼,我該如何解決?

+0

你可以顯示腳本嗎? – tristan

+0

好吧,我現在可以看到,還有一些額外的因素,因爲我沒有得到一個微不足道的例子相同的行爲。我會花一些時間將其縮小到再現行爲的最小示例,並用更多細節更新我的問題。 – RashaMatt

回答

2

可能的原因:在進程處於休眠狀態時發出的信號直到進程被喚醒纔會被傳遞。當通過命令行啓動時,進程不會休眠,因此信號會立即傳送。

+1

延斯,你打敗了我,但我會在下面添加我的答案,因爲它有更多的細節;-) – RashaMatt

3

http://mywiki.wooledge.org/SignalTrap解釋 -

「當bash在前臺執行外部命令,它不能處理接收到的任何信號,直到前臺進程終止」 - 並且由於sleep是一個外部命令,bash所做在睡眠結束之前甚至不會看到信號。

該頁面具有信號處理在bash一個很好的概述,以及變通這個問題。簡單地說,處理這種情況一個正確的方法是將信號發送到進程而不只是父進程的:在我的再現

kill -INT -123 # will kill the process group with the ID 123 

團長引用的頁面更全面的解釋(沒有任何意義更多的在這裏)。

0

@RashaMatt,我無法得到格雷格的wiki所標榜的read命令工作。向腳本發送信號根本不會中斷讀取。我需要做的是:

#!/bin/bash 
bail() { 
     echo "exiting" 
     kill $readpid 
     rm -rf $TMPDIR 
     exit 0 
} 

sig2() { 
    echo "doing stuff" 
} 

echo Shell $$ started. 
trap sig2 SIGUSR2 
trap bail SIGUSR1 SIGHUP SIGINT SIGQUIT SIGTERM 
trap -p 

TMPDIR=$(mktemp -p /tmp -d .daemonXXXXXXX) 
chmod 700 $TMPDIR 
mkfifo $TMPDIR/fifo 
chmod 400 $TMPDIR/fifo 

while : ; do 
     read < $TMPDIR/fifo & readpid=$! 
     wait $readpid 
done 

...發送所需的信號從Shell $$ started線顯示shell的PID,並觀看了興奮。

wait在睡眠上更簡單,真實,但有些操作系統'沒有sleep infinity,我想看看Greg的read示例是如何工作的(它沒有)。

相關問題