Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parallel writing to a file from multiple processes by using echo

I have written a function in our ERP-System which writes a log to a file on the server by simply "echoing" it to the logfile.

echo "SOME LOGDATA" >> /users/erp/log/LOGMSG

Every time a user triggers a specific event, the LOG function is called.

What would happen if 2 users trigger the LOG event exactly at the same time?

Does "echo" take care of file locking? In my opinion it has to be the linux kernel or the bash who has to takes care, that a file is not written by 2 command line instructions simultaneously.

I wrote a testcase to force this condition (some 1000 LOG calls within one second) and it seems that my thoughts are right but I can not be really sure, that these calls are executed at the same time on the bash.

like image 421
Alexander Baltasar Avatar asked Nov 24 '15 07:11

Alexander Baltasar


People also ask

Can multiple processes write to the same file?

no, generally it is not safe to do this! you need to obtain an exclusive write lock for each process -- that implies that all the other processes will have to wait while one process is writing to the file.. the more I/O intensive processes you have, the longer the wait time.

Can two processes open the same file?

The process of opening (and if necessary creating) the file is atomic, so it will never happen that one process will create the file but the other process will open it. Note: this is specific to Windows, other operating systems have different behaviour.

How do I run multiple shell scripts in parallel?

GNU parallel is a shell tool for executing jobs in parallel using one or more computers. A job can be a single command or a small script that has to be run for each of the lines in the input. The typical input is a list of files, a list of hosts, a list of users, a list of URLs, or a list of tables.

How do you run a command in parallel?

Running Commands in Parallel using Bash Shell The best method is to put all the wget commands in one script, and execute the script. The only thing to note here is to put all these wget commands in background (shell background). See our simple script file below. Notice the & towards the end of each command.


3 Answers

As explained here, echo is guaranteed to be atomic only when writing sequences shorter than the smaller of PIPE_BUF and the size of the stdout buffer (which is most likely BUFSIZ).

For longer sequences, you need to locking. Use can use lockfile-create and lockfile-check.

like image 59
Claudio Avatar answered Oct 04 '22 19:10

Claudio


You can use GNU Parallel as a mutex/semaphore ensuring that only one echo runs at a time like this:

sem --id mysem echo "System crashed"  >> log.txt

GNU Parallel is installed on most Linux distros, and is readily available for OSX via homebrew.

You can test the idea by starting a loop in each of two, or more, terminals and having each one do this:

for i in {1..100}; do sem --id mysem echo hi >> log ; done

and at the end you will see there are exactly 100 lines per terminal in your log.

like image 36
Mark Setchell Avatar answered Oct 04 '22 21:10

Mark Setchell


Be careful not to reinvent the wheel, in *nix systems there is syslog to handle logging in a proper way. The problem with echo to a file is that you can enforce mutual exclusion but the hardest part would be to handle serialization, the fact that one echo writes before another does not mean that the logged operation actually executed first (nor in parallel).

like image 25
Oberix Avatar answered Oct 04 '22 20:10

Oberix