-
Notifications
You must be signed in to change notification settings - Fork 0
/
jup.sh
executable file
·513 lines (452 loc) · 19.7 KB
/
jup.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
#!/usr/bin/env bash
## 文件路径、脚本网址
dir_shell=$(dirname $(readlink -f "$0"))
dir_root=$dir_shell
url_shell=${JD_SHELL_URL:-https://ghproxy.com/https://github.com/y2038558528/tsnode.git}
url_scripts=${JD_SCRIPTS_URL:-https://ghproxy.com/https://github.com/y2038558528/sync.git}
send_mark=$dir_shell/send_mark
## 导入通用变量与函数
. $dir_shell/jshare.sh
## 导入配置文件,检测平台,创建软连接,识别命令,修复配置文件
detect_termux
detect_macos
link_shell
define_cmd
fix_config
import_config_no_check jup
## 更新crontab,gitee服务器同一时间限制5个链接,因此每个人更新代码必须错开时间,每次执行git_pull随机生成。
## 每天次数随机,更新时间随机,更新秒数随机,至少4次,至多6次,大部分为5次,符合正态分布。
random_update_jup_cron () {
if [[ $(date "+%-H") -le 4 ]] && [ -f $list_crontab_user ]; then
local random_min=$(gen_random_num 60)
local random_sleep=$(gen_random_num 56)
local random_hour_array[0]=$(gen_random_num 5)
local random_hour=${random_hour_array[0]}
local i j tmp
for ((i=1; i<14; i++)); do
j=$(($i - 1))
tmp=$(($(gen_random_num 3) + ${random_hour_array[j]} + 4))
[[ $tmp -lt 24 ]] && random_hour_array[i]=$tmp || break
done
for ((i=1; i<${#random_hour_array[*]}; i++)); do
random_hour="$random_hour,${random_hour_array[i]}"
done
perl -i -pe "s|.+(jup(\.sh)? .+jup\.log.*)|$random_min $random_hour \* \* \* sleep $random_sleep && \1|" $list_crontab_user
crontab $list_crontab_user
fi
}
## 重置仓库remote url,docker专用,$1:要重置的目录,$2:要重置为的网址
reset_romote_url () {
local dir_current=$(pwd)
local dir_work=$1
local url=$2
if [ -d "$dir/.git" ]; then
cd $dir_work
git remote set-url origin $url
git reset --hard
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
}
## 统计 own 仓库数量
count_own_repo_sum () {
if [[ -z ${OwnRepoUrl1} ]]; then
own_repo_sum=0
else
for ((i=1; i<=1000; i++)); do
local tmp1=OwnRepoUrl$i
local tmp2=${!tmp1}
[[ $tmp2 ]] && own_repo_sum=$i || break
done
fi
}
## 形成 own 仓库的文件夹名清单,依赖于import_config_and_check或import_config_no_check
## array_own_repo_path:repo存放的绝对路径组成的数组;array_own_scripts_path:所有要使用的脚本所在的绝对路径组成的数组
gen_own_dir_and_path () {
if [[ $own_repo_sum -ge 1 ]]; then
local scripts_path_num="-1"
local repo_num tmp1 tmp2 tmp3 tmp4 tmp5 dir
for ((i=1; i<=$own_repo_sum; i++)); do
repo_num=$((i - 1))
tmp1=OwnRepoUrl$i
array_own_repo_url[$repo_num]=${!tmp1}
tmp2=OwnRepoBranch$i
array_own_repo_branch[$repo_num]=${!tmp2}
array_own_repo_dir[$repo_num]=$(echo ${array_own_repo_url[$repo_num]} | perl -pe "s|.+com(/\|:)([\w-]+)/([\w-]+)(\.git)?|\2_\3|")
array_own_repo_path[$repo_num]=$dir_own/${array_own_repo_dir[$repo_num]}
tmp3=OwnRepoPath$i
for dir in ${!tmp3}; do
let scripts_path_num++
tmp4="${array_own_repo_dir[repo_num]}/$dir"
tmp5=$(echo $tmp4 | perl -pe "{s|//|/|g; s|/$||}") # 去掉多余的/
array_own_scripts_path[$scripts_path_num]="$dir_own/$tmp5"
done
done
fi
if [[ ${#OwnRawFile[*]} -ge 1 ]]; then
let scripts_path_num++
array_own_scripts_path[$scripts_path_num]=$dir_raw # 只有own脚本所在绝对路径附加了raw文件夹,其他数组均不附加
fi
}
## 生成 jd_scripts task 清单,仅有去掉后缀的文件名
gen_list_task () {
make_dir $dir_list_tmp
grep -E "node.+j[drx]_\w+\.js" $list_crontab_jd_scripts | perl -pe "s|.+(j[drx]_\w+)\.js.+|\1|" | sort -u > $list_task_jd_scripts
grep -E "$cmd_jtask j[drx]_\w+" $list_crontab_user | perl -pe "s|.*$cmd_jtask (j[drx]_\w+).*|\1|" | sort -u > $list_task_user
}
## 生成 own 脚本的绝对路径清单
gen_list_own () {
local dir_current=$(pwd)
rm -f $dir_list_tmp/own*.list >/dev/null 2>&1
for ((i=0; i<${#array_own_scripts_path[*]}; i++)); do
cd ${array_own_scripts_path[i]}
for file in $(ls *.js); do
if [ -f $file ]; then
perl -ne "{
print if /.*([\d\*]*[\*-\/,\d]*[\d\*] ){4}[\d\*]*[\*-\/,\d]*[\d\*]( |,).*\/?$file/
}" $file | \
perl -pe "{
s|.*(([\d\*]*[\*-\/,\d]*[\d\*] ){4}[\d\*]*[\*-\/,\d]*[\d\*]( \|,)).*/?$file.*|$file|g;
s|^(.+)|${array_own_scripts_path[i]}/\1|
}" | \
head -1 >> $list_own_scripts
fi
done
done
grep -E "$cmd_otask " $list_crontab_user | perl -pe "s|.*$cmd_otask ([^\s]+)( .+\|$)|\1|" | sort -u > $list_own_user
cd $dir_current
}
## 检测cron的差异,$1:脚本清单文件路径,$2:cron任务清单文件路径,$3:增加任务清单文件路径,$4:删除任务清单文件路径
diff_cron () {
make_dir $dir_list_tmp
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
else
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
}
## 更新docker-entrypoint,docker专用
update_docker_entrypoint () {
if [[ $JD_DIR ]] && [[ $(cat $dir_root/docker/docker-entrypoint.sh) != $(cat /usr/local/bin/docker-entrypoint.sh) ]]; then
cp -f $dir_root/docker/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
chmod 777 /usr/local/bin/docker-entrypoint.sh
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
}
## npm install 子程序,判断是否为安卓,判断是否安装有yarn
npm_install_sub () {
local cmd_1 cmd_2
type yarn >/dev/null 2>&1 && cmd_1=yarn || cmd_1=npm
[[ $is_termux -eq 1 ]] && cmd_2="--no-bin-links" || cmd_2=""
$cmd_1 install $cmd_2 --registry=https://registry.npm.taobao.org || $cmd_1 install $cmd_2
}
## npm install,$1:package.json文件所在路径
npm_install_1 () {
local dir_current=$(pwd)
local dir_work=$1
cd $dir_work
echo -e "运行 npm install...\n"
npm_install_sub
[[ $? -ne 0 ]] && echo -e "\nnpm install 运行不成功,请进入 $dir_work 目录后手动运行 npm install...\n"
cd $dir_current
}
npm_install_2 () {
local dir_current=$(pwd)
local dir_work=$1
cd $dir_work
echo -e "检测到 $dir_work 的依赖包有变化,运行 npm install...\n"
npm_install_sub
[[ $? -ne 0 ]] && echo -e "\n安装 $dir_work 的依赖包运行不成功,再次尝试一遍...\n"
npm_install_1 $dir_work
cd $dir_current
}
## 输出是否有新的或失效的定时任务,$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/AutoDelOwnCron 设置为 true;2.正常更新js脚本,没有报错;3.存在失效任务;4.crontab.list存在并且不为空
## $1:失效任务清单文件路径,$2:jtask/otask
del_cron () {
local list_drop=$1
local type=$2
local detail type2 detail2
if [ -s $list_drop ] && [ -s $list_crontab_user ]; then
detail=$(cat $list_drop)
[[ $type == jtask ]] && type2="jd_scipts脚本"
[[ $type == otask ]] && type2="own脚本"
echo -e "开始尝试自动删除$type2的定时任务...\n"
for cron in $detail; do
local tmp=$(echo $cron | perl -pe "s|/|\.|g")
perl -i -ne "{print unless / $type $tmp( |$)/}" $list_crontab_user
done
crontab $list_crontab_user
detail2=$(echo $detail | perl -pe "s| |\\\n|g")
echo -e "成功删除失效的$type2的定时任务...\n"
notify "删除失效任务通知" "成功删除以下失效的定时任务($type2):\n$detail2"
fi
}
## 自动增加jd_scripts新的定时任务,需要:1.AutoAddCron 设置为 true;2.正常更新js脚本,没有报错;3.存在新任务;4.crontab.list存在并且不为空
## $1:新任务清单文件路径
add_cron_jd_scripts () {
local list_add=$1
if [[ ${AutoAddCron} == true ]] && [ -s $list_add ] && [ -s $list_crontab_user ]; then
echo -e "开始尝试自动添加 jd_scipts 的定时任务...\n"
local detail=$(cat $list_add)
for cron in $detail; do
if [[ $cron == jd_bean_sign ]]; then
echo "4 0,9 * * * $cmd_jtask $cron" >> $list_crontab_user
else
cat $list_crontab_jd_scripts | grep -E "\/$cron\." | perl -pe "s|(^.+)node */scripts/(j[drx]_\w+)\.js.+|\1$cmd_jtask \2|" >> $list_crontab_user
fi
done
exit_status=$?
fi
}
## 自动增加自己额外的脚本的定时任务,需要:1.AutoAddOwnCron 设置为 true;2.正常更新js脚本,没有报错;3.存在新任务;4.crontab.list存在并且不为空
## $1:新任务清单文件路径
add_cron_own () {
local list_add=$1
local list_crontab_own_tmp=$dir_list_tmp/crontab_own.list
[ -f $list_crontab_own_tmp ] && rm -f $list_crontab_own_tmp
if [[ ${AutoAddOwnCron} == true ]] && [ -s $list_add ] && [ -s $list_crontab_user ]; then
echo -e "开始尝试自动添加 own 脚本的定时任务...\n"
local detail=$(cat $list_add)
for file_full_path in $detail; do
local file_name=$(echo $file_full_path | awk -F "/" '{print $NF}')
if [ -f $file_full_path ]; then
perl -ne "{
print if /.*([\d\*]*[\*-\/,\d]*[\d\*] ){4}[\d\*]*[\*-\/,\d]*[\d\*]( |,).*$file_name/
}" $file_full_path | \
perl -pe "{
s|[^\d\*]*(([\d\*]*[\*-\/,\d]*[\d\*] ){4}[\d\*]*[\*-\/,\d]*[\d\*]( \|,)).*/?$file_name.*|\1 $cmd_otask $file_full_path|g;
s| | |g
}" | \
head -1 >> $list_crontab_own_tmp
fi
done
crontab_tmp="$(cat $list_crontab_own_tmp)"
perl -i -pe "s|(# 自用own任务结束.+)|$crontab_tmp\n\1|" $list_crontab_user
exit_status=$?
fi
[ -f $list_crontab_own_tmp ] && rm -f $list_crontab_own_tmp
}
## 向系统添加定时任务以及通知,$1:写入crontab.list时的exit状态,$2:新增清单文件路径,$3:jd_scripts脚本/own脚本
add_cron_notify () {
local status_code=$1
local list_add=$2
local tmp=$(echo $(cat $list_add))
local detail=$(echo $tmp | perl -pe "s| |\\\n|g")
local type=$3
if [[ $status_code -eq 0 ]]; then
crontab $list_crontab_user
echo -e "成功添加新的定时任务...\n"
notify "新增任务通知" "成功添加新的定时任务($type):\n$detail"
else
echo -e "添加新的定时任务出错,请手动添加...\n"
notify "新任务添加失败通知" "尝试自动添加以下新的定时任务出错,请手动添加($type):\n$detail"
fi
}
## 更新 own 所有仓库
update_own_repo () {
[[ ${#array_own_repo_url[*]} -gt 0 ]] && echo -e "--------------------------------------------------------------\n"
for ((i=0; i<${#array_own_repo_url[*]}; i++)); do
if [ -d ${array_own_repo_path[i]}/.git ]; then
git_pull_scripts ${array_own_repo_path[i]}
else
git_clone_scripts ${array_own_repo_url[i]} ${array_own_repo_path[i]} ${array_own_repo_branch[i]}
fi
[[ $exit_status -eq 0 ]] && echo -e "\n更新${array_own_repo_path[i]}成功...\n" || echo -e "\n更新${array_own_repo_path[i]}失败,请检查原因...\n"
done
}
## 更新 own 所有 raw 文件
update_own_raw () {
local rm_mark
[[ ${#OwnRawFile[*]} -gt 0 ]] && echo -e "--------------------------------------------------------------\n"
for ((i=0; i<${#OwnRawFile[*]}; i++)); do
raw_file_name[$i]=$(echo ${OwnRawFile[i]} | awk -F "/" '{print $NF}')
echo -e "开始下载:${OwnRawFile[i]} \n\n保存路径:$dir_raw/${raw_file_name[$i]}\n"
wget -q --no-check-certificate -O "$dir_raw/${raw_file_name[$i]}.new" ${OwnRawFile[i]}
if [[ $? -eq 0 ]]; then
mv "$dir_raw/${raw_file_name[$i]}.new" "$dir_raw/${raw_file_name[$i]}"
echo -e "下载 ${raw_file_name[$i]} 成功...\n"
else
echo -e "下载 ${raw_file_name[$i]} 失败,保留之前正常下载的版本...\n"
[ -f "$dir_raw/${raw_file_name[$i]}.new" ] && rm -f "$dir_raw/${raw_file_name[$i]}.new"
fi
done
for file in $(ls $dir_raw); do
rm_mark="yes"
for ((i=0; i<${#raw_file_name[*]}; i++)); do
if [[ $file == ${raw_file_name[$i]} ]]; then
rm_mark="no"
break
fi
done
[[ $rm_mark == yes ]] && rm -f $dir_raw/$file 2>/dev/null
done
}
#################################################################################################################################
## 在日志中记录时间与路径
echo "
--------------------------------------------------------------
系统时间:$(date "+%Y-%m-%d %H:%M:%S")
脚本根目录:$dir_root
jd_scripts目录:$dir_scripts
own脚本目录:$dir_own
--------------------------------------------------------------
"
## 更新jup任务的cron
random_update_jup_cron
## 重置仓库romote url
if [[ $JD_DIR ]] && [[ $ENABLE_RESET_REPO_URL == true ]]; then
reset_romote_url $dir_shell $url_shell >/dev/null
reset_romote_url $dir_scripts $url_scripts >/dev/null
fi
## 更新shell
[ -f $dir_panel/package.json ] && panel_depend_old=$(cat $dir_panel/package.json)
git_pull_scripts $dir_shell
if [[ $exit_status -eq 0 ]]; then
echo -e "\n更新$dir_shell成功...\n"
[ ! -d $dir_panel/node_modules ] && npm_install_1 $dir_panel
[ -f $dir_panel/package.json ] && panel_depend_new=$(cat $dir_panel/package.json)
[[ "$panel_depend_old" != "$panel_depend_new" ]] && npm_install_2 $dir_panel
make_dir $dir_config
cp -f $file_config_sample $dir_config/config.sample.sh
update_docker_entrypoint
detect_config_version
else
echo -e "\n更新$dir_shell失败,请检查原因...\n"
fi
## 更新scripts
## 更新前先存储package.json和githubAction.md的内容
[ -f $dir_scripts/package.json ] && scripts_depend_old=$(cat $dir_scripts/package.json)
[ -f $dir_scripts/githubAction.md ] && cp -f $dir_scripts/githubAction.md $dir_list_tmp/githubAction.md
## 更新或克隆scripts
if [ -d $dir_scripts/.git ]; then
git_pull_scripts $dir_scripts
else
git_clone_scripts $url_scripts $dir_scripts
fi
if [[ $exit_status -eq 0 ]]; then
echo -e "\n更新$dir_scripts成功...\n"
## npm install
[ ! -d $dir_scripts/node_modules ] && npm_install_1 $dir_scripts
[ -f $dir_scripts/package.json ] && scripts_depend_new=$(cat $dir_scripts/package.json)
[[ "$scripts_depend_old" != "$scripts_depend_new" ]] && npm_install_2 $dir_scripts
## diff cron
gen_list_task
diff_cron $list_task_jd_scripts $list_task_user $list_task_add $list_task_drop
## 失效任务通知
if [ -s $list_task_drop ]; then
output_list_add_drop $list_task_drop "失效"
[[ ${AutoDelCron} == true ]] && del_cron $list_task_drop jtask
fi
## 新增任务通知
if [ -s $list_task_add ]; then
output_list_add_drop $list_task_add "新"
add_cron_jd_scripts $list_task_add
[[ ${AutoAddCron} == true ]] && add_cron_notify $exit_status $list_task_add "jd_scripts脚本"
fi
## 环境变量变化通知
echo -e "检测环境变量清单文件 $dir_scripts/githubAction.md 是否有变化...\n"
diff $dir_list_tmp/githubAction.md $dir_scripts/githubAction.md | tee $dir_list_tmp/env.diff
if [ ! -s $dir_list_tmp/env.diff ]; then
echo -e "$dir_scripts/githubAction.md 没有变化...\n"
elif [ -s $dir_list_tmp/env.diff ] && [[ ${EnvChangeNotify} == true ]]; then
notify_title="检测到环境变量清单文件有变化"
notify_content="减少的内容:\n$(grep -E '^-[^-]' $dir_list_tmp/env.diff)\n\n增加的内容:\n$(grep -E '^\+[^\+]' $dir_list_tmp/env.diff)"
notify "$notify_title" "$notify_content"
fi
else
echo -e "\n更新$dir_scripts失败,请检查原因...\n"
fi
## 更新own脚本
count_own_repo_sum
gen_own_dir_and_path
if [[ ${#array_own_scripts_path[*]} -gt 0 ]]; then
make_dir $dir_raw
update_own_repo
update_own_raw
gen_list_own
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 "失效"
[[ ${AutoDelOwnCron} == true ]] && del_cron $list_own_drop otask
fi
if [ -s $list_own_add ]; then
output_list_add_drop $list_own_add "新"
add_cron_own $list_own_add
[[ ${AutoAddOwnCron} == true ]] && add_cron_notify $exit_status $list_own_add "own脚本"
fi
else
perl -i -ne "{print unless / $cmd_otask /}" $list_crontab_user
fi
## 调用用户自定义的diy.sh
if [[ ${EnableExtraShell} == true ]]; then
if [ -f $file_diy_shell ]
then
echo -e "--------------------------------------------------------------\n"
. $file_diy_shell
else
echo -e "$file_diy_shell文件不存在,跳过执行DIY脚本...\n"
fi
fi
exit 0