当我从 ( ) cronjob 调用脚本时,root
它会失败并显示消息“未找到 ipset”。以下是有问题的脚本行:
for i in $(cat /etc/cn.zone); do ipset -A china $i; done
脚本中之前的一些行调用了此命令:
ipset -N china hash:net
因此,所讨论的 ipset 实际上已经被创建了。
如果我从 root 的主目录运行此脚本,它可以完美运行。
知道什么可能导致错误吗?
答案1
当作为 cron 作业运行时,您的脚本看不到您的环境变量。
我从 () cronjob 调用一个脚本
root
,但脚本失败并显示“未找到 ipset”消息...
您是否将此脚本作为 Bash 脚本运行;目前大多数 shell 脚本都是这样的?
如果是这样,那么将脚本的第一行从
#!/bin/bash
对此:
#!/bin/bash -l
添加-l
告诉 Bash 像被调用为登录 shell 一样运行。如果 Bash 脚本通过该 cron 作业中的登录 shell 运行,则通常通过登录 shell 设置的所有环境变量(以及其他项目)都将可用于该 Bash 脚本,从而允许ipset
按预期运行。
您可以使用的另一个技巧是which
在 Bash 变量中使用这样的技巧;您显然正在使用它,$(cat /etc/cn.zone)
因此机制类似:
$(which ipset)
然后在脚本中将您的行更改为:
for i in $(cat /etc/cn.zone); do $(which ipset) -A china $i; done
这样做的目的是——通过使用which
——为脚本提供完整路径ipset
(类似于/sbin/ipset
),无论你在哪个系统上运行它。然后通过将其设置为解析变量,$()
脚本本身就可以运行它。
但是由于您ipset
在脚本的其他地方使用了该方法,因此我建议(如果您使用此which
方法)重构脚本以将ipset
其设置为脚本顶部附近的变量:
ipset_bin=$(which ipset);
然后像这样调用命令:
$ipset_bin -N china hash:net
和这个:
for i in $(cat /etc/cn.zone); do $ipset_bin -A china $i; done
答案2
您的 shell 知道在哪里找到可执行文件,例如ipset
通过查看您的PATH
,它由您的环境设置,但cron
不共享相同的环境。
将其添加到(或您的脚本)的顶部crontab
应该会告诉它在哪里找到命令,正如您所期望的那样:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin