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

Posted

技术标签:

【中文标题】crontab 和手动运行脚本的结果不同【英文标题】:different results between crontab and running script manually 【发布时间】:2017-01-21 14:50:15 【问题描述】:

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

【问题讨论】:

您是否使用sudo 尝试过您的脚本,看看是cron 用户还是root 用户产生了影响? 我实际上是从 sudo cron 和常规 cron 运行脚本,它们都产生了相同的错误输出。我使用 sudo 和常规模式手动运行了我的脚本,它们产生了相同的正确输出。 检查环境变量差异。我会做grep -Eo '192\.168\.0\.1,3\[0-9]'(引用) 尝试尝试...由于某种原因出现此错误:“grep: invalid repeat count(s)” 你还有其他写给new.txt的cronjobs吗? 【参考方案1】:

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

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

#!/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 或手动运行时在相同的环境中运行。

【讨论】:

谢谢!它现在可以工作了,你能给我提供一个链接或扩展为什么 /bin/bash 不如 /usr/bin/env bash 可移植 /bin/bash 是特定于 linux 的,而 /usr/bin/env 应该存在于所有 unix 系统上。请参阅***.com/questions/16365130/… 了解更多信息。【参考方案2】:

首先,你的 grep 正则表达式有几个问题:

    重复计数 (1,3) 适用于其前一个原子(即“.”)而不是下一个原子(即“[0-9]”)。

    正则表达式中未转义的点 ('.') 匹配任何字符,从而隐藏了先前的错误。您的正则表达式 (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

【讨论】:

感谢所有这些建议,我从来没有意识到 tmpfile 的东西要好得多,尤其是因为 nmap 确实需要相对较长的时间来运行。并感谢您的正则表达式更正

以上是关于crontab 和手动运行脚本的结果不同的主要内容,如果未能解决你的问题,请参考以下文章

Bash 脚本手动运行,但在 crontab 上失败

crontab linux定时运行程序

Bash脚本手动运行,但在crontab上失败

crontab定时任务详解

crontab不执行sh脚本 手动可以执行crontab执行失败【亲测】

crontab 定时任务