601 lines
25 KiB
Bash
601 lines
25 KiB
Bash
#!/system/bin/sh
|
||
# ============================================================
|
||
# SpeedBackup - Android 備份恢復腳本
|
||
# By @YAWAsau
|
||
# ============================================================
|
||
#
|
||
# 模組化結構 — 函數定義已移至 tools/core/
|
||
# core/config_mgmt.sh - 配置檔生成
|
||
# core/base_utils.sh - 基礎工具函數
|
||
# core/app_utils.sh - 應用/進程/權限管理
|
||
# core/backup_core.sh - 備份核心邏輯
|
||
# core/restore_core.sh - 恢復核心邏輯
|
||
# core/updater.sh - 更新/列表/WiFi/設備
|
||
#
|
||
# 本文件為執行入口,包含:
|
||
# L21-32 全局變量與初始檢查
|
||
# L33-43 模組載入
|
||
# L44-77 配置檔加載與語言設定
|
||
# L78-217 環境設置 (PATH/busybox/SHA/TMPDIR)
|
||
# L218-292 硬件信息/語言檢測
|
||
# L293-369 用戶檢測與環境別名
|
||
# L370-498 更新檢查流程
|
||
# L499-510 後台應用檢測
|
||
# L511-599 入口分發 (菜單/直接執行)
|
||
# ============================================================
|
||
if [ "$(whoami)" != root ]; then
|
||
echo "你是憨批?不給Root用你媽 爬"
|
||
exit 1
|
||
fi
|
||
[[ -d /data/cache ]] && set -x 2> /data/cache/debug_output.log
|
||
shell_language="zh-TW"
|
||
MODDIR_NAME="${MODDIR##*/}"
|
||
tools_path="$MODDIR/tools"
|
||
script="${0##*/}"
|
||
backup_version="202508162209"
|
||
[[ $SHELL = *mt* ]] && echo "請勿使用MT管理器拓展包環境執行,請更換系統環境" && exit 2
|
||
# ======================== Section 2: 配置檔生成與加載 ========================
|
||
# --- Load core modules ---
|
||
core_path="$MODDIR/tools/core"
|
||
[[ ! -d $core_path ]] && core_path="${0%/*}/core"
|
||
. "$core_path/config_mgmt.sh"
|
||
. "$core_path/base_utils.sh"
|
||
. "$core_path/app_utils.sh"
|
||
. "$core_path/backup_core.sh"
|
||
. "$core_path/restore_core.sh"
|
||
. "$core_path/updater.sh"
|
||
# --- End module loading ---
|
||
|
||
if [[ ! -d $tools_path ]]; then
|
||
tools_path="${MODDIR%/*}/tools"
|
||
[[ ! -d $tools_path ]] && echo "$tools_path二進制目錄遺失" && EXIT="true"
|
||
fi
|
||
if [[ ! -f $conf_path ]]; then
|
||
if [[ $conf_path != *restore_settings.conf && $conf_path = *backup_settings.conf ]]; then
|
||
update_backup_settings_conf>"$conf_path"
|
||
else
|
||
if [[ $conf_path = *restore_settings.conf && $conf_path != *backup_settings.conf ]]; then
|
||
update_Restore_settings_conf>"$conf_path"
|
||
else
|
||
echo "$conf_path配置遺失" && exit 1
|
||
fi
|
||
fi
|
||
echo "因腳本找不到\n$conf_path\n故重新生成默認列表\n請重新配置後重新執行腳本" && exit 0
|
||
fi
|
||
[[ ! -f $conf_path ]] && echo "$conf_path遺失" && exit 2
|
||
. "$conf_path" &>/dev/null
|
||
# 加載後立即更新配置(補充新選項)
|
||
if [[ $conf_path != *restore_settings.conf && $conf_path = *backup_settings.conf ]]; then
|
||
update_backup_settings_conf>"$conf_path"
|
||
else
|
||
if [[ $conf_path = *restore_settings.conf && $conf_path != *backup_settings.conf ]]; then
|
||
update_Restore_settings_conf>"$conf_path"
|
||
else
|
||
echo "$conf_path配置遺失" && exit 1
|
||
fi
|
||
fi
|
||
case $Shell_LANG in
|
||
1) LANG="CN" ;;
|
||
0) LANG="TW" ;;
|
||
*) LANG="${LANG:="$(getprop "persist.sys.locale")"}" ;;
|
||
esac
|
||
# ======================== Section 3: 基礎工具函數 ========================
|
||
rgb_a="${rgb_a:=214}"
|
||
abi="$(getprop ro.product.cpu.abi)"
|
||
case $abi in
|
||
arm64*)
|
||
if [[ $(getprop ro.build.version.sdk) -lt 26 ]]; then
|
||
echoRgb "設備Android $(getprop ro.build.version.release)版本過低 請升級至Android 8+" "0"
|
||
exit 1
|
||
else
|
||
case $(getprop ro.build.version.sdk) in
|
||
26|27|28)
|
||
echoRgb "設備Android $(getprop ro.build.version.release)版本偏低,無法確定腳本能正確的使用" "0"
|
||
;;
|
||
esac
|
||
fi
|
||
;;
|
||
*)
|
||
echoRgb "未知的架構: $abi" "0"
|
||
exit 1
|
||
;;
|
||
esac
|
||
get_mv="$(which mv)"
|
||
PATH="/system/bin:/system/xbin:/data/adb/ksu/bin:/sbin/.magisk/busybox:/sbin/.magisk:/sbin:/system_ext/bin:/vendor/bin:/vendor/xbin:/data/data/com.omarea.vtools/files/toolkit:/data/user/0/com.termux/files/usr/bin"
|
||
if [[ -d $(magisk --path 2>/dev/null) ]]; then
|
||
PATH="$(magisk --path 2>/dev/null)/.magisk/busybox:$PATH"
|
||
else
|
||
[[ $(ksud -V 2>/dev/null) = "" ]] && echo "Magisk busybox Path does not exist"
|
||
fi
|
||
export PATH="$PATH"
|
||
filepath="/data/backup_tools"
|
||
busybox="$filepath/busybox"
|
||
busybox2="$tools_path/busybox"
|
||
#排除自身
|
||
exclude="
|
||
update
|
||
soc.json
|
||
classes.dex
|
||
Device_List"
|
||
if [[ ! -d $filepath ]]; then
|
||
mkdir -p "$filepath"
|
||
[[ $? = 0 ]] && echoRgb "設置busybox環境中"
|
||
fi
|
||
#刪除無效軟連結
|
||
find -L "$filepath" -maxdepth 1 -type l -exec rm -rf {} \;
|
||
if [[ -f $busybox && -f $busybox2 ]]; then
|
||
filesha256="$(sha256sum "$busybox" | cut -d" " -f1)"
|
||
filesha256_1="$(sha256sum "$busybox2" | cut -d" " -f1)"
|
||
if [[ $filesha256 != $filesha256_1 ]]; then
|
||
echoRgb "busybox sha256不一致 重新創立環境中"
|
||
rm -rf "$filepath"/*
|
||
fi
|
||
fi
|
||
find "$tools_path" -maxdepth 1 ! -path "$tools_path/tools.sh" -type f | egrep -v "$(echo $exclude | sed 's/ /\|/g')" | while read; do
|
||
File_name="${REPLY##*/}"
|
||
if [[ ! -f $filepath/$File_name ]]; then
|
||
cp -r "$REPLY" "$filepath"
|
||
chmod 0755 "$filepath/$File_name"
|
||
echoRgb "$File_name > $filepath/$File_name"
|
||
else
|
||
filesha256="$(sha256sum "$filepath/$File_name" | cut -d" " -f1)"
|
||
filesha256_1="$(sha256sum "$tools_path/$File_name" | cut -d" " -f1)"
|
||
if [[ $filesha256 != $filesha256_1 ]]; then
|
||
echoRgb "$File_name sha256不一致 重新創建"
|
||
cp -r "$REPLY" "$filepath"
|
||
chmod 0755 "$filepath/$File_name"
|
||
echoRgb "$File_name > $filepath/$File_name"
|
||
fi
|
||
fi
|
||
done
|
||
if [[ -f $busybox ]]; then
|
||
"$busybox" --list | while read; do
|
||
if [[ $REPLY != tar && $REPLY != bc && ! -f $filepath/$REPLY ]]; then
|
||
ln -fs "$busybox" "$filepath/$REPLY"
|
||
fi
|
||
done
|
||
fi
|
||
[[ ! -f $filepath/zstd ]] && echoRgb "$filepath缺少zstd" && exit 2
|
||
export PATH="$filepath:$PATH"
|
||
export TZ=Asia/Taipei
|
||
ln -fs "$tools_path/classes.dex" "$filepath/classes.dex"
|
||
export CLASSPATH="$filepath/classes.dex"
|
||
quit=0
|
||
while read -r file expected_hash; do
|
||
if [[ -f $tools_path/$file ]]; then
|
||
computed_hash="$(sha256sum "$tools_path/$file" | awk '{print $1}')"
|
||
if [[ $computed_hash = $expected_hash ]]; then
|
||
echoRgb "✅ $file: 驗證通過"
|
||
else
|
||
echoRgb "❌ $tools_path/$file: SHA-256 不一致\n -\"$computed_hash\""
|
||
quit=2
|
||
break
|
||
fi
|
||
else
|
||
echoRgb "⚠️ 檔案 $tools_path/$file 不存在"
|
||
quit=1
|
||
break
|
||
fi
|
||
done <<< "$(cat <<EOF
|
||
zstd ab32aecb389c3ba5c1f7ab05d5eb6a861bad80261fd14ef9a8f4c283ac48c22c
|
||
tar 3c605b1e9eb8283555225dcad4a3bf1777ae39c5f19a2c8b8943140fd7555814
|
||
classes.dex 63934f7d15de40f4b188672e36fe22a01b55abb235becee2c2738f29aaf8299b
|
||
bc b15d730591f6fb52af59284b87d939c5bea204f944405a3518224d8df788dc15
|
||
busybox 4d60ab3f5a59ebb2ca863f2f514e6924401b581e9b64f602665c008177626651
|
||
find 7fa812e58aafa29679cf8b50fc617ecf9fec2cfb2e06ea491e0a2d6bf79b903b
|
||
jq 4dd2d8a0661df0b22f1bb9a1f9830f06b6f3b8f7d91211a1ef5d7c4f06a8b4a5
|
||
keycheck 50645ee0e0d2a7d64fb4a1286446df7a4445f3d11aefd49eeeb88515b314c363
|
||
cmd 08da8ac23b6e99788fd3ce6c19c7b5a083b2ad48be35963a48d01d6ee7f3bb6d
|
||
EOF)"
|
||
if [[ $background_execution = 1 || $setDisplayPowerMode = 1 ]]; then
|
||
alias notification="app_process /system/bin com.xayah.dex.NotificationUtil notify -t 'SpeedBackup' "$@""
|
||
else
|
||
alias notification="&>/dev/null"
|
||
fi
|
||
if [[ $quit -ne 0 ]]; then
|
||
exit "$quit"
|
||
fi
|
||
TMPDIR="/data/local/tmp/SpeedBackup"
|
||
[[ ! -d $TMPDIR ]] && mkdir -p "$TMPDIR"
|
||
[[ -n $TMPDIR && $TMPDIR = /data/local/tmp/* ]] && rm -rf "$TMPDIR"/*
|
||
chmod 771 "$TMPDIR"
|
||
chown '2000:2000' "$TMPDIR"
|
||
if [[ $(which busybox) = "" ]]; then
|
||
echoRgb "環境變量中沒有找到busybox 請在tools內添加一個\narm64可用的busybox\n或是安裝搞機助手 scene或是Magisk busybox模塊...." "0"
|
||
exit 1
|
||
fi
|
||
if [[ $(which toybox | egrep -o "system") != system ]]; then
|
||
echoRgb "系統變量中沒有找到toybox" "0"
|
||
exit 1
|
||
fi
|
||
#下列為自定義函數
|
||
alias down="app_process /system/bin com.xayah.dex.HttpUtil get $@"
|
||
case $LANG in
|
||
*CN* | *cn*)
|
||
alias ts="app_process /system/bin com.xayah.dex.CCUtil t2s $@" ;;
|
||
*)
|
||
alias ts="app_process /system/bin com.xayah.dex.CCUtil s2t $@" ;;
|
||
esac
|
||
alias LS="toybox ls -Zd"
|
||
alias mv="$get_mv"
|
||
nskg=1
|
||
echo $$
|
||
kill_Serve
|
||
[[ -f /sys/block/sda/size ]] && ROM_TYPE="UFS" || ROM_TYPE="eMMC"
|
||
if [[ -f /proc/scsi/scsi ]]; then
|
||
UFS_MODEL="$(sed -n 3p /proc/scsi/scsi | awk '/Vendor/{print $2,$4}')"
|
||
else
|
||
if [[ $(cat "/sys/class/block/sda/device/inquiry" 2>/dev/null) != "" ]]; then
|
||
UFS_MODEL="$(cat "/sys/class/block/sda/device/inquiry")"
|
||
else
|
||
UFS_MODEL="unknown"
|
||
fi
|
||
fi
|
||
[[ $(egrep -w "$(getprop ro.product.model 2>/dev/null)" "$tools_path/Device_List" | awk -F'"' '{print $4}') != "" ]] && Device_name="$(egrep -w "$(getprop ro.product.model 2>/dev/null)" "$tools_path/Device_List" | awk -F'"' '{print $4}' | head -1)" || Device_name="$(getprop ro.product.model 2>/dev/null)"
|
||
if [[ $(su -v 2>/dev/null) != "" ]]; then
|
||
Manager_version="$(su -v 2>/dev/null)"
|
||
[[ $Manager_version = *KernelSU* ]] && ksu="ksu"
|
||
[[ $ksu = "" ]] && [[ -d /data/adb/ksu ]] && ksu="ksu"
|
||
else
|
||
if [[ -d /data/adb/ksu ]]; then
|
||
Manager_version=KernelSU
|
||
ksu="ksu"
|
||
fi
|
||
fi
|
||
Socname="$(getprop ro.soc.model)"
|
||
if [[ $Socname != "" ]]; then
|
||
if [[ -f $tools_path/soc.json ]]; then
|
||
jq -r --arg device "$Socname" '.[$device] | "處理器:\(.VENDOR) \(.NAME)"' "$tools_path/soc.json" &>/dev/null
|
||
if [[ $? = 0 ]]; then
|
||
DEVICE_NAME="$(jq -r --arg device "$Socname" '.[$device] | "處理器:\(.VENDOR) \(.NAME)"' "$tools_path/soc.json" 2>/dev/null)"
|
||
jq -r --arg device "$Socname" '.[$device] | "RAM:\(.MEMORY) \(.CHANNELS)"' "$tools_path/soc.json" &>/dev/null
|
||
if [[ $? = 0 ]]; then
|
||
RAMINFO="$(jq -r --arg device "$Socname" '.[$device] | "RAM:\(.MEMORY) \(.CHANNELS)"' "$tools_path/soc.json" 2>/dev/null)"
|
||
else
|
||
RAMINFO="RAM:null"
|
||
fi
|
||
else
|
||
DEVICE_NAME="處理器:null"
|
||
RAMINFO="RAM:null"
|
||
fi
|
||
else
|
||
DEVICE_NAME="處理器:null"
|
||
RAMINFO="RAM:null"
|
||
fi
|
||
else
|
||
DEVICE_NAME="處理器:null"
|
||
RAMINFO="RAM:null"
|
||
fi
|
||
echoRgb "---------------------SpeedBackup---------------------"
|
||
echoRgb "腳本路徑:$MODDIR\n -已開機:$(Show_boottime)\n -執行時間:$(date +"%Y-%m-%d %H:%M:%S")\n -busybox路徑:$(which busybox)\n -busybox版本:$(busybox | head -1 | cut -d' ' -f2)\n -腳本版本:$backup_version\n -管理器:$Manager_version\n -品牌:$(getprop ro.product.brand 2>/dev/null)\n -型號:$Device_name($(getprop ro.product.device 2>/dev/null))\n -閃存顆粒:$UFS_MODEL($ROM_TYPE)\n -$DEVICE_NAME\n -$RAMINFO\n -Android版本:$(getprop ro.build.version.release 2>/dev/null) SDK:$(getprop ro.build.version.sdk 2>/dev/null)\n -內核:$(uname -r)\n -Selinux狀態:$([[ $(getenforce) = Permissive ]] && echo "寬容" || echo "嚴格")\n -By@YAWAsau\n -Support: https://jq.qq.com/?_wv=1027&k=f5clPNC3"
|
||
case $MODDIR in
|
||
*Backup_*)
|
||
if [[ -f $MODDIR/app_details.json ]]; then
|
||
if [[ -d ${MODDIR%/*/*}/tools ]]; then
|
||
path_hierarchy="${MODDIR%/*/*}"
|
||
else
|
||
path_hierarchy="${MODDIR%/*}"
|
||
fi
|
||
else
|
||
if [[ -d ${MODDIR%/*}/tools ]]; then
|
||
path_hierarchy="${MODDIR%/*}"
|
||
else
|
||
[[ -d $MODDIR/tools ]] && path_hierarchy="$MODDIR"
|
||
fi
|
||
fi ;;
|
||
*) [[ -d $MODDIR/tools ]] && path_hierarchy="$MODDIR" ;;
|
||
esac
|
||
[[ $LANG = "" ]] && echoRgb "系統無參數語言獲取失敗\n -如果需要更改腳本語言請於$conf_path\n -Shell_LANG=填入對應數字" "0"
|
||
case $LANG in
|
||
*TW* | *tw* | *HK*)
|
||
Script_target_language="zh-TW" ;;
|
||
*CN* | *cn*)
|
||
Script_target_language="zh-CN" ;;
|
||
esac
|
||
echoRgb "$Script_target_language腳本"
|
||
# ======================== Section 4: 用戶檢測與環境別名 ========================
|
||
if [[ ! -f ${0%/*}/app_details.json ]]; then
|
||
if [[ $user = "" ]]; then
|
||
user_id="$(ls /data/user | tr ' ' '\n')"
|
||
if [[ $user_id != "" && $(ls /data/user | tr ' ' '\n' | wc -l) -gt 1 ]]; then
|
||
echo "$user_id" | while read ; do
|
||
[[ $REPLY = 0 ]] && echoRgb "主用戶:$REPLY" "2" || echoRgb "分身用戶:$REPLY" "2"
|
||
done
|
||
echoRgb "設備存在多用戶,選擇操作目標用戶"
|
||
if [[ $(echo "$user_id" | wc -l) = 2 ]]; then
|
||
user1="$(echo "$user_id" | sed -n '1p')"
|
||
user2="$(echo "$user_id" | sed -n '2p')"
|
||
case $Lo in
|
||
0|1)
|
||
echoRgb "音量上選擇用戶:$user1,音量下選擇用戶:$user2" "2"
|
||
Select_user="true"
|
||
get_version "$user1" "$user2" && user="$branch"
|
||
unset Select_user ;;
|
||
2)
|
||
Enter_options "輸入1選擇用戶:$user1 0用戶:$user2" "$user1" "$user2"
|
||
case $parameter in
|
||
0) user="$user2" ;;
|
||
1) user="$user1" ;;
|
||
esac ;;
|
||
esac
|
||
else
|
||
while true ;do
|
||
if [[ $option != "" ]]; then
|
||
user="$option"
|
||
break
|
||
else
|
||
echoRgb "請輸入需要操作目標分區" "1"
|
||
read option
|
||
fi
|
||
done
|
||
fi
|
||
else
|
||
user="0"
|
||
fi
|
||
else
|
||
user_id="$(ls /data/user | tr ' ' '\n')"
|
||
if [[ $user_id != "" && $(ls /data/user | tr ' ' '\n' | wc -l) -gt 1 ]]; then
|
||
echo "$user_id" | while read ; do
|
||
[[ $REPLY = 0 ]] && echoRgb "主用戶:$REPLY" "2" || echoRgb "分身用戶:$REPLY" "2"
|
||
done
|
||
else
|
||
echoRgb "主用戶:$user_id" "2"
|
||
fi
|
||
fi
|
||
else
|
||
case $(echo "${0%}") in
|
||
*zstd*) user="$(echo "${0%}" | sed 's/.*\/Backup_zstd_\([0-9]*\).*/\1/')" ;;
|
||
*tar*) user="$(echo "${0%}" | sed 's/.*\/Backup_tar_\([0-9]*\).*/\1/')" ;;
|
||
*) echoRgb "請勿修改備份資料夾名稱,保持原本的Backup_壓縮算法名稱_使用者id" "0" && exit 2 ;;
|
||
esac
|
||
fi
|
||
[[ $user != 0 ]] && am start-user "$user"
|
||
path="/data/media/$user/Android"
|
||
path2="/data/user/$user"
|
||
path3="/data/user_de/$user"
|
||
[[ ! -d $path2 ]] && echoRgb "$user分區不存在,請將上方提示的用戶id按照需求填入\n -$conf_path配置項user=,一次只能填寫一個" "0" && exit 2
|
||
echoRgb "當前操作為用戶$user"
|
||
export USER_ID="$user"
|
||
unset LD_LIBRARY_PATH
|
||
#因接收USER_ID環境變量問題故將函數放在此處
|
||
alias appinfo="app_process /system/bin com.xayah.dex.HiddenApiUtil getInstalledPackagesAsUser $USER_ID $@"
|
||
alias appinfo2="app_process /system/bin com.xayah.dex.HiddenApiUtil getPackageLabel $USER_ID $@"
|
||
alias appinfo3="app_process /system/bin com.xayah.dex.HiddenApiUtil getPackageArchiveInfo $@"
|
||
alias get_ssaid="app_process /system/bin com.xayah.dex.SsaidUtil get $USER_ID $@"
|
||
alias set_ssaid="app_process /system/bin com.xayah.dex.SsaidUtil set $USER_ID $@"
|
||
alias get_uid="app_process /system/bin com.xayah.dex.HiddenApiUtil getPackageUid $USER_ID $@"
|
||
alias get_Permissions="app_process /system/bin com.xayah.dex.HiddenApiUtil getRuntimePermissions $USER_ID $@"
|
||
alias Set_true_Permissions="app_process /system/bin com.xayah.dex.HiddenApiUtil grantRuntimePermission $USER_ID $@"
|
||
alias Set_false_Permissions="app_process /system/bin com.xayah.dex.HiddenApiUtil revokeRuntimePermission $USER_ID $@"
|
||
alias Set_Ops="app_process /system/bin com.xayah.dex.HiddenApiUtil setOpsMode $USER_ID $@"
|
||
alias setDisplay="app_process /system/bin com.xayah.dex.HiddenApiUtil setDisplayPowerMode $@"
|
||
find_tools_path="$(find "$path_hierarchy"/* -maxdepth 1 -name "tools" -type d ! -path "$path_hierarchy/tools")"
|
||
# ======================== Section 5: WiFi/腳本生成/重命名工具 ========================
|
||
# ======================== Section 6: 腳本更新邏輯 ========================
|
||
update_script
|
||
zipFile="$(ls -t /storage/emulated/0/Download/*.zip 2>/dev/null | head -1)"
|
||
if [[ $(unzip -l "$zipFile" 2>/dev/null | awk '{print $4}' | egrep -wo "^backup_settings.conf$") != "" ]]; then
|
||
update_script
|
||
else
|
||
zipFile="$(ls -t /storage/emulated/0/Android/data/com.tencent.mobileqq/Tencent/QQfile_recv/*.zip 2>/dev/null | head -1)"
|
||
[[ $(unzip -l "$zipFile" 2>/dev/null | awk '{print $4}' | egrep -wo "^backup_settings.conf$") != "" ]] && update_script
|
||
fi
|
||
SDK_V="$(getprop ro.build.version.sdk)"
|
||
if [[ $SDK_V -lt 30 ]]; then
|
||
alias INSTALL="pm install --user $user -r -t >/dev/null"
|
||
alias create="pm install-create --user $user -tl"
|
||
elif [[ $SDK_V -gt 33 ]]; then
|
||
alias INSTALL="pm install -r --bypass-low-target-sdk-block -i com.android.vending --user $user -t >/dev/null"
|
||
alias create="pm install-create -i com.android.vending --bypass-low-target-sdk-block --user $user -t"
|
||
else
|
||
alias INSTALL="pm install -r -i com.android.vending --user $user -t >/dev/null"
|
||
alias create="pm install-create -i com.android.vending --user $user -t"
|
||
fi
|
||
#settings get system system_locales
|
||
Language="https://api.github.com/repos/YAWAsau/backup_script/releases/latest"
|
||
if [[ $path_hierarchy != "" && $Script_target_language != "" ]]; then
|
||
K=1
|
||
J="$(find "$path_hierarchy" -maxdepth 3 -name "tools.sh" -type f | wc -l)"
|
||
find "$path_hierarchy" -maxdepth 3 -name "tools.sh" -type f | while read ; do
|
||
unset shell_language
|
||
shell_language="$(awk -F= '/^shell_language=/ {gsub(/"/, "", $2); print $2}' "$REPLY")"
|
||
case $shell_language in
|
||
zh-CN|zh-TW)
|
||
if [[ $Script_target_language != $shell_language ]]; then
|
||
[[ $K = 1 ]] && echoRgb "腳本語言為$shell_language....轉換為$Script_target_language中,請稍後等待轉換...."
|
||
ts <"$REPLY">temp && cp temp "$REPLY" && rm temp
|
||
if [[ $? = 0 ]]; then
|
||
touch "$TMPDIR/0"
|
||
echo_log "$(echo "$REPLY" | sed "s|^$path_hierarchy/||")翻譯"
|
||
MODDIR="${0%/*}"
|
||
if [[ -f ${REPLY%/*/*}/backup_settings.conf ]]; then
|
||
update_backup_settings_conf>"${REPLY%/*/*}/backup_settings.conf"
|
||
ts <"${REPLY%/*/*}/backup_settings.conf">temp && cp temp "${REPLY%/*/*}/backup_settings.conf" && rm temp
|
||
echo_log "${REPLY%/*/*}/backup_settings.conf翻譯"
|
||
fi
|
||
if [[ -f ${REPLY%/*/*}/restore_settings.conf ]]; then
|
||
update_Restore_settings_conf>"${REPLY%/*/*}/restore_settings.conf"
|
||
ts <"${REPLY%/*/*}/restore_settings.conf">temp && cp temp "${REPLY%/*/*}/restore_settings.conf" && rm temp
|
||
echo_log "${REPLY%/*/*}/restore_settings.conf翻譯"
|
||
fi
|
||
sed "s/shell_language=\"$shell_language\"/shell_language=\"$Script_target_language\"/g" "$REPLY" > temp && cp temp "$REPLY" && rm temp
|
||
[[ $shell_language != $(awk -F= '/^shell_language=/ {gsub(/"/, "", $2); print $2}' "$REPLY") ]] && echoRgb "$(echo "$REPLY" | sed "s|^$path_hierarchy/||")變量修改成功" || echoRgb "$(echo "$REPLY" | sed "s|^$path_hierarchy/||")變量修改失敗" "0"
|
||
ts <"${REPLY%/*}/Device_List">temp && cp temp "${REPLY%/*}/Device_List" && rm temp
|
||
echo_log "${REPLY%/*}/Device_List翻譯"
|
||
[[ $K = 1 ]] && Rename_script
|
||
else
|
||
echoRgb "$REPLY ts進程出現錯誤" "0"
|
||
fi
|
||
K=$((K + 1))
|
||
fi ;;
|
||
esac
|
||
done
|
||
[[ -e $TMPDIR/0 ]] && rm "$TMPDIR/0" && echoRgb "轉換腳本完成,退出腳本重新執行即可使用" && exit 2
|
||
fi
|
||
#校驗選填是否正確
|
||
case $Lo in
|
||
0)
|
||
[[ $update != "" ]] && isBoolean "$update" "update" && update="$nsx" || {
|
||
echoRgb "自動更新腳本?\n -音量上更新,下不更新"
|
||
get_version "更新" "不更新" && update="$branch"
|
||
} ;;
|
||
1)
|
||
[[ $update = "" ]] && {
|
||
echoRgb "自動更新腳本?\n -音量上更新,下不更新"
|
||
get_version "更新" "不更新" && update="$branch"
|
||
} || isBoolean "$update" "update" && update="$nsx" ;;
|
||
2)
|
||
[[ $update = "" ]] && {
|
||
Enter_options "輸入1自動更新腳本,輸入0不自動更新腳本" "更新" "不更新" && isBoolean "$parameter" "update" && update="$nsx"
|
||
} || {
|
||
isBoolean "$update" "update" && update="$nsx"
|
||
} ;;
|
||
*) echoRgb "$conf_path Lo=$Lo填寫錯誤,正確值0 1 2" "0" && exit 2 ;;
|
||
esac
|
||
if [[ $update = true ]]; then
|
||
json="$(down "$Language")"
|
||
else
|
||
echoRgb "自動更新被關閉" "0"
|
||
fi
|
||
if [[ $json != "" ]]; then
|
||
tag="$(jq -r '.tag_name'<<< "$json" 2>/dev/null)"
|
||
if [[ $tag != "" && $backup_version != $tag ]]; then
|
||
if [[ $(expr "$(echo "$backup_version" | tr -d "a-zA-Z")" \> "$(echo "$tag" | tr -d "a-zA-Z")") -eq 0 ]]; then
|
||
download="$(jq -r '.assets[].browser_download_url'<<< "$json")"
|
||
case $cdn in
|
||
0) zip_url="$download" ;;
|
||
1) zip_url="https://ghfast.top/$download" ;;
|
||
2) zip_url="https://shrill-pond-3e81.hunsh.workers.dev/$download" ;;
|
||
*) echoRgb "$conf_path cdn=設置錯誤 範圍只能是0-2" && exit 2 ;;
|
||
esac
|
||
if [[ $(expr "$(echo "$backup_version" | tr -d "a-zA-Z")" \> "$(echo "$download" | tr -d "a-zA-Z")") -eq 0 ]]; then
|
||
echoRgb "發現新版本:$tag"
|
||
if [[ $update = true ]]; then
|
||
echoRgb "$(ts "更新日誌:\n$(down "$Language" | jq -r '.body')")"
|
||
case $Lo in
|
||
0|1)
|
||
echoRgb "是否更新腳本?\n -音量上更新,音量下不更新" "2"
|
||
get_version "更新" "不更新" && choose="$branch" ;;
|
||
2)
|
||
Enter_options "輸入1自動更新腳本,輸入0不自動更新腳本" "更新" "不更新" && isBoolean "$parameter" "update" && update="$nsx" ;;
|
||
esac
|
||
if [[ $choose = true ]]; then
|
||
echoRgb "下載中.....耐心等待 如果下載失敗請掛飛機"
|
||
starttime1="$(date -u "+%s")"
|
||
down "$zip_url" >"$MODDIR/update.zip" &
|
||
wait
|
||
endtime 1
|
||
[[ ! -f $MODDIR/update.zip ]] && echoRgb "下載失敗" && exit 2
|
||
zipFile="$MODDIR/update.zip"
|
||
fi
|
||
else
|
||
echoRgb "$conf_path內update選項為0忽略更新僅提示更新" "0"
|
||
fi
|
||
fi
|
||
fi
|
||
fi
|
||
else
|
||
[[ $update = true ]] && echoRgb "更新獲取失敗" "0"
|
||
fi
|
||
update_script
|
||
# ======================== Section 7: 備份路徑/分區/APK/SSAID/權限 ========================
|
||
# ======================== Section 8: 數據備份與恢復核心 ========================
|
||
# ======================== Section 9: 應用列表管理與進程檢測 ========================
|
||
Background_application_list debug
|
||
pkgs="$(pm list packages --user "$user" | cut -f2 -d ':' | awk -v pkg="$(echo "$Backstage" | head -1)" '$1 == pkg {print $1}')"
|
||
if [[ $pkgs != "" ]]; then
|
||
echoRgb "後台應用獲取成功($pkgs)" "1"
|
||
[[ $(Process_Information "$pkgs") = "" ]] && echoRgb "應用pid獲取失敗" "0" || echoRgb "應用pid獲取成功$(Process_Information "$pkgs")" "1"
|
||
else
|
||
echoRgb "後台應用獲取失敗" "0" activity=false
|
||
fi
|
||
unset Backstage
|
||
# ======================== Section 10: 備份主流程 ========================
|
||
# ======================== Section 11: 恢復主流程 ========================
|
||
# ======================== Section 12: 應用列表生成 ========================
|
||
# ======================== Section 13: 入口分發 ========================
|
||
if [[ $0 = *backup.sh ]]; then
|
||
start=backup
|
||
else
|
||
[[ $0 = *recover.sh ]] && start=Restore
|
||
fi
|
||
if [[ $start != "" ]]; then
|
||
case $(grep -o 'background_execution=.*' "$conf_path" | awk -F '=' '{print $2}') in
|
||
0)
|
||
eval "$start" ;;
|
||
1)
|
||
{
|
||
eval "$start"
|
||
} & ;;
|
||
esac
|
||
else
|
||
if [[ -f $MODDIR/backup_settings.conf ]]; then
|
||
steps=(
|
||
"生成應用列表"
|
||
"備份應用"
|
||
"備份已更新應用"
|
||
"備份自定義資料夾"
|
||
"備份WiFi"
|
||
"殺死運行中腳本"
|
||
)
|
||
commands=(
|
||
"Getlist"
|
||
"backup"
|
||
"backup_update_apk"
|
||
"backup_media"
|
||
"wifi"
|
||
"echoRgb '等待腳本停止中,請稍後.....' && echoRgb '腳本終止'; exit"
|
||
)
|
||
elif [[ -f $MODDIR/restore_settings.conf ]]; then
|
||
steps=(
|
||
"重新生成應用列表"
|
||
"恢復備份"
|
||
"僅恢復包含ssaid應用(含數據)"
|
||
"僅恢復包含ssaid應用(不含數據)"
|
||
"恢復自定義資料夾"
|
||
"恢復wifi"
|
||
"壓縮檔完整性檢查"
|
||
"轉換文件夾名稱"
|
||
"殺死運行中腳本"
|
||
)
|
||
commands=(
|
||
"dumpname"
|
||
"Restore"
|
||
"ssaid_mode=true && Restore"
|
||
"ssaid_mode_1=true && Restore4"
|
||
"Restore3"
|
||
"recover_wifi \"$MODDIR/wifi\""
|
||
"check_file"
|
||
"convert"
|
||
"echoRgb '等待腳本停止中,請稍後.....' && echoRgb '腳本終止'; exit"
|
||
)
|
||
fi
|
||
echoRgb "請選擇要執行的操作:"
|
||
for i in "${!steps[@]}"; do
|
||
printf "%d) %s\n" "$((i+1))" "${steps[$i]}"
|
||
done
|
||
echo "x) 離開腳本"
|
||
echo -n "請輸入選項編號: "
|
||
read choice
|
||
case $choice in
|
||
x|X)
|
||
echoRgb "已退出腳本" "0"
|
||
exit 0 ;;
|
||
[1-9])
|
||
if (( choice >= 1 && choice <= ${#steps[@]} )); then
|
||
index=$((choice - 1))
|
||
echo "執行:${steps[$index]}"
|
||
background=$(grep -o 'background_execution=.*' "$conf_path" | awk -F '=' '{print $2}')
|
||
if [[ "$background" = "1" ]]; then
|
||
eval "${commands[$index]}" &
|
||
else
|
||
eval "${commands[$index]}"
|
||
fi
|
||
else
|
||
echoRgb "超出功能選項範圍(1-${#steps[@]})" "0"
|
||
fi
|
||
;;
|
||
*)
|
||
echoRgb "輸入錯誤,請重新輸入有效的數字或輸入 x 離開。" "0" ;;
|
||
esac
|
||
fi |