Link to home
Start Free TrialLog in
Avatar of Dr. Klahn
Dr. Klahn

asked on

Want to timestamp into the cron logfile

I would like to put a timestamped separator in the cron log at midnight:

(blank)
==================== 23 March 2020 ====================
(blank)

Open in new window


I've put an echo line into /etc/crontab, and that sends me an email that I don't want.

I've put an extended line into the crontab prefacing the echo line with { MAILTO=""; (echo here); } and that still sends the unwanted email.

I've written a script with MAILTO="" and echo lines in it which works splendidly on the console and does not send the unwanted email, but puts nothing into the cron log file.

goofling around produced no immediate results.  But Debian does something close to this, because the cron log was showing single-line timestamps when I brought the system up -- and then discovered how to disable, which I did by deleting instead of commenting out.

Is there a simple way to do this?
Avatar of MURUGESAN N
MURUGESAN N
Flag of India image

@Dr. Klahn

I tried the following (from root user) using CentOS:
/usr/bin/yum -y install vixie-cron
$ /usr/bin/yum -y install vixie-cron
$ /sbin/service crond start
$ /bin/ps -eafj | /bin/egrep -v "\/bin\/ps|\/bin\/egrep|\/bin\/egrep" | /bin/egrep "crond|PID"
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
root      6380     1  6380  6380  0 09:43 ?        00:00:00 crond
$ echo -e "#\041/bin/bash\n/usr/bin/ls -ltrd ~/ > /root/delete.txt 2>&1" > /root/list.sh
$ cat  /root/list.sh
#!/bin/bash
/usr/bin/ls -ltrd ~/ > /root/delete.txt 2>&1
$ /usr/bin/crontab -e

Open in new window

Typed the following
* * * * * /root/list.sh > /root/delete.txt 2>&1
$ /usr/bin/ls -ltrp /root/delete.txt
-rw-r--r-- 1 root root 48 Mar 22 09:52 /root/delete.txt
$ grep list.sh  /var/log/cron
Mar 22 04:22:01 bmovm crond[6854]: (root) CMD (/root/list.sh > /root/delete.txt 2>&1)

Open in new window


you can type required commands inside list.sh (including date/...)
@Dr. Klahn
Few more information:
$ cat ~/list.sh
#!/bin/bash
#Always unalias any name before defining a function
unalias DispDate >/dev/null 2>&1
unset -f DispDate
DispDate ()
{
	LOGNAME=$(whoami)
	HOME=$(getent passwd $LOGNAME | awk -F: '{ print $6}')
	#Using default TZ value at localhost.
	while [ 1 ]
	do
		#Assign OUTPUT_FILE pointing to $HOME/OUTPUT_dd_mm_yyy....txt
		OUTPUT_FILE="$HOME/OUTPUT_"$(/usr/bin/date "+%d_%b_%Y_%H_%M_%S")".txt"
		if [ ! -f "$OUTPUT_FILE" ]
		then
			# If $OUTPUT_FILE is not present break the loop
			break
		fi
	done
	if [ -d /usr/share/zoneinfo/ ]
	then
		for TZLOC in $(/usr/bin/ls -ltrd -ld /usr/share/zoneinfo/*/* | /usr/bin/awk '{ printf( "%s ", substr( $NF, 21) );}' | sed "s/ $//;")
		do
			export TZ=$TZLOC
			# echo display date at all locations and redirect the output and error(if any) to $OUTPUT_FILE file
			echo $(/usr/bin/date "+%a %d-%b-%Y %H:%M %S %N %Z") $TZLOC |\
			/usr/bin/awk '{
				if ( ENVIRON["TZ"] != $NF )
				{
					printf( "%s %s %s %s %s %s %s\n", $1, $2, $3, $4, $5, $6, ENVIRON["TZ"]);
				}
				else
				{
					printf( "%s %s %s %s %s %s\n", $1, $2, $3, $4, $5, $6);
				}
			}' >> "$OUTPUT_FILE" 2>&1
		done
	else
		echo "/usr/bin/ls -ld /usr/share/zoneinfo"
	fi
	return $?
}
DispDate $@

Open in new window

Output:
murugesandins@123.456.78.910 /home/murugesandins [ 0 ]
$ crontab -e
[/code]
* * * * * /home/murugesandins/list.sh

crontab: installing new crontab
murugesandins@123.456.78.910 /home/murugesandins [ 1 ]
$ sudo /etc/init.d/crond start
Starting crond:                                            [  OK  ]
murugesandins@123.456.78.910 /home/murugesandins [ 0 ]
$ head OUTPUT_22_Mar_2020_10_58_01.txt
Sat 21-Mar-2020 23:58 01 552772000 SST
Sun 22-Mar-2020 03:58 01 554160000 PDT
Sun 22-Mar-2020 04:58 01 556048000 MDT
Sun 22-Mar-2020 06:58 01 558128000 EDT
Sun 22-Mar-2020 05:58 01 621515000 CDT
Sun 22-Mar-2020 00:58 01 624064000 HST
Sun 22-Mar-2020 06:58 01 627190000 EDT
Sun 22-Mar-2020 06:58 01 629896000 EDT
Sun 22-Mar-2020 05:58 01 714155000 CDT
Sun 22-Mar-2020 03:58 01 745125000 MST
murugesandins@123.456.78.910 /home/murugesandins [ 0 ]
$ tail OUTPUT_22_Mar_2020_10_58_01.txt
Sun 22-Mar-2020 10:58 03 017943000 posix/Australia
Sun 22-Mar-2020 10:58 03 019527000 posix/Atlantic
Sun 22-Mar-2020 10:58 03 021072000 posix/Asia
Sun 22-Mar-2020 10:58 03 022677000 posix/Arctic
Sun 22-Mar-2020 10:58 03 024241000 posix/Antarctica
Sun 22-Mar-2020 10:58 03 025855000 posix/America
Sun 22-Mar-2020 10:58 03 027704000 posix/Africa
Sun 22-Mar-2020 10:58 03 029462000 America/Kentucky
Sun 22-Mar-2020 10:58 03 031315000 America/Indiana
Sun 22-Mar-2020 10:58 03 033153000 America/Argentina

Open in new window

Avatar of Dr. Klahn
Dr. Klahn

ASKER

This is cleverly written code, but not what I want.  I want the output to appear in the cron log.
@Dr. Klahn

We can achieve the same using similar way.
I have updated same code (for simulation)
$ cat ~/list.sh
#!/bin/bash
#Always unalias any name before defining a function
unalias DispDate >/dev/null 2>&1
unset -f DispDate
DispDate ()
{
        LOGNAME=$(whoami)
        HOME=$(getent passwd $LOGNAME | awk -F: '{ print $6}')
        #Using default TZ value at localhost.
        #Assign OUTPUT_FILE pointing to /var/log/cron
        CRONLOG=/var/log/cron
        OUTPUT_FILE="$HOME/OUTPUT_"$(/usr/bin/date "+%d_%b_%Y_%H_%M_%S")".txt"
        if [ -d /usr/share/zoneinfo/ ]
        then
                for TZLOC in $(/usr/bin/ls -ltrd -ld   /usr/share/zoneinfo/*/* | /usr/bin/awk '{ printf( "%s ", substr( $NF, 21) );}' | sed "s/ $//;")
                do
                        export TZ=$TZLOC
                        # echo display date at all locations and redirect the output and error(if any) to $OUTPUT_FILE file
                        echo $(/usr/bin/date "+%a %d-%b-%Y %H:%M %S %N %Z") $TZLOC |\
                        /usr/bin/awk '{
                                if ( ENVIRON["TZ"] != $NF )
                                {
                                        printf( "%s %s %s %s %s %s %s\n", $1, $2, $3, $4, $5, $6, ENVIRON["TZ"]);
                                }
                                else
                                {
                                        printf( "%s %s %s %s %s %s\n", $1, $2, $3, $4, $5, $6);
                                }
                        }' >> "$OUTPUT_FILE" 2>&1
                        # I have written break here
                        break
                done
                echo "$(/usr/bin/date "+%a %d-%b-%Y %H:%M %S %N %Z") Completing murugesandins list.sh" >> "$CRONLOG"
        else
                echo "/usr/bin/ls -ld /usr/share/zoneinfo"
        fi
        return $?
}
DispDate $@

Open in new window


Main change:
a)
CRONLOG=/var/log/cron
b)
echo "$(/usr/bin/date "+%a %d-%b-%Y %H:%M %S %N %Z") Completing murugesandins list.sh" >> "$CRONLOG"
after completing the for loop
c)
for testing I have included break command inside for loop.


Sample output:
$ tail -3 /var/log/cron
Sun 22-Mar-2020 00:15 01 318371000 SST Completing murugesandins list.sh
Sun 22-Mar-2020 00:16 01 507489000 SST Completing murugesandins list.sh
Sun 22-Mar-2020 00:17 01 757822000 SST Completing murugesandins list.sh

Open in new window

@Dr. Klahn

>> I want the output to appear in the cron log.
Any comment or updates required ?
It is not permissible to write directly to the cron logfile -- or indeed any log file -- as those files are not interlocked against multiple writers.
ASKER CERTIFIED SOLUTION
Avatar of Dr. Klahn
Dr. Klahn

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
@Dr. Klahn

Since I am the owner, hence written the code (from root user) :) here.
>> workable solution is to use the logger
I agree.
Few more information, better to follow >> OUTPUT_LOG_FILE instead of using further commands like logger due to
1. performance issue
2. increasing disk usage (df /bdf)
3. locking (process1 holding src1 waiting for src2, process2 holding src2 waiting for src1 making dead lock)
4. inode handle by data block by kernel => rename /make a copy
Hence better to follow using OUTPUT_LOG_FILE at required directory where disk space is available.
We can achieve the same using sudo for any required command.
your wish for making ASKER CERTIFIED SOLUTION :)
Postscript:  In fact the logger solution does not work, but two lines of C code in a minimal program does:

  /* Attach to syslog, send the message, and exit.*/

  openlog("cronmsg", LOG_PID, LOG_CRON);
  syslog(LOG_INFO, "%s", argtext);

Open in new window

>> logger solution does not work
:)
>> two lines of C code in a minimal program does
Thank you for sharing the same.

I am not proceeding further comments ( => two lines, locking, bug 2004, bug fix 2018 ... ).

Proceed the same.