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?
Linux* cronjobs* Debian* Cron

Avatar of undefined
Last Comment
MURUGESAN N

8/22/2022 - Mon
MURUGESAN N

@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/...)
MURUGESAN N

@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

Dr. Klahn

ASKER
This is cleverly written code, but not what I want.  I want the output to appear in the cron log.
Your help has saved me hundreds of hours of internet surfing.
fblack61
MURUGESAN N

@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

MURUGESAN N

@Dr. Klahn

>> I want the output to appear in the cron log.
Any comment or updates required ?
Dr. Klahn

ASKER
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.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
ASKER CERTIFIED SOLUTION
Dr. Klahn

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
MURUGESAN N

@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 :)
Dr. Klahn

ASKER
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

MURUGESAN N

>> 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.
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes