2009-02-01 80 views
8

我已經編寫了一個程序,它使用printf將消息發送到標準輸出,並且我無法將輸出重定向到一個文件(從bash運行)。在bash中重定向C程序輸出的問題

我已經試過:

./program argument >> program.out 
./program argument > program.out 
./program >> program.out argument 
./program > program.out argument 

在每種情況下,在文件被創建program.out但它仍然是空的。執行結束後,將文件的大小爲0。

如果我在執行程序時省略了重定向:

./program argument 

然後,發送用printf到stdout的所有消息在終端被示出。

我有其他的C程序,我沒有問題重定向輸出這種方式。 它與程序本身有關嗎?參數傳遞? 應該在哪裏尋找問題?

關於C程序的一些細節:

  • 它不會從標準
  • 它採用BSD互聯網域套接字
  • 它使用POSIX線程
  • 它分配一個特殊處理函數讀什麼使用sigaction的SIGINT信號
  • 它向stdout發送大量新行(對於那些你認爲我應該刷新的行)

一些代碼:

int main(int argc, char** argv) 
{ 
    printf("Execution started\n"); 
    do 
    {   
     /* lots of printf here */ 
    } while (1); 
    /* Code never reached */ 
    pthread_exit(EXIT_SUCCESS); 
} 
+0

是否不輸出重定向相同的程序產生任何輸出到屏幕上? – womble 2009-02-01 00:32:39

+0

我編輯了這個問題來澄清。謝謝 – mmutilva 2009-02-01 00:40:36

回答

14

沖洗後換行只打印到終端的時候,但不一定打印到文件時的作品。快速谷歌搜索顯示此頁面的進一步信息:http://www.pixelbeat.org/programming/stdio_buffering/

請參閱標題爲「默認緩衝模式」一節。

畢竟,您可能需要添加一些調用fflush(stdout)。

您還可以使用setvbuf來設置緩衝區大小和行爲。

+1

程序何時結束呢?不應該stdout被自動刷新呢? – mmutilva 2009-02-01 01:06:54

3

程序在檢查重定向文件的內容時終止了嗎?如果它仍在運行,你的輸出可能仍然會被緩衝到鏈上,所以你不會在文件中看到它。

除此之外,以及迄今爲止提供的其他答案,我認爲該是展示問題代碼示例的時候了。有太多深奧的可能性。

編輯

從樣本代碼的外觀,如果你有印刷發生的相對較少,那麼你就陷入輸出緩衝器。在每次寫入之後沖洗以確保它已經寫入磁盤。通常情況下,您可以擁有最多達到頁面大小的未寫入數據。

在沒有刷新的情況下,唯一一次可以確定你已經獲得磁盤上的所有內容的時候,程序退出。即使是一個線程終止也不會這樣做,因爲像這樣的輸出緩衝區不是每個線程,而是每個進程。

6

刷新緩衝區通常由exit()函數處理,該函數通常由來自main()的return隱式地調用。通過提高SIGINT來結束程序,顯然缺省的SIGINT處理程序不會刷新緩衝區。

看一看這篇文章: Applying Design Patterns to Simplify Signal Handling。文章主要是C++,但在第二部分中有一個有用的C例子,它展示瞭如何使用SIGINT來優雅地退出程序。

至於爲什麼一個終端的行爲不同於一個文件, 看看史蒂文斯的Advanced Programing in the UNIX Environment緩衝節5.4。他說:

大多數實現默認爲以下類型的緩衝。 標準錯誤始終未緩衝。 如果所有其他流引用終端設備,則其他流都是行緩衝的;否則,它們會被完全緩衝。 本書中討論的四種平臺遵循標準I/O緩衝的這些慣例:標準錯誤是無緩衝的,向終端設備開放的流是行緩衝的,所有其他流都是完全緩衝的。
0

建議:

  1. stderr重定向到一個文件中。
  2. 嘗試尾巴-f你的輸出文件。
  3. 打開一個文件並記錄你的日誌(以幫助弄清楚發生了什麼)。
  4. 搜索std * FILE句柄或1-3文件描述符的任何手動關閉/複製/管道。
  5. 降低複雜度;裁剪大塊的功能,直到printfs工作。然後讀取它們直到它再次破裂。繼續,直到找出罪魁禍首的代碼。
0

只是爲了記錄在案,在Perl中你可以使用:

use IO::Handle; 

flush STDOUT; 
autoflush STDOUT;