手动 crontab 和 运行 脚本之间的不同结果

different results between crontab and running script manually

我有一个 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 用户的 运行,因此它具有扫描整个网络所需的所有提升。

首先,你的 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

您的脚本缺少 shebang,因此它可能 运行 具有不同的 shell,具体取决于 crontab 或手动启动。

在脚本的第一行添加以下内容(如果需要,将 bash 替换为当前用户 shell):

#!/usr/bin/env bash

不要使用 /bin/bash,因为它的便携性不如 /usr/bin/env bash。

此外,crontab 运行s 将没有 PATH 变量。 使用以下命令打印您的路径变量:

echo $PATH

并将其添加为脚本的第二行,例如:

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

这应该确保您的脚本 运行s 在与 运行 通过 crontab 或手动时相同的环境中。