我编写了一个 Linux shell 程序来保持我的服务器信息更新。它的工作原理是使用最新的服务器信息创建一个新文件并将其与旧文件进行比较。但是,程序有时无法找到新文件。
now=$(cd $(dirname $0);pwd)
while [ ! -s "$now/../var/service.info.temp" ];do
sh "$now/get_service_info.sh" > "$now/../var/service.info.temp"
done
diff "$now/../var/service.info.temp" "$now/../var/service.info" >> "$now/../var/update.log" 2>> "$now/../var/update.log"
if [ $? -ne 0 ];then
sh "$now/send_service_info.sh" >> "$now/../var/update.log" 2>> "$now/../var/update.log"
cp "$now/../var/service.info.temp" "$now/../var/service.info"
fi
rm "$now/../var/service.info.temp"
我在
update.log
中发现的内容(cat
在send_service_info.sh
中被称为):
diff: /home/(my user name)/network/sh/../var/service.info.temp: No such file or directory
cat: /home/(my user name)/network/sh/../var/service.info.temp: No such file or directory
该程序由 cron 每分钟运行一次:
# one line of my crontab
* * * * * sh /home/(my user name)/network/sh/check_update.sh
我已经多次手动运行该程序,但当我这样做时它从未抛出上述错误。我只是通过日志找到的,并且发错了邮件。这个问题并不是每次都会发生,只有在 cron 运行时每 20 分钟到一小时才会发生一次。
程序中新添加了
while
循环来克服文件问题,但是不起作用。我仍然得到相同的结果。我还尝试了get_service_info.sh
中的制造延迟(由sleep 5s
),但当我手动运行时它仍然运行良好。我已将 get_servive_info.sh
简化为只有一个命令 hostname -I
,但问题仍然存在。
我的Linux系统是Android手机上UserLand运行的Ubuntu 22.04.3 LTS(Linux 4.14.141+)(尚未root)。我使用
ssh
连接到它并完成我的工作。我还发现,如果屏幕在凌晨 0 点到 6 点之间关闭,我的系统将会暂停,这可能与上述问题有关(在这两种情况下,cron
都没有响应)。
根据建议,我将程序代码更改为:
set -e
now=$(cd $(dirname $0);pwd)
get="$now/get_service_info.sh"
send="$now/send_service_info.sh"
var="$now/../var"
log="$var/update.log"
origin="$var/service.info"
temp="$var/service.info.temp.$$"
exec >> $log 2>> $log
while [ ! -s $temp ];do
sh $get > $temp
done
if [[ $(diff $origin $temp) ]];then
sh $send
cp $temp $origin
fi
rm $temp
如果有效,我会尽快写反馈。
如果您的脚本出于某种原因需要大约 1 分钟来执行,则存在竞争条件:在旧进程完成之前,cron 将启动一个新进程,然后
rm
旧进程可能会在 之前删除该文件新进程的diff
被执行。
我建议您创建一个特定于进程的临时文件:
service_info_temp=$now/../var/service.info.temp.$$
while [ ! -s "$service_info_temp" ]
do
....