2016-11-15 19 views
4

如果管道流空閒一段時間,如何關閉程序?Bash:如果管道IO空閒,請關閉

例如說:

someprogram | closeidlepipe -t 500 | otherprogram

有一些程序closeidlepipe可以關閉,如果閒置一段(-t 500)?

timeout可以在一段時間後關閉,但不能與「空閒」區分。

UPDATE

需要注意的是someprogram輸出二進制數據的層出不窮是很重要的。數據可能包含空字符\0,應該逐字輸入。

+0

man 3 select;應該是一個小時的編碼。 – Joshua

回答

1

這是一個程序的核心的一般形式,這樣做。

while(1) { 
    struct timeval tv; 
    tv.m_sec = 0; 
    tv.m_usec = 500000; 
    int marker = 1; 
    select(1, &marker, NULL, NULL, &tv); 
    if (marker == 0) exit(1); 
    char buf[8192]; 
    int n = read(0, buf, 8192); 
    if (n < 0) exit(2); 
    char *b = buf; 
    while (n) 
    { 
     int l = write(1, b, n); 
     if (l <= 0) exit(3); 
     b += l; 
     n -= l; 
    } 
} 
+0

如果小於8192字節可用,在讀取時是否會阻止該塊? – Climax

+1

不是。 read()僅返回在這種情況下讀取多少內容。 – Joshua

+0

只有當文件描述符被設置爲非阻塞 – Climax

1

內置read有一個超時選項-t

someprogram | 
    while :; do 
    IFS= read -d'' -r -t 500 line 
    res=$? 
    if [[ $res -eq 0 ||)); then 
     # Normal read up to delimiter 
     printf '%s\0' "$line" 
    else 
     # Either read timed out without reading another null 
     # byte, or there was some other failure meaning we 
     # should break. In neither case did we read a trailing null byte 
     # that read discarded. 
     [[ -n $line ]] && printf '%s' "$line" 
     break 
    fi 
    done | 
    otherprogram 

如果read時間從500個秒鐘後,while循環將退出與管道的中間部分關閉。 someprogram將在下一次嘗試寫入該管道的末端時收到SIGCHLD信號,從而允許其退出。

+0

如果我不想逐行閱讀,而是儘可能多地閱讀?我應該使用'-n 4096'還是其他類似的東西?它應該是我的用例層出不窮 – Climax

+0

也將printf工作正確的二進制數據,因爲在字符串中允許null(0x00)而不停止? – Climax

+0

這提出了一個更好的觀點,即'read'將放棄它用來定義行的任何分隔符。你必須寫出分隔符,*如果*'read'實際超時。我越想這件事,越少我認爲這是一個好主意。 – chepner