簡體   English   中英

奇怪的重定向行為允許輸出截斷

[英]Strange redirection behaviour allowing output truncation

我們有一個構建腳本,可以為多種電路板類型構建嵌入式系統,並且以一種方式捕獲輸出時,它似乎可以正常工作。 另一種方法是,它部分通過輸出,然后在繼續之前截斷文件。

工作方式:

time ( cd ~ ; builder.sh 2>&1 | tee ~/builder.out )

和似乎截斷的方式:

time ( cd ~ ; builder.sh > ~/builder.out 2>&1 )

截斷似乎發生在非常特定的位置,截斷后文件的第一行始終是qmake DEFAULT_INCDIRS=... 它是在過程中的特定點而不是在文件達到特定大小時,這一事實似乎表明它不是執行截斷的外部文件檢查器。

無論如何,如果腳本被刪除,腳本將繼續寫入已刪除文件的索引節點,直到關閉為止,然后它將刪除該索引節點。

實際發生的情況是該文件似乎已被截斷,然后從頭開始繼續寫入。 但是我知道,如果沒有程序實際上無法訪問文件句柄本身,就無法做到這一點。

在以上兩種情況下,構建器腳本實際上都不知道其輸出文件,它只是將輸出消息和錯誤消息都寫到stdout並讓Shell重定向來處理它。

所以我的問題是:在文件I / O的UNIX模型中有沒有辦法做到這一點(例如,從C文件API調用)? 換句話說,當通過重定向設置了要寫入的文件時,是否可以截斷該文件? tee為什么起作用? 是什么阻止它被截斷?

所以,是的,正如您已經注意到的,顯然有人在stdout上調用了lseek()ftruncate()

要追蹤罪犯, strace -f當然會有所幫助。 當做這樣奇特的事情時,您可能需要做strace -f sh -c 'build.sh 2>&1 | cat > output' > log 2>&1 strace -f sh -c 'build.sh 2>&1 | cat > output' > log 2>&1因為它也會很高興地破壞您的strace輸出。

有了日志后,找到對lseek(1,lseek(2,ftruncate(1, ,或ftruncate(2,的調用)。從那里,向后搜索到前一個exec ,您應該知道。

cdrecord是一個可以正常使用stdout游戲的程序,其中至少有一些版本希望將CD刻錄機輸出到標准輸出中。

好的,事實證明程序可以尋求標准輸出(盡管我懷疑這樣做的程序是否合理)。

以下程序說明了這一點:

#include <stdio.h>

int main(void){
    for (int i = 3; i > 0; --i) {
        //rewind(stdout);
        printf("Hello, world %d !\n", i);
    }
    return 0;
}

運行此捕獲輸出,您將得到一個包含以下內容的文件:

Hello, world 3 !
Hello, world 2 !
Hello, world 1 !

但是,如果取消注釋rewind行,則只會在輸出文件中以最后一行結束。

有趣的是,由於我無法控制截斷stdout的程序,因此對於“貓的無用使用”獎,這實際上可能是有用的用貓。 代替執行:

myprog >outfile 2>&1

並讓myProg截斷文件,我可以改為:

myprog 2>&1 | cat >outfile

並且管道將保護cat輸出文件不被截斷。


就實際問題而言,似乎出於某種原因, qt5basebuildroot一部分)正在使用輸出文件句柄播放某種qt5base 由於沒有時間追逐buildroot(或創建補丁文件)以使其正確修復,因此我們使用上述cat方法解決了該問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM