簡體   English   中英

在bash中重定向C程序輸出時出現問題

[英]Problem redirecting a C program output in bash

我用C編寫了一個程序,它使用printf將消息發送到stdout,我無法將輸出重定向到一個文件(從bash運行)。

我試過了:

./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程序的一些細節:

  • 它沒有從stdin中讀取任何內容
  • 它使用BSD Internet Domain套接字
  • 它使用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);
}

換行后的刷新僅在打印到終端時有效,但在打印到文件時不一定。 谷歌的快速搜索在此頁面上顯示了更多信息: http//www.pixelbeat.org/programming/stdio_buffering/

請參閱標題為“默認緩沖模式”的部分。

畢竟,你可能不得不為fflush(stdout)添加一些調用。

您還可以使用setvbuf設置緩沖區大小和行為。

刷新緩沖區通常由exit()函數處理,該函數通常由main() return隱式調用。 您通過引發SIGINT結束程序,顯然默認的SIGINT處理程序不會刷新緩沖區。

看看這篇文章: 應用設計模式簡化信號處理 這篇文章主要是C ++,但在第二部分中有一個有用的C示例,它展示了如何使用SIGINT優雅地退出程序。

至於終端的行為與文件的不同之處,請參閱UNIX環境第5.4節中關於緩沖的史蒂文斯的高級編程 他說:

大多數實現默認為以下類型的緩沖。 標准錯誤始終是無緩沖的。 如果它們引用終端設備,則所有其他流都是行緩沖的; 否則,它們是完全緩沖的。 本書中討論的四個平台遵循標准I / O緩沖的這些約定:標准錯誤是無緩沖的,對終端設備開放的流是行緩沖的,所有其他流都是完全緩沖的。

在您檢查重定向文件的內容時程序是否已終止? 如果它仍在運行,您的輸出可能仍會在鏈的某個位置緩沖,因此您不會在文件中看到它。

除此之外,到目前為止提供的其他答案,我認為是時候展示問題代碼的代表性示例了。 有太多深奧的可能性。

編輯

從示例代碼的外觀來看,如果您進行了相對少量的打印,那么您將被捕獲到輸出緩沖區中。 每次寫入后刷新,以確保它已進入磁盤。 通常情況下,您可以擁有最多頁面大小的未寫入數據。

在沒有刷新的情況下,唯一一次可以確定你已經擁有磁盤上的所有東西就是程序退出的時候。 即使是一個終止的線程也不會這樣做,因為像這樣的輸出緩沖區不是每個線程,它們是每個進程。

只是為了記錄,在Perl中你會使用:

use IO::Handle;

flush STDOUT;
autoflush STDOUT;

建議:

  1. 將stderr重定向到文件。
  2. 嘗試tail -f你的輸出文件。
  3. 打開一個文件並fprintf你的日志記錄(以幫助弄清楚發生了什么)。
  4. 搜索std * FILE句柄或1-3文件描述符的任何手動關閉/復制/管道。
  5. 降低復雜性; 在printfs工作之前,切掉大塊功能。 然后讀取它們直到它再次破裂。 繼續,直到您找出罪魁禍首代碼。

暫無
暫無

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

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