Detecting Changed Files

This page is showing a generic answer.
To see a more detailed answer customized for you, type your domain name here:

We’ve been asked if it’s possible to be notified when any files change on a website. This gives an extra layer of defense against “hackers” who might modify a site if they somehow gain access to it.

Technically advanced users can do this if you’re familiar with cron jobs. The idea is to add a script to your site that detects any changes within a certain period, then run that script file every so often.

Here’s an example script that checks for changes to any PHP files on your site:

#!/bin/bash

# Change the next line to the email address that should be notified
ADDRESS=address@example.com

DIRECTORY=/var/www/html/ex/example.com/
MINUTES=61
CHANGED=`find $DIRECTORY \( -cmin -$MINUTES -or -mmin -$MINUTES -or -amin -$MINUTES \) -name '*.php'`
if [ -n "$CHANGED" ]; then
  DOMAIN=`id -u -n`
  NOTE="These PHP files have changed on $DOMAIN within the last $MINUTES minutes:"
  /bin/echo -e "$NOTE\n\n$CHANGED" | mail -s "Changed files on $DOMAIN" $ADDRESS
fi

You would edit the ADDRESS and save this as a file in your home directory as detect-changes.sh. Then add this cron job to run it every hour:

59 * * * * /bin/bash /home/ex/example.com/detect-changes.sh

Then the ADDRESS specified will receive an email message each time any PHP files have changed in the previous hour.

Using this with WP Super Cache

If you use WP Super Cache or a similar plugin, the script above will detect modifications to cached files, which may be annoying. If so, you can exclude them by adding | egrep -v /wp-content/cache/ to the “CHANGED=” line, so the whole script will look like this:

#!/bin/bash

# Change the next line to the email address that should be notified
ADDRESS=address@example.com

DIRECTORY=/var/www/html/ex/example.com/
MINUTES=61
CHANGED=`find $DIRECTORY \( -cmin -$MINUTES -or -mmin -$MINUTES -or -amin -$MINUTES \) -name '*.php' | egrep -v /wp-content/cache/`
if [ -n "$CHANGED" ]; then
  DOMAIN=`id -u -n`
  NOTE="These PHP files have changed on $DOMAIN within the last $MINUTES minutes:"
  /bin/echo -e "$NOTE\n\n$CHANGED" | mail -s "Changed files on $DOMAIN" $ADDRESS
fi

Technical notes

  • This example script would run every hour, but report changes from the last 61 minutes, so you’d occasionally be notified twice about a change. This ensures that it won‘t miss anything if the cron job sometimes takes a few seconds longer to run than it did the previous hour.
  • It’s wise to check all three Unix file modification times (cmin, mmin, and amin), because the cmin and mmin are sometimes “reset” by hackers.
  • It’s theoretically possible for hackers to delete this cron job if they gain full access to your site. In our experience, “hackers” rarely make cron changes, but because it’s possible, this should be considered part of a layered security solution, not as the sole defense against otherwise poor security practices.