Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use logging in Bash script

Tags:

bash

logging

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

like image 715
Sibi JV Avatar asked Nov 25 '11 18:11

Sibi JV


People also ask

What is !/ Bin bash?

#!/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.


Video Answer


1 Answers

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).

like image 154
Adam Zalcman Avatar answered Sep 20 '22 04:09

Adam Zalcman