简体   繁体   中英

Problem redirecting a C program output in bash

I've coded a program in C that sends messages to the stdout using printf and I'm having trouble redirecting the output to a file (running from bash).

I've tried:

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

In each case, the file program.out is created but it remains empty. After the execution ends the file size is 0.

If I omit the redirection when executing the program:

./program argument

Then, all messages sent to stdout using printf are shown in the terminal.

I have other C programs for which I've no problem redirecting the output this way. Does it have to do with the program itself? with the argument passing? Where should look for the problem?

Some details about the C program:

  • It does not read anything from stdin
  • It uses BSD Internet Domain sockets
  • It uses POSIX threads
  • It assigns a special handler function for SIGINT signal using sigaction
  • It sends lots of newlines to stdout (for those of you thinking I should flush)

Some code:

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

Flushing after newlines only works when printing to a terminal, but not necessarily when printing to a file. A quick Google search revealed this page with further information: http://www.pixelbeat.org/programming/stdio_buffering/

See the section titled "Default Buffering modes".

You might have to add some calls to fflush(stdout), after all.

You could also set the buffer size and behavior using setvbuf .

Flushing the buffers is normally handled by the exit() function, which is usually called implicitly by a return from main(). You are ending your program by raising SIGINT, and apparently the default SIGINT handler does not flush the buffers.

Take a look at this article: Applying Design Patterns to Simplify Signal Handling . The article is mostly C++, but there is a useful C example in the 2nd section, which shows how to use SIGINT to exit your program gracefully.

As for why the behavior of a terminal differs from a file, take a look at Stevens' Advanced Programing in the UNIX Environment Section 5.4 on Buffering. He says that:

Most implementations default to the following types of buffering. Standard error is always unbuffered. All other streams are line buffered if they refer to a terminal device; otherwise, they are fully buffered. The four platforms discussed in this book follow these conventions for standard I/O buffering: standard error is unbuffered, streams open to terminal devices are line buffered, and all other streams are fully buffered.

Has the program terminated by the time you check the contents of the redirected file? If it's still running, your output might still be buffered somewhere up the chain, so you don't see it in the file.

Apart from that, and the other answers provided so far, I think it's time to show a representative example of the problem code. There's too many esoteric possibilities.

EDIT

From the look of the sample code, if you've got a relatively small amount of printing happening, then you're getting caught in the output buffer. Flush after each write to be sure that it's gone to disk. Typically you can have up to a page size's worth of unwritten data lying around otherwise.

In the absence of a flush, the only time you can be sure you've got everything on disk is when the program exits. Even a thread terminating won't do it, since output buffers like that aren't per-thread, they're per-process.

Just for the record, in Perl you would use:

use IO::Handle;

flush STDOUT;
autoflush STDOUT;

Suggestions:

  1. Redirect stderr to a file as well.
  2. Try tail -f your output file(s).
  3. Open a file and fprintf your logging (to help figure out what's going on).
  4. Search for any manual closes/duplication/piping of std* FILE handles or 1-3 file descriptors.
  5. Reduce complexity; cut out big chunks of functionality until printfs work. Then readd them until it breaks again. Continue until you identify the culprit code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM