Home > Software engineering >  Cron: Diaplay the commands run by cron scheduler using awk
Cron: Diaplay the commands run by cron scheduler using awk

Time:05-30

I'm writing a script to get a list of only the commands from my crontab. My input data so far looks like this:

$  crontab -l | grep -i --color -v '^#' | awk '$0 ~ /^*\/[0-9]{1,20}|\* /'
*/5 * * * * /usr/local/bin/bash msmtp-queue -r 
*/5 * * * * /usr/bin/env bash /Users/tonybarganski/bin/offlineimap-fetch
*/15 * * * * /usr/bin/env bash ~/bin/checkMail
00 12 * * * /usr/local/bin/bash ~/bin/lbdb-fetchaddress-daily
* */3 * * * /usr/bin/env rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.log

Outcome

Print everything after either '/usr/bin/env bash' or '/usr/local/bin/bash' or '* */3 * * *'

msmtp-queue -r 
offlineimap-fetch
checkMail
lbdb-fetchaddress-daily
rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.log

Tried

I tried starting from the end of file ($NF) and printing everything up until the first forward slash but I just got syntax errors with where to put the brackets:

$ crontab -l | grep -i --color -v '^#' | \
awk -F'/' '{ if ($0 ~ /^*\/[0-9]{1,20}|\* /) for(i=NF;i>0;i--) { if ( sub(/\//, "", $i) { print $i} } }'
awk: cmd. line:1: { if ($0 ~ /^*\/[0-9]{1,20}|\* /) for(i=NF;i>0;i--) { if ( sub(/\//, "", $i) { print $i} } }
awk: cmd. line:1:                                                                              ^ syntax error

How can this be achieved?

CodePudding user response:

If you don't really want the output in your question and instead want the output shown in the currently accepted answer then all you need is:

$ sed -E 's/([^ ]* ){5}//' file
/usr/local/bin/bash msmtp-queue -r
/usr/bin/env bash /Users/tonybarganski/bin/offlineimap-fetch
/usr/bin/env bash ~/bin/checkMail
/usr/local/bin/bash ~/bin/lbdb-fetchaddress-daily
/usr/bin/env rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.log

The above requires a sed that has -E to enable EREs, e.g. GNU or BSD sed. With any POSIX sed you could do sed 's/\([^ ]* \)\{5\}//' file instead or with any POSIX awk awk '{sub(/([^ ]* ){5}/,"")}1' file.

CodePudding user response:

If you want to

Print everything after either '/usr/bin/env bash' or '/usr/local/bin/bash' or '* */3 * * *'

and given the format of the examples, you can split on the different patterns and check if there are at least 2 parts.

If file contains the example data:

awk '
{
  n = split($0,a, /(^\* \*\/3 \* \* \*|\/usr\/local\/bin\/bash|\/usr\/bin\/env[[:space:]] bash)[[:space:]] /)
  if (n > 1) {
    print a[2]
  }
}
' file

Output

msmtp-queue -r 
/Users/tonybarganski/bin/offlineimap-fetch
~/bin/checkMail
~/bin/lbdb-fetchaddress-daily
/usr/bin/env rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.log

CodePudding user response:

get a list of only the commands from my crontab

I would just jettison 5 first fields, let file.txt content be

*/5 * * * * /usr/local/bin/bash msmtp-queue -r 
*/5 * * * * /usr/bin/env bash /Users/tonybarganski/bin/offlineimap-fetch
*/15 * * * * /usr/bin/env bash ~/bin/checkMail
00 12 * * * /usr/local/bin/bash ~/bin/lbdb-fetchaddress-daily
* */3 * * * /usr/bin/env rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.lo

then

awk 'BEGIN{FS="[ ]"}{$1=$2=$3=$4=$5="";sub(/^ */,"");print}' file.txt

gives output

/usr/local/bin/bash msmtp-queue -r
/usr/bin/env bash /Users/tonybarganski/bin/offlineimap-fetch
/usr/bin/env bash ~/bin/checkMail
/usr/local/bin/bash ~/bin/lbdb-fetchaddress-daily
/usr/bin/env rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.lo

Explanation: I inform GNU AWK that field separator (FS) and output field separator (OFS) is single space. I do not use default FS as it would cause changing tab characters to space characters to space and compressing spaces (2 or more consecutive spaces into single space). For each line I set 1st, 2nd, 3rd, 4th and 5th field to empty string, then use sub to shave off leading spaces, then print such altered line.

(tested in GNU Awk 5.0.1)

CodePudding user response:

Using sed (if applicable)

$ sed s'/.*\(bin\/\|\/env \)\?bash \|.*\* //' input_file
msmtp-queue -r
/Users/tonybarganski/bin/offlineimap-fetch
~/bin/checkMail
~/bin/lbdb-fetchaddress-daily
/usr/bin/env rsync -auv -f- index.lock --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.log

CodePudding user response:

$ awk -F"bash|env bash|env" '!/^#/ {print $2}' <(crontab -l)
 msmtp-queue -r 
 /Users/tonybarganski/bin/offlineimap-fetch
 ~/bin/checkMail
 ~/bin/lbdb-fetchaddress-daily
 rsync -auv -f"- index.lock" --exclude={'Macintosh HD','MyArchive'} ~/mnt/ ~/.Backup/mnt/ > ~/crypto-vols-backup.log
  • Related