qinglong/shell/update.sh
whyour 5b3687f7b6 全新青龙2.0 (#65)
* 重构shell (#17)

* 更新正则

* 更新update命令

* 移除测试代码

* 重构删除日志命令

* 更新entrypoint

* 更新dockerfile

* 完善shell调用

* 修复share shell引用

* 修复entrypoint

* 修复share shell

* 修复share.sh

* 修改依赖重装逻辑

* 更新docker entrypoint

* curl 使用静默模式

* 更新ql raw

* 修复添加单个任务

* 修复shell语法

* 添加定时任务进程

* 更新默认定时任务

* 更新定时任务重启schedule

* 更新青龙重启逻辑

* 修复定时任务列表创建

* 修复schedule进程

* 修复entrypoint

* 更新task命令

* pm2 restart替换成reload

* 修复task命令参数引入

* 完善ql repo命令

* 修复update.sh

* 更新ql repo命令

* ql repo添加登录验证,修复package.json示例

* 修复定时任务命令补全

* 修改默认cron端口

* 修复cron日志弹框异常

* 修改cron新建label

* 修复ql repo命令

* 修复cron格式验证

* 修改日志目录格式

* 修改青龙remote url

* 修复添加定时cron匹配

* 添加定时任务超时时间设置

* 暂时移除timeout命令

* 恢复定时任务timeout

* 修复cookie.sh引用

* 修复shell变量自加

* 修复ck更新状态同步

* 增加tg bot测试,修改增删任务通知

* 修复shell函数返回值

* 修改添加任务日志打印

* 修改entrypoint日志

* 修复api日志打印

* 修改api日志打印

* 定时任务支持批量启用禁用删除运行

* 修改cron管理操作按钮响应样式

* 更新bot启动脚本

* 更新bot启动脚本

* 增加timeout默认值,修改session管理逻辑

* 更新config示例和通知日志

* 更新bot.sh

* 更新启动bot命令

* 更新启动bot命令

* 修复task运行参数合并

* 增加停止定时任务功能

* 修复停止定时任务api

* 更新停止定时任务日志

* 更新停止任务日志

* 修复删除cron api

* 更新删除cron通知文本

* 更新命令提示

* 更新bot启动脚本
2021-05-10 20:47:23 +08:00

401 lines
14 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# 导入通用变量与函数
dir_shell=/ql/shell
. $dir_shell/share.sh
. $dir_shell/api.sh
send_mark=$dir_shell/send_mark
get_token
## 重置仓库remote urldocker专用$1要重置的目录$2要重置为的网址
reset_romote_url() {
local dir_current=$(pwd)
local dir_work=$1
local url=$2
if [ -d "$dir_work/.git" ]; then
cd $dir_work
git remote set-url origin $url >/dev/null
git reset --hard >/dev/null
cd $dir_current
fi
}
## 克隆脚本,$1仓库地址$2仓库保存路径$3分支可省略
git_clone_scripts() {
local url=$1
local dir=$2
local branch=$3
[[ $branch ]] && local cmd="-b $branch "
echo -e "开始克隆仓库 $url$dir\n"
git clone $cmd $url $dir
exit_status=$?
}
## 更新脚本,$1仓库保存路径
git_pull_scripts() {
local dir_current=$(pwd)
local dir_work=$1
cd $dir_work
echo -e "开始更新仓库:$dir_work\n"
git fetch --all
exit_status=$?
git reset --hard
git pull
cd $dir_current
}
## 检测cron的差异$1脚本清单文件路径$2cron任务清单文件路径$3增加任务清单文件路径$4删除任务清单文件路径
diff_cron() {
local list_scripts="$1"
local list_task="$2"
local list_add="$3"
local list_drop="$4"
if [ -s $list_task ]; then
grep -vwf $list_task $list_scripts >$list_add
elif [ ! -s $list_task ] && [ -s $list_scripts ]; then
cp -f $list_scripts $list_add
fi
if [ -s $list_scripts ]; then
grep -vwf $list_scripts $list_task >$list_drop
else
cp -f $list_task $list_drop
fi
}
## 检测配置文件版本
detect_config_version() {
## 识别出两个文件的版本号
ver_config_sample=$(grep " Version: " $file_config_sample | perl -pe "s|.+v((\d+\.?){3})|\1|")
[ -f $file_config_user ] && ver_config_user=$(grep " Version: " $file_config_user | perl -pe "s|.+v((\d+\.?){3})|\1|")
## 删除旧的发送记录文件
[ -f $send_mark ] && [[ $(cat $send_mark) != $ver_config_sample ]] && rm -f $send_mark
## 识别出更新日期和更新内容
update_date=$(grep " Date: " $file_config_sample | awk -F ": " '{print $2}')
update_content=$(grep " Update Content: " $file_config_sample | awk -F ": " '{print $2}')
## 如果是今天,并且版本号不一致,则发送通知
if [ -f $file_config_user ] && [[ $ver_config_user != $ver_config_sample ]] && [[ $update_date == $(date "+%Y-%m-%d") ]]; then
if [ ! -f $send_mark ]; then
local notify_title="配置文件更新通知"
local notify_content="更新日期: $update_date\n用户版本: $ver_config_user\n新的版本: $ver_config_sample\n更新内容: $update_content\n更新说明: 如需使用新功能请对照config.sample.sh将相关新参数手动增加到你自己的config.sh中否则请无视本消息。本消息只在该新版本配置文件更新当天发送一次。\n"
echo -e $notify_content
notify "$notify_title" "$notify_content"
[[ $? -eq 0 ]] && echo $ver_config_sample >$send_mark
fi
else
[ -f $send_mark ] && rm -f $send_mark
fi
}
## 输出是否有新的或失效的定时任务,$1新的或失效的任务清单文件路径$2新/失效
output_list_add_drop() {
local list=$1
local type=$2
if [ -s $list ]; then
echo -e "检测到有$type的定时任务\n"
cat $list
echo
fi
}
## 自动删除失效的脚本与定时任务需要1.AutoDelCron 设置为 true2.正常更新js脚本没有报错3.存在失效任务
## $1失效任务清单文件路径
del_cron() {
local list_drop=$1
local author=$2
local detail=""
local ids=""
echo -e "开始尝试自动删除失效的定时任务...\n"
for cron in $(cat $list_drop); do
local id=$(cat $list_crontab_user | grep -E "$cmd_task $cron$" | perl -pe "s|.*ID=(.*) $cmd_task $cron$|\1|" | xargs | sed 's/ /","/g')
if [[ $ids ]]; then
ids="$ids,\"$id\""
else
ids="\"$id\""
fi
cron_file="$dir_scripts/${cron}"
if [[ -f $cron_file ]]; then
cron_name=$(grep "new Env" $cron_file | awk -F "'|\"" '{print $2}' | head -1)
fi
[[ -z $cron_name ]] && cron_name="$cron"
detail="${detail}\n${cron_name}"
rm -f $cron_file
done
result=$(del_cron_api "$ids")
detail="${result}\n\n${detail}"
notify "删除失效任务通知" "$detail"
}
## 自动增加定时任务需要1.AutoAddCron 设置为 true2.正常更新js脚本没有报错3.存在新任务4.crontab.list存在并且不为空
## $1新任务清单文件路径
add_cron() {
local list_add=$1
local author=$2
echo -e "开始尝试自动添加定时任务...\n"
local detail=""
cd $dir_scripts
for file in $(cat $list_add); do
local file_name=${file/${author}\_/}
if [ -f $file ]; then
cron_line=$(
perl -ne "{
print if /.*([\d\*]*[\*-\/,\d]*[\d\*] ){4,5}[\d\*]*[\*-\/,\d]*[\d\*]( |,|\").*$file_name/
}" $file |
perl -pe "{
s|[^\d\*]*(([\d\*]*[\*-\/,\d]*[\d\*] ){4,5}[\d\*]*[\*-\/,\d]*[\d\*])( \|,\|\").*/?$file_name.*|\1|g;
s| | |g
}" | sort -u | head -1
)
cron_name=$(grep "new Env" $file | awk -F "'|\"" '{print $2}' | head -1)
[[ -z $cron_name ]] && cron_name="$file_name"
[[ -z $cron_line ]] && cron_line="0 6 * * *"
result=$(add_cron_api "$cron_line:$cmd_task $file:$cron_name")
echo -e "$result"
detail="${detail}\n${result}"
fi
done
notify "新增任务通知" "$detail"
}
## 更新仓库
update_repo() {
echo -e "--------------------------------------------------------------\n"
local url="$1"
local path="$2"
local blackword="$3"
local dependence="$4"
local urlTmp="${url%*/}"
local repoTmp="${urlTmp##*/}"
local repo="${repoTmp%.*}"
local tmp="${url%/*}"
local authorTmp1="${tmp##*/}"
local authorTmp2="${authorTmp1##*:}"
local author="${authorTmp2##*.}"
local repo_path="${dir_repo}/${author}_${repo}"
if [ -d ${repo_path}/.git ]; then
reset_romote_url ${repo_path} ${url}
git_pull_scripts ${repo_path}
else
git_clone_scripts ${url} ${repo_path}
fi
if [[ $exit_status -eq 0 ]]; then
echo -e "\n更新${repo_path}成功...\n"
else
echo -e "\n更新${repo_path}失败,请检查原因...\n"
fi
diff_scripts $repo_path $author $path $blackword $dependence
}
## 更新所有 raw 文件
update_raw() {
echo -e "--------------------------------------------------------------\n"
local raw_url="$1"
raw_file_name=$(echo ${raw_url} | awk -F "/" '{print $NF}')
echo -e "开始下载:${raw_url} \n\n保存路径$dir_raw/${raw_file_name}\n"
wget -q --no-check-certificate -O "$dir_raw/${raw_file_name}.new" ${raw_url}
if [[ $? -eq 0 ]]; then
mv "$dir_raw/${raw_file_name}.new" "$dir_raw/${raw_file_name}"
echo -e "下载 ${raw_file_name} 成功...\n"
cd $dir_raw
local filename="raw_${raw_file_name}"
local cron_id=$(cat $list_crontab_user | grep -E "$cmd_task $filename$" | perl -pe "s|.*ID=(.*) $cmd_task $filename$|\1|")
cp -f $raw_file_name $dir_scripts/${filename}
cron_line=$(
perl -ne "{
print if /.*([\d\*]*[\*-\/,\d]*[\d\*] ){4,5}[\d\*]*[\*-\/,\d]*[\d\*]( |,|\").*$raw_file_name/
}" $raw_file_name |
perl -pe "{
s|[^\d\*]*(([\d\*]*[\*-\/,\d]*[\d\*] ){4,5}[\d\*]*[\*-\/,\d]*[\d\*])( \|,\|\").*/?$raw_file_name.*|\1|g;
s| | |g
}" | sort -u | head -1
)
cron_name=$(grep "new Env" $raw_file_name | awk -F "'|\"" '{print $2}' | head -1)
[[ -z $cron_name ]] && cron_name="$raw_file_name"
[[ -z $cron_line ]] && cron_line="0 6 * * *"
if [[ -z $cron_id ]]; then
result=$(add_cron_api "$cron_line:$cmd_task $filename:$cron_name")
echo -e "$result"
notify "新增任务通知" "\n$result"
# update_cron_api "$cron_line:$cmd_task $filename:$cron_name:$cron_id"
fi
else
echo -e "下载 ${raw_file_name} 失败,保留之前正常下载的版本...\n"
[ -f "$dir_raw/${raw_file_name}.new" ] && rm -f "$dir_raw/${raw_file_name}.new"
fi
}
## 调用用户自定义的extra.sh
run_extra_shell() {
if [[ ${EnableExtraShell} == true ]]; then
if [ -f $file_extra_shell ]; then
echo -e "--------------------------------------------------------------\n"
. $file_extra_shell
else
echo -e "$file_extra_shell文件不存在,跳过执行...\n"
fi
fi
}
## 脚本用法
usage() {
echo -e "本脚本用法:"
echo -e "1. $cmd_update update # 更新青龙并且运行extra.sh"
echo -e "2. $cmd_update restart # 重新启动青龙并编译不会运行extra.sh"
echo -e "3. $cmd_update raw <fileurl> # 更新单个脚本文件"
echo -e "4. $cmd_update repo <repourl> <path> <blacklist> <dependence> # 更新单个仓库的脚本"
echo -e "5. $cmd_update rmlog <days> # 删除旧日志"
echo -e "6. $cmd_update code # 获取互助码"
echo -e "6. $cmd_update bot # 启动tg-bot"
}
## 更新qinglong
update_qinglong() {
echo -e "--------------------------------------------------------------\n"
git_pull_scripts $dir_root
if [[ $exit_status -eq 0 ]]; then
echo -e "\n更新$dir_root成功...\n"
cp -f $file_config_sample $dir_config/config.sample.sh
detect_config_version
update_depend
else
echo -e "\n更新$dir_root失败,请检查原因...\n"
fi
}
## 对比脚本
diff_scripts() {
gen_list_repo $1 $2 $3 $4 $5
diff_cron $list_own_scripts $list_own_user $list_own_add $list_own_drop
if [ -s $list_own_drop ]; then
output_list_add_drop $list_own_drop "失效"
if [[ ${AutoDelCron} == true ]]; then
del_cron $list_own_drop $2
fi
fi
if [ -s $list_own_add ]; then
output_list_add_drop $list_own_add "新"
if [[ ${AutoAddCron} == true ]]; then
add_cron $list_own_add $2
fi
fi
}
## 生成脚本的路径清单文件
gen_list_repo() {
local dir_current=$(pwd)
local repo_path="$1"
local author="$2"
local path="$3"
local blackword="$4"
local dependence="$5"
rm -f $dir_list_tmp/own*.list >/dev/null 2>&1
cd ${repo_path}
files=$(find . -name "*.js" | sed 's/^..//')
if [[ $path ]]; then
files=$(find . -name "*.js" | sed 's/^..//' | egrep $path)
fi
if [[ $blackword ]]; then
files=$(find . -name "*.js" | sed 's/^..//' | egrep -v $blackword | egrep $path)
fi
if [[ $dependence ]]; then
find . -name "*.js" | sed 's/^..//' | egrep $dependence | xargs -i cp {} $dir_scripts
fi
for file in ${files}; do
filename=$(basename $file)
cp -f $file $dir_scripts/${author}_${filename}
echo ${author}_${filename} >>$list_own_scripts
done
grep -E "$cmd_task $author" $list_crontab_user | perl -pe "s|.*ID=(.*) $cmd_task ($author_.*)\.*|\2|" | awk -F " " '{print $1}' | sort -u >$list_own_user
cd $dir_current
}
## 重新编译qinglong
restart_qinglong() {
update_qinglong
if [[ $exit_status -eq 0 ]]; then
echo -e "重新编译青龙...\n"
yarn install --network-timeout 1000000000 || yarn install --registry=https://registry.npm.taobao.org --network-timeout 1000000000
yarn build
yarn build-back
yarn cache clean
echo -e "重新编译青龙完成...\n"
echo -e "重启青龙面板...\n"
pm2 reload panel 2>/dev/null || pm2 start $dir_root/build/app.js -n panel
nginx -s reload 2>/dev/null || nginx -c /etc/nginx/nginx.conf
echo -e "重启面板完成...\n"
echo -e "重启定时任务...\n"
pm2 reload schedule 2>/dev/null || pm2 start $dir_root/build/schedule.js -n schedule
echo -e "重启定时完成...\n"
fi
}
main() {
local p1=$1
local p2=$2
local p3=$3
local p4=$4
local p5=$5
log_time=$(date "+%Y-%m-%d-%H-%M-%S")
log_path="$dir_log/update/${log_time}_$p1.log"
case $p1 in
update)
update_qinglong | tee $log_path
run_extra_shell | tee -a $log_path
;;
restart)
restart_qinglong | tee $log_path
;;
repo)
get_user_info
local name=$(echo "${p2##*/}" | awk -F "." '{print $1}')
log_path="$dir_log/update/${log_time}_$name.log"
if [[ -n $p2 ]]; then
update_repo "$p2" "$p3" "$p4" "$p5" | tee $log_path
else
echo -e "命令输入错误...\n"
usage
fi
;;
raw)
get_user_info
local name=$(echo "${p2##*/}" | awk -F "." '{print $1}')
log_path="$dir_log/update/${log_time}_$name.log"
if [[ -n $p2 ]]; then
update_raw "$p2" | tee $log_path
else
echo -e "命令输入错误...\n"
usage
fi
;;
rmlog)
. $dir_shell/rmlog.sh "$p2" | tee $log_path
;;
code)
. $dir_shell/code.sh
;;
bot)
. $dir_shell/bot.sh
;;
*)
echo -e "命令输入错误...\n"
usage
;;
esac
}
main "$@"
exit 0