Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am getting the following error email every week. It appears to be a problem with either cron, logrotate, or denyhosts. I'm not sure which.

Subject: Cron <root@vps> test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )

test: 91: /etc/hosts.deny: unexpected operator

Any suggestions?

share|improve this question
I edited my answer to suggest a command to aid in the search. – Dennis Williamson Sep 30 '09 at 14:35

/etc/logrotate.d/denyhosts is very short and doesn't seem to me to use test:

Yes, but it has this:

/etc/init.d/denyhosts restart > /dev/null

and that script does stuff like

    HOSTS_DENY=$(grep ^HOSTS_DENY $CONFIG  | cut -d = -f 2)
    test -e $HOSTS_DENY || touch $HOSTS_DENY

assuming the script is correct, if I had to guess I'd say your HOSTS_DENY line in your config file is malformed somehow.

Fortunately, we don't have to guess, this command will show you exactly where the error is coming from:

/bin/sh -x /etc/init.d/denyhosts restart
share|improve this answer
Hello thanks for the help Justin, but I tried that command and I just saw a bunch of + signs. I wasn't able to find any errors. – Unknown Jan 4 '10 at 2:54
What exactly did it print? The restarting of denyhosts has to be what is generating that error. maybe in the logrotate file change the line to "/bin/sh -x /etc/init.d/denyhosts restart" from "/etc/init.d/denyhosts restart > /dev/null" that might shed some more light on where the problem is coming from. it wouldn't do anything for a week unless you change 'weekly' to 'daily' though... – Justin Jan 4 '10 at 3:06

To me it looks like there is an error in line 91 of /etc/hosts.deny or /etc/cron.daily/logrotate.

Make sure entries in hosts.deny are formatted validly.

share|improve this answer
My hosts.deny is empty and my logrotate file is this: #!/bin/sh test -x /usr/sbin/logrotate || exit 0 4 /usr/sbin/logrotate /etc/logrotate.conf – Unknown Sep 29 '09 at 19:50

My bet is that somewhere there's a sh script with a double equal sign ("==") in a test command instead of a single one ("="). Bash's builtin test allows == or =, but the Bourne shell (at least dash on Ubuntu) only allows =. Also, my /usr/bin/test only allows the single equal. But see the bottom of this answer for other examples that produce this same error.

I would look in logrotate.conf and see if it has a line 91 that might have that problem.

If, for some reason, you want to recreate the error message for testing:

Create a file, let's call it "a", with the following contents:

echo 'In script "a"'
test $f == "foo"

Now do:

sh a

You should get:

In script "a"
test: 3: /etc/hosts.deny: unexpected operator

You can also reproduce a similar error using any of the following:

sh -c "test /etc/hosts.deny +"
sh -c "test /etc/hosts.deny -"
sh -c "test /etc/hosts.deny /"
sh -c "test /etc/hosts.deny *"

Edit: Try the following to narrow down your search:

$ su -
$ find /etc -type f | xargs awk 'FNR==91 && /test/ {print FILENAME, $0}'

You will su to root, then run the find/awk command. It will show you the filenames and line 91 of the file if the word "test" appears on that line, for each file under /etc. Then you can look for operators that are incorrect.

share|improve this answer
My entire logrotate.conf file is only 32 lines long: – Unknown Sep 30 '09 at 7:31
@Dennis, I just tried that. No results were found. – Unknown Oct 5 '09 at 4:44
Then I would broaden the search and change the /etc in the find command to / – Dennis Williamson Oct 5 '09 at 5:08
It might be better to user null-terminated filenames, too: find / -type f -print0 | xargs -0 awk 'FNR==91 && /test/ {print FILENAME, $0}' – Dennis Williamson Oct 5 '09 at 5:19
This will be faster: find / -type f -print0 | xargs -0 awk 'FNR==91 && /test/ {print FILENAME, $0} FNR==92 {exit}' – Dennis Williamson Oct 5 '09 at 5:33

How about in /etc/logrotate.d/denyhosts ?

share|improve this answer
Here is the file: its only 10 lines long. – Unknown Oct 5 '09 at 4:42

/etd/logrotate.d/denyhosts is very short and doesn't seem to me to use test:

/var/log/denyhosts {
create 0640 root root
rotate 7
/etc/init.d/denyhosts restart > /dev/null

The only instance of "test" on line 91 of a file in /etc is in an unrelated file.

The cron.daily/logrotate job point at /usr/sbin/logrotate (a binary file) -- if the bug is in there, where could I check the source code?

share|improve this answer

Just for sanity you may want to use:

foo:~# which test

to see that the test program is what you think it is. One defensive programming method is to use the full path to commands in cron jobs. This ensures the proper binary is called and prevents an attacker from substituting another similarly named command earlier in your PATH.

share|improve this answer
Yep, my test is at /usr/bin/test – Unknown Jan 4 '10 at 2:56

Here's some troubleshooting tips. I think Justin is absolutely on the right track. The problem is probably in your denyhosts setup. But let's track it down.

You're getting the error originally from logrotate. So run logrotate:

logrotate /etc/logrotate.conf

Assuming you get an error, at least you've got a reproducible case. Now let's see if the problem is in logrotate or denyhosts. Let's use the denyhosts command we saw in logrotate:

/etc/init.d/denyhosts restart > /dev/null

If that gives you an error, you're really close to tracking this down. Try taking off the "> /dev/null" from the end of the line to get more information. Post the output here for help.

However, if neither of the above two tricks got you an error, but you're still getting the error from the cron jobs, you've got a problem. Waiting a week between attempts to debug something sucks.

Add another line to your /etc/crontab. Copy the cron.weekly line, and paste it below all the other lines. Then edit it so all the "when" entries are asterisks.

47  6   *   *   7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )

Change that to:

*   *   *   *   *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )

Then it will run once a minute all day long, all week long. This is obviously not something you'd want to leave in there, but it can be helpful in troubleshooting.

In cases where you see errors in cron jobs that you don't see when running the scripts from the command-line, it's almost always a difference in your environment. Check the path first.

share|improve this answer

I had this same issue after uninstalling the denyhosts package. Confirm that you actually have the package installed:

mlambie@prime:~$ dpkg -l | grep denyhosts
rc  denyhosts                              2.6-6.1ubuntu1                    a utility to help sys admins thwart SSH crac

You'll have "ii" as the first two characters if the package is installed. For example, I have openssh-server installed and get this result:

mlambie@prime:~$ dpkg -l | grep openssh-server
ii  openssh-server                         1:5.3p1-3ubuntu7                  secure shell (SSH) server, for secure access

In my case, I think the logrotate configuration was not successfully removed when the package was removed, so I manually rm'd it.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.