4

I have a bash script that does this:

nmap -sn 192.168.0.1-255 | grep -Eo 192.168.0.{1,3\}[0-9] > new.txt
date >> network_log
echo ---------------------------- >> network_log
cat new.txt >> network_log

Scans the network, and appends results to file network_log with a timestamp. After running it manually, the network_log file looks like this:

Tue 13 Sep 2016 11:22:23 EDT 
---------------------------- 

192.168.0.1
192.168.0.2 
192.168.0.45

whereas the cronjobs produce the following outputs in my network_log file:

Tue Sep 13 17:46:00 EDT 2016
----------------------------

with no ip results. Note: the cronjob is running from root user so it has all the elevation it needs to scan the entire network.

carrots
  • 785
  • 1
  • 8
  • 19

2 Answers2

6

Your script lacks a shebang, so it might run with different shells depending on a crontab or manual launch.

Add the following as first line in your script (replace bash with your current user shell if needed):

#!/usr/bin/env bash

Don't use /bin/bash as it's less portable than /usr/bin/env bash.

Also, crontab runs won't have the PATH variable. Print your path variable with:

echo $PATH

And add it as second line of your script like:

#!/usr/bin/env bash
PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin

This should ensure that your script runs in the same environment when run by crontab or manually.

Orsiris de Jong
  • 2,819
  • 1
  • 26
  • 48
  • Thanks for this! It works now, could you provide me with a link or expand on why /bin/bash is less portable than /usr/bin/env bash – carrots Sep 22 '16 at 00:51
  • /bin/bash is linux specific whereas /usr/bin/env is supposed to exist on all unix systems. See http://stackoverflow.com/questions/16365130/the-difference-between-usr-bin-env-bash-and-usr-bin-bash for mre. – Orsiris de Jong Sep 23 '16 at 06:15
3

First of all, there are a couple of problems in your grep regular expression:

  1. The repetition count ({1,3}) applies to its preceding atom (i.e. '.') rather than the next one (i.e. '[0-9]').
  2. An unescaped dot ('.') in the regex matches any character, which hides the previous error. Your regex (192.168.0.{1,3}[0-9]) matches 192.168.0.123 as follows:

    192.168.0 matches 192.168.0
    .{1,3}    matches .12
    [0-9]     matches 3
    

    But it would also match the following strings:

    192116810abc1
    192.681.012.9
    

The correct regex must be 192\.168\.0\.[0-9]{1,3} and it must be quoted, so that bash passes it to grep literally:

grep -Eo '192\.168\.0\.[0-9]{1,3}'

Yet, the wrong regex can hardly explain the problem your are seeing with cron.

One problem may be that you are using a fixed name new.txt for your temporary file. If you do the same in your other scripts, or if you set up this cron job to run every minute while it takes nmap more than a minute to complete scanning the network, then new.txt may be overwritten at the wrong time.

Please fix your script as follows and check if the problem disappears:

#!/bin/bash

tmpfile="$(mktemp)"
trap "rm $tmpfile" EXIT
nmap -sn 192.168.0.1-255 | grep -Eo '192\.168\.0\.[0-9]{1,3}' > "$tmpfile"
date >> network_log
echo ---------------------------- >> network_log
cat "$tmpfile" >> network_log
Leon
  • 31,443
  • 4
  • 72
  • 97
  • Thank-you for all these suggestions, I would have never realized the tmpfile thing is alot better, especially since nmap does take a relatively long time to run. & thankyou for regex corrections – carrots Sep 22 '16 at 00:55