我已经编写了一个Linuxshell 程序来更新我的服务器信息.它的工作原理是使用最新的服务器信息创建一个新文件,并将其与旧文件进行比较.但是,程序有时找不到新文件.

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中发现了什么(catsend_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

我已经手动运行了程序很多次,但当我这样做时,它从来没有抛出上面的错误.我只是通过日志(log)找到了它,并错误地发送了邮箱.这个问题并不是每次都会发生,在由cron运行时,它只会每隔20分钟到一小时发生一次.

程序中的while循环是新添加的,以克服文件问题,但它不起作用.我还是得到了同样的结果.我也try 了在get_service_info.sh中制造延迟(sleep 5s),但当我手动操作时,它仍然运行得很好.我已经将get_servive_info.sh简化为只有一个命令hostname -I,但问题仍然存在.

我的Linux系统是Ubuntu 22.04.3 LTS(Linux 4.14.141+),由Userland在Android手机上运行(还没有根).我用ssh连接它,做我的工作.我还发现,如果屏幕在0AM和6AM之间关闭,我的系统将暂停,这可能与上面的问题有关(在这两种情况下,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

我想我已经等待了足够长的时间,它不会再次抛出错误.这是因为执行时间很长.我忽略这一点,因为当我使用SSH连接测试它时,该程序只需要不到1秒的时间.也许当我的系统自动运行时,由于省电模式或其他原因,它会变得慢得多.最后,为了提高可读性和健壮性,下面是更改后的代码:

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 ! test -s "$temp" ; do
    sh "$get" > "$temp"
done
if ! diff -q "$origin" "$temp" > /dev/null ; then
    sh "$send" "$temp"
    cp "$temp" "$origin"
fi
rm "$temp"

推荐答案

如果您的脚本出于某种原因花费了大约1分钟来执行,那么您有一个竞争条件:在旧进程完成之前,cron将启动一个新进程,然后rm个旧进程可能就在执行新进程的第diff个进程之前删除该文件.

我建议你创建一个特定于进程的临时文件:

service_info_temp=$now/../var/service.info.temp.$$
while [ ! -s "$service_info_temp" ]
do
  ....

Linux相关问答推荐

Bash脚本用于在远程工作后关闭用户会话

如何将netcdf文件列表中的特定变量添加到不同的文件中?

无法分析nasm中的单词

如何从大页分配标准数组内存

如何使用 gdb 调试堆栈分段错误?

替换前 3 个字符范围内的所有整数

如何使用netcat为DPDK实例提供输入?

使用 sed 或 awk 在 linux 中将第一行中的一个单词替换为第二行中的另一个单词

如何在 Linux 上使用 -grep 构建过滤间隔的命令

/usr/local/bin/ 中Collection的权限被拒绝

Java 8 上的 SQL Server JDBC 错误:驱动程序无法使用安全套接字层 (SSL) 加密建立与 SQL Server 的安全连接

使用 RPATH 但不使用 RUNPATH?

通过 VM 的 Centos - 镜像列表中没有 URL

Linux 和 I/O 完成端口?

与交换空间相关的链接器性能?

polkitd未注册身份验证代理的解释

'&&' 与 '&' 与 Bash 中的 'test' 命令

如何设置errno值?

如何链接到 GCC 中特定版本的共享库

如何将文件夹中的文件列表发送到Linux中的txt文件