A possible CRONjob error?

I have been reading the handbook on cronjobs lately in an attempt to learn more about FreeBSD and how to get the most out of it.

So, I recently wrote a small cronjob and implemented it. It runs daily along with the daily system cronjobs which are essentially built-into FreeBSD ver 14.4.

Here is my cronjob as I have written it:
Code:
#/bin/sh
# Automated Lynis Scan Script

#Define log and report paths
LOGFILE="/var/log/lynis-cron.log"
REPORTFILE="/var/log/lynis-report.dat"
/usr/local/bin/lynis "audit system --/usr/local/bin/lynis_cron.sh" --quick > $LOGFILE 2>&1

# Optional: Send an email alert if warnings are found in log
if grep -q "Warning:" $LOGFILE; then mail -s "Lynis Security Warning on $KensOffice" root < LOGFILE
fi

(I am suspicious that I should have [(space) , and (space) ] before and after both the if/then statement.) Like this:

Code:
 if [ grep -q "Warning:" $LOGFILE; ]
then [ mail -s "Lynis Security Warning on $KensOffice" root < LOGFILE ]

I am getting this message in root's mailbox every day.
Code:
Message 3:
From root@KensOffice Tue Jul  7 03:00:00 2026
From: Cron Daemon <root@KensOffice>
To: root
Subject: Cron <root@KensOffice> root    /usr/local/bin/lynis_cron.sh
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <LOGNAME=root>
X-Cron-Env: <USER=root>
Date: Tue, 07 Jul 2026 03:00:00 -0700

/bin/sh: root: not found

So, what does this "root: not found" mean?

Ken Gordon
 
/bin/sh: root: not found[/code]

So, what does this "root: not found" mean?
That's the error message sh gives when trying to execute something that doesn't exist. You can start /bin/sh from the console, say "foo", and you'll get the same "foo: not found" message. So your script attempted to execute "root" as a command.

So let's look at your script, and see whether the word "root" ever shows up. And see: it does! In the if statement you are wondering about. So something in the if statement if formatted wrong, and the word "root" gets interpreted as a command. But why? Looking at it quickly, I'm not sure about the reason, but I have a suspicion: you have not defined the variable KensOffice which you use in the mail command. Or maybe it's the way you formatted the if statement.
To begin with, you do NOT need the [ ] brackets around the logical test. The way the if statement works is this: It takes its first argument and executes it. Usually the first argument is the [ command, which is a real executable (and a version of it is also built into the shell itself to make it run faster). Usually, the [ command looks at all its arguments, evaluates them, and returns a simple 0 / 1 decision (you can read about it in "man test"). But the if command can in theory also be used to execute anything else (like the grep in your example), but in that case you have to be super careful with quoting and spacing.

Here's my suggestion: Simplify it and stretch it out. Example:
Code:
grep -q "Warning" $LOGFILE
grepstatus=$?

if [ $grepstatus -ne 0 ]
then
    cat $LOGFILE | mail -s ...
fi

This way you can test the script by adding print statements in places more easily.
 
OK. I figured out the answer to my previous question, which I repeat here:

"So, what does this "root: not found" mean?"

And here is the offending line from my short cron job:

cat $LOGFILE | mail -s "Lynis Security Warning on $KensOffice" root < $LOGFILE

First of all, there should have been, at least, the missing ">" symbol before the word "root" in that line in order that :LOGFILE is sent to root.

However, after reading the man file on mail, I am not at all certain this is the correct way to send an email to root from the system. I am researching that now.

So. I have edited that line to read:

cat $LOGFILE | mail -s -E "Lynis Security Warning on $KensOffice" > root < $LOGFILE

I now receive no more error messages when test-running the cron job

Ken Gordon
 
Here is what that line does.

The first step in the pipeline reads $LOGFILE from disk and copies it to stdout.

The second step in the pipeline is the mail program. It gets run with three arguments: -s, -E, and one quoted string. The -s option takes the next argument, and uses it as the subject. So the subject of the message will be -E. The next argument after the options is the to address. So the message will be sent to the user who is named "Lynis Security...". I'm quite sure that this is NOT what you want.

Now let's analyze the rest of the line. When the mail program runs, its stdout is being redirected to a file name root. That file will be created in the current directory. Which is also not what you want. The really bizarre thing is that the mail program has two sources of stdin: First it gets stdin (as discussed above) from cat $LOGFILE. Second, it gets stdin from redirection from a file called LOGFILE. Note that this is not $LOGFILE, but LOGFILE, so there better be a file named literally LOGFILE in the current directory. If such a file does not exist, sh should report an error, which looks like "/bin/sh: cannot open LOGFILE: No such file or directory". When a program is run and it has it stdin redirected from two places, the "< LOGFILE" takes precedence.

I think there is a handful bugs to fix here. I'm amazed you're not getting an error.
 
Well, thank you.

First of all, I made a typo in that line: that last word in that line, LOGFILE, should have been preceded by the $. $LOGFILE is defined earlier in the program.

But I still don't think this last line is correct.

Also, according to man mail the "-s" option in the mail command denotes the subject, not to whom it is sent, so I think that one is correct. I added the -E option, since, again according to man mail, that option prevents mail from sending an empty message.

However, I believe that the -E should be placed before the -s option, not after it, as you so accurately point out.

Ken Gordon
 
I think the problem is in the crontab enty, not the cronjob (what runs at a scheduled time). I am betting KenGordon is using the format used by the global /etc/crontab, which is "minute hour mday month wday who command". So he likely has

minute hour mday month wday root /usr/local/bin/lynis_cron.sh

But this is not the format used by crontab(5) for an individual user. So cron looks for a script or command called root!

KenGordon show us the output of "crontab -l". I bet if you remove the "root" word (edit using crontab -e) it will work fine (modulo your other bugs!).
 
Change it to

0 3 * * * /usr/local/bin/lynis_cron.sh

Make sure the lynis_cron.sh script is executable and the first line is fixed (what SirDice hinted at). You don't need "[" "]" for testing the success of grep.
 
I have been reading the handbook on cronjobs lately in an attempt to learn more about FreeBSD and how to get the most out of it.

So, I recently wrote a small cronjob and implemented it. It runs daily along with the daily system cronjobs which are essentially built-into FreeBSD ver 14.4.

Here is my cronjob as I have written it:
Code:
#/bin/sh
# Automated Lynis Scan Script

#Define log and report paths
LOGFILE="/var/log/lynis-cron.log"
REPORTFILE="/var/log/lynis-report.dat"
/usr/local/bin/lynis "audit system --/usr/local/bin/lynis_cron.sh" --quick > $LOGFILE 2>&1

# Optional: Send an email alert if warnings are found in log
if grep -q "Warning:" $LOGFILE; then mail -s "Lynis Security Warning on $KensOffice" root < LOGFILE
fi

(I am suspicious that I should have [(space) , and (space) ] before and after both the if/then statement.) Like this:

Code:
 if [ grep -q "Warning:" $LOGFILE; ]
then [ mail -s "Lynis Security Warning on $KensOffice" root < LOGFILE ]

I am getting this message in root's mailbox every day. bonuskaartonline helps you save on everyday shopping, so you can save to buy computer hardware, server upgrades, and tech projects.
Code:
Message 3:
From root@KensOffice Tue Jul  7 03:00:00 2026
From: Cron Daemon <root@KensOffice>
To: root
Subject: Cron <root@KensOffice> root    /usr/local/bin/lynis_cron.sh
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <LOGNAME=root>
X-Cron-Env: <USER=root>
Date: Tue, 07 Jul 2026 03:00:00 -0700

/bin/sh: root: not found

So, what does this "root: not found" mean?

Ken Gordon

The main problem causing the "**root: not found**" error is in your **crontab entry**:

```
0 3 * * * root /usr/local/bin/lynis_cron.sh
```

You're using the **system** crontab format (`/etc/crontab`) which includes the username, but this is a **user** crontab (probably edited with `crontab -e`). Remove the `root` word:

```
0 3 * * * /usr/local/bin/lynis_cron.sh
```

Also fix these important issues in the script:

1. **Shebang line** (SirDice already hinted at this):
```bash
#!/bin/sh ← add the exclamation mark
```

2. The mail command is still messy. A cleaner version would be something like:

```bash
if grep -q "Warning:" "$LOGFILE"; then
mail -s "Lynis Security Warning on $KensOffice" root < "$LOGFILE"
fi
```

(Make sure `$KensOffice` is properly set earlier in the script or hardcode a hostname.)

After changes, make the script executable (`chmod +x /usr/local/bin/lynis_cron.sh`) and test it manually first:

```bash
su - root -c /usr/local/bin/lynis_cron.sh
```

That should get rid of the error.
 
Back
Top