如何解决在不使用子shell的情况下检测当前脚本是否已更改? 并启动新脚本
是否可以在不使用 subshell 命令的情况下让正在运行的脚本查看它是否已更改/更新?
如果已更新,则启动新脚本并杀死旧脚本。
以前我为它使用了一个单独的文件,所以当我创建文件时,脚本检测到它。但是,如果您正在运行脚本的多个实例,这可能会非常混乱
if [[ -f /mnt/g/update.tt ]]; then script.sh 2 && kill $$ ;fi
这个函数将被放置在一个大约需要 0.8 秒的循环中,这就是为什么没有子 shell 是重要的。
解决方法
也许:
age_of_script=$(( $(date +%s) - $(stat -c %Y "$0") ))
running_time=$SECONDS
if (( running_time > age_of_script )); then
# script has been updated since I started running
exec "$0" 2
fi
正如 that other guy
评论的那样,使用 exec
来替换当前进程。
使用 bash 4.3+,您可以使用:
bash_root=${BASH%/bin/bash}
if [[ -d "$bash_root/lib/bash" ]]; then
enable -f "$bash_root/lib/bash/finfo" finfo
file_age() { echo $(( $(printf '%(%s)T' -1) - $(finfo -m "$1") )); }
else
file_age() { echo $(( $(printf '%(%s)T' -1) - $(stat -c %Y "$1") )); }
fi
age_of_script=$(file_age "$0")
仍然使用 subshell 进行命令替换,但如果您的 bash 构建具有可加载模块,您可能不需要使用任何外部工具
对于后代,stat
与可加载 finfo
的快速基准
$ file_age() { echo $(( $(printf '%(%s)T' -1) - $(stat -c %Y "$1") )); }
$ time for ((i=0; i<1000; i++)); do x=$(file_age /etc/hosts); done
real 0m14.750s
user 0m2.288s
sys 0m4.139s
$ file_age() { echo $(( $(printf '%(%s)T' -1) - $(finfo -m "$1") )); }
$ time for ((i=0; i<1000; i++)); do x=$(file_age /etc/hosts); done
real 0m7.162s
user 0m1.148s
sys 0m2.085s
,
自动更新脚本的最佳和最简单的方法是将脚本修改戳与您在脚本开头创建的临时文件进行比较。
scriptupdate=$(mktemp)
只要确保你只运行一次 mktemp,并且在任何循环之外,否则脚本会一遍又一遍地更新控制文件,使其比脚本更新..
那你只需要对比一下脚本文件和临时文件,看看脚本是不是从不,然后重启脚本
if [[ $0 -nt $scriptupdate ]]; then
exec $0 $@
fi
Exec
用新脚本替换正在运行的脚本
$0
是当前脚本的完整路径和名称
$@
将参数传递给新的运行。
您可以创建一个参考文件,然后继续检查当前脚本是否比该参考新:
#!/bin/bash
reference=$(mktemp)
thisscript="${BASH_SOURCE[0]}"
trap 'rm "$reference"' EXIT
printf '\nStarting\n'
while true
do
if [[ "$thisscript" -nt "$reference" ]]
then
rm "$reference"
exec "$thisscript"
fi
printf "beep boop "
read -t 0.8
done
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。