我有一个如下所示的 bash 脚本:
#!/bin/sh
PID=`ps faux | grep libt | awk 'NR==2{print $2}'`
STATUS=`ps faux | grep libt | awk 'NR==2{print $1}'`
if [ "$STATUS" = "ec2-user" ]; then
echo "libt already killed"
else
sudo kill $PID
echo "libt was killed"
fi
sleep 5
cd /home/ec2-user/libt
sudo ./libt
我已将此文件保存为 restart.sh,当我像 ./restart.sh 一样运行它时,它会执行其应有的操作(终止 libt 进程并重新启动它)。但是,现在我正尝试使用 cron 来自动化该过程。因此,我创建了一个 cron 作业,希望每 6 小时运行一次,如下所示
0 */6 * * * /home/ec2-user/restart.sh
当我运行“crontab -l”时,我可以看到此打印,所以我知道它已被正确添加。我应该提到,该服务没有重新启动的能力,(如“service ... restart”)需要找到进程 ID,然后终止进程 ID,然后运行启动脚本。
我发现这个 cronjob 不起作用,我登录到机器上,通过查看日志可以发现没有发生重新启动。我做错了什么?我可以做什么来排除故障?
任何建议都会有帮助,这是我的第一个 cron 作业:) 谢谢!
答案1
除了允许用户运行/bin/kill
而libt
无需密码之外,您可能还需要visiblepw
将Defaults
sudoers文件例如
Defaults env_reset, visiblepw
和
#allow user to run kill with no password entry
user ALL=NOPASSWD: /bin/kill, /home/ec2-user/libt/libt
答案2
据推测,您使用这些行的目的是为了避免匹配grep
输出中的命令ps
:
PID=`ps faux | grep libt | awk 'NR==2{print $2}'`
STATUS=`ps faux | grep libt | awk 'NR==2{print $1}'`
你不能保证第二行就是你想要的。你应该grep
使用一个常用技巧来消除:
ps faux | grep [l]ibt
通过将字符括在方括号中,grep
会查找“libt”而不是文字“[l]ibt”,因为它将括号中的字符解释为列表。
你应该用于$()
命令替换而不是反引号。它们更易读,也更容易嵌套。
您还可以通过一次调用获取用户名和 PID,以ps
减少出现竞争条件的可能性,但您实际上并不需要用户名,因为您已经知道了。您只需要知道该进程是否正在运行。
但是,仍然有误报的可能性。如果可以,您应该使用pgrep
和pkill
。
#!/bin/sh
PID=$(pgrep -U ec2-user libt 2>/dev/null)
if [ $? = 0 ]
then
kill $PID
echo "libt was killed"
else
echo "libt already killed"
fi
sleep 5
/home/ec2-user/libt/libt
请参见流程管理了解更多信息。
答案3
sudo
在 cron 作业中不起作用;它会提示输入密码,因为您注销时不会保持其信号文件处于活动状态。考虑将其安装在 的root
crontab 中,而不是您自己的 crontab 中。