I have a bash script from which i need to write logs. currently i use block like the one below
#log stop request
{
local now=$(date +"%a %b %d %Y %H:%M:%S")
printf "batch stop request successful. \n"
printf " Time :: %s\n" "$now"
printf " PID of process :: %s\n" ${PID[0]}"
} >> "${mylogfile}"
where mylogfile variable will have name of the logfile.
The problem with this approach is that when 2 or more instances are running, the logs tends to get messed up with writes from instances coming interleaved.
Please note i used the block thinking that it would result in the log being written to file in one go, thus avoiding the problem.
I have seen logger command from Vivek Gite post. but the problem is it does not write to a file I can specify, rather does so to /var/log/message.
Any help is much appreciated.
Thanks and Regards Sibi
#!/bin/bash Essentially it tells your terminal that when you run the script it should use bash to execute it. It can be vital since you may be using a different shell in your machine ( zsh , fish , sh , etc.), but you designed the script to work specifically with bash.
POSIX (IEEE Std 1003.1-2001) does not define the behavior of concurrent write() syscalls sending data to the same file, hence you may obtain different results depending on your platform. You can try to merge all printfs
into one in the hope that this will work, but even if it does there is no guarantee that it will in the future or on a different platform.
Rather than using concurrency control and flushing to ensure the writes are sequenced, you can send the messages to a third process which will write your log messages sequentially to a file on behalf on all the processes. In fact, this is what is done with logger
and syslog
in the post you cited. The logger
command does not send the messages to /var/log/messages
. It sends the log messages to syslog
which can be configured to save the log messages anywhere you like. Changing this configuration usually requires administrative privileges, though.
If you can't or don't want to use syslog
, you can also use netcat as a logging server. Run this to multiplex all incoming log messages from all scripts into the file (this job should remain running in the background all the time, you can also run it in a screen):
nc -luk localhost 9876 > shared_log_file &
(port 9876 is just an example) and log in each script this way:
printf "Log message\n" > /dev/udp/localhost/9876
You can also use a custom UDP server instead of netcat (e.g. like this one).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With