snowfox
snowfox

Reputation: 2098

How to write a file in multiple processes using standard I/O functions on Linux?

I'm working on a feature which requires writing a single log file(identified by its path) in multiple processes. Previously, each process used to call printf to stream the log on terminal(standard output). Now I need to change the output destination to a file. So I tried using freopen to redirect the stdout to the file in each process.

freopen(file_path, "a", stdout); //

But it seems it doesn't work well. Some log is missing. What's the common practice to achieve this ?

B.T.W In our requirement, the user should be allowed to switch logging destination between file and standard output, so the first argument "file_path" could be tty when switched back to terminal. Is that OK to call freopen(tty, "a", stdout)?

Upvotes: 1

Views: 2598

Answers (3)

pilcrow
pilcrow

Reputation: 58589

Writes in O_APPEND mode will do what you want as long as they are less than PIPE_BUF bytes, which is usually plenty of room (about 4k).

So, set the newly freopen()ed file to line buffered (_IOLBF below), and then make sure your writes contain a newline to flush the buffer:

freopen(file_path, "a", stdout);
setvbuf(stdout, (char *)NULL, _IOLBF, 0); // a.k.a. setlinebuf(stdout) under BSD

...

printf("Some log line\n"); // Note the newline!

Upvotes: 1

Spencer Rathbun
Spencer Rathbun

Reputation: 14900

Pipe your output to a file handle called, say, output using fprintf. Since file handle's are just pointers, just set output = stdout or output = yourFile. Then every fprintf(output, "sometext") winds up going wherever that handle is set at the moment. You can even have a function to dynamically redirect the output on the fly based upon user input.

Upvotes: 0

paulsm4
paulsm4

Reputation: 121669

You have many options:

1) the simplest approach would be for every process to simply write to the same log independently. The problem, of course, is that the file would get scrambled if any two processes wrote different messages at the same time.

2) You could instead have the processes send messages to one "master logger", which would then output messages one at a time, in the order received. The "master logger" might use sockets. If all the processes were on the same host, you might instead use a message queue or a named pipe.

3) Even simpler, you could have a system-wide semaphore to insure only one message at a time gets written.

4) Yet another approach could be to use an open-source logger such as log4j or syslog-ng

Upvotes: 2

Related Questions