разные результаты между crontab и запуском скрипта вручную

У меня есть скрипт bash, который делает это:

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

Сканирует сеть и добавляет результаты в файл network_log с отметкой времени. После запуска вручную файл network_log выглядит так:

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

192.168.0.1
192.168.0.2 
192.168.0.45

тогда как cronjobs производят следующие выходные данные в моем файле network_log:

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

без результатов ip. Примечание: cronjob запускается от пользователя root, поэтому у него есть все права, необходимые для сканирования всей сети.


person carrots    schedule 13.09.2016    source источник
comment
Вы пробовали свой сценарий с sudo, чтобы увидеть, имеет ли значение пользователь cron или root?   -  person Jean-François Fabre    schedule 14.09.2016
comment
На самом деле я запускаю скрипт как из sudo cron, так и из обычного cron, и оба они выдают один и тот же неверный вывод. Я запустил свой скрипт вручную, используя sudo и обычный режим, они выдают одинаковый правильный вывод.   -  person carrots    schedule 14.09.2016
comment
проверьте различия переменных среды. А я бы сделал grep -Eo '192\.168\.0\.{1,3\}[0-9]' (цитирую)   -  person Jean-François Fabre    schedule 14.09.2016
comment
пытаюсь попробовать это... по какой-то причине получаю эту ошибку: grep: неверный счетчик повторений   -  person carrots    schedule 14.09.2016
comment
Вы помещаете эти команды напрямую в crontab или просто вызываете скрипт?   -  person Leon    schedule 14.09.2016
comment
У вас есть другие cronjobs, которые пишут в new.txt?   -  person Leon    schedule 14.09.2016
comment
Проверьте путь к nmap с помощью type map или which nmap и укажите полный путь в своем скрипте.   -  person Mark Setchell    schedule 14.09.2016
comment
@Leon только что увидел это сейчас, я вызываю скрипт из cronjob, и никто другой не пишет в new.txt   -  person carrots    schedule 22.09.2016


Ответы (2)


Во-первых, в регулярном выражении grep есть пара проблем:

  1. Счетчик повторений ({1,3}) применяется к предыдущему атому (т. е. «.»), а не к следующему (т. е. «[0-9]»).
  2. Неэкранированная точка ('.') в регулярном выражении соответствует любому символу, который скрывает предыдущую ошибку. Ваше регулярное выражение (192.168.0.{1,3}[0-9]) соответствует 192.168.0.123 следующим образом:

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

    Но он также будет соответствовать следующим строкам:

    192116810abc1
    192.681.012.9
    

Правильное регулярное выражение должно быть 192\.168\.0\.[0-9]{1,3} и оно должно быть заключено в кавычки, чтобы bash передал его в grep буквально:

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

Тем не менее, неправильное регулярное выражение вряд ли может объяснить проблему, с которой вы сталкиваетесь при работе с cron.

Одной из проблем может быть то, что вы используете фиксированное имя new.txt для своего временного файла. Если вы сделаете то же самое в других своих сценариях или если вы настроите это задание cron для запуска каждую минуту, в то время как для завершения сканирования сети требуется nmap больше минуты, то new.txt может быть перезаписан в неподходящее время.

Пожалуйста, исправьте ваш скрипт следующим образом и проверьте, исчезла ли проблема:

#!/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
person Leon    schedule 14.09.2016
comment
Спасибо за все эти предложения, я бы никогда не понял, что tmpfile намного лучше, тем более что nmap требует относительно много времени для запуска. & спасибо за исправления регулярных выражений - person carrots; 22.09.2016

В вашем скрипте отсутствует shebang, поэтому он может работать с разными оболочками в зависимости от crontab или ручного запуска.

Добавьте следующую строку в качестве первой строки в ваш скрипт (при необходимости замените bash на вашу текущую пользовательскую оболочку):

#!/usr/bin/env bash

Не используйте /bin/bash, поскольку он менее переносим, ​​чем /usr/bin/env bash.

Кроме того, запуски crontab не будут иметь переменной PATH. Распечатайте свою переменную пути с помощью:

echo $PATH

И добавьте его как вторую строку вашего скрипта, например:

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

Это должно гарантировать, что ваш скрипт запускается в той же среде при запуске с помощью crontab или вручную.

person Orsiris de Jong    schedule 14.09.2016
comment
Спасибо за это! Теперь это работает, не могли бы вы дать мне ссылку или объяснить, почему /bin/bash менее переносим, ​​чем /usr/bin/env bash - person carrots; 22.09.2016
comment
/bin/bash специфичен для Linux, тогда как /usr/bin/env должен существовать во всех системах unix. См. stackoverflow.com/questions/16365130/ для mre. - person Orsiris de Jong; 23.09.2016