mirror of
https://github.com/kuaifan/dootask.git
synced 2026-07-01 20:05:05 +00:00
feat: 新增 bin/install 一键安装/升级脚本并支持 CLI 双语
- bin/install:curl 一行命令按当前目录自动判断 空目录安装 / 续装 / 升级;升级时取线上最新 cmd 执行,规避旧 cmd 导致的两次升级;输出按 locale 中英双语,判空时忽略系统垃圾文件 - cmd:所有用户可见输出按 locale 中英双语(msg 查表 + (*) 占位),业务逻辑不变 - README / README_CN:安装段补充一键脚本命令、升级段补充一键命令并移除升级重试提示;删除 0.x 迁移到 1.x 章节 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
0896f09878
commit
e5a88c2957
27
README.md
27
README.md
@ -9,14 +9,6 @@ English | **[中文文档](./README_CN.md)**
|
||||
|
||||
- Group Number: `546574618`
|
||||
|
||||
## 📍 Migration from 0.x to 1.x
|
||||
|
||||
- Please ensure to back up your data before upgrading!
|
||||
- If the upgrade fails, try running `./cmd update` multiple times.
|
||||
- If you encounter "Container xxx not found" during upgrade, run `./cmd reup` and then execute `./cmd update`.
|
||||
- If you see a 502 error after upgrading, run `./cmd reup` to restart the services.
|
||||
- If you encounter "Application 'xxx' not installed" after upgrading, log in with the admin account and install the relevant applications from the App Store.
|
||||
|
||||
## Installation Requirements
|
||||
|
||||
- Required: `Docker v20.10+` and `Docker Compose v2.0+`
|
||||
@ -27,6 +19,16 @@ English | **[中文文档](./README_CN.md)**
|
||||
|
||||
### Deploy Project
|
||||
|
||||
**Option 1: One-line script (recommended)**
|
||||
|
||||
Run it in an empty directory to clone and install automatically; run it inside an existing installation to check and upgrade:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/kuaifan/dootask/pro/bin/install | bash
|
||||
```
|
||||
|
||||
**Option 2: Manual deployment**
|
||||
|
||||
```bash
|
||||
# 1、Clone the project to your local machine or server
|
||||
|
||||
@ -105,11 +107,18 @@ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
**Note: Please backup your data before upgrading!**
|
||||
|
||||
Recommended: use the one-line script (run it inside an existing installation; it pulls the latest code and finishes the upgrade in a single run):
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/kuaifan/dootask/pro/bin/install | bash
|
||||
```
|
||||
|
||||
Or use the local command:
|
||||
|
||||
```bash
|
||||
./cmd update
|
||||
```
|
||||
|
||||
* Please retry if upgrade fails across major versions.
|
||||
* If you encounter 502 errors after upgrade, run `./cmd reup` to restart services.
|
||||
|
||||
## Project Migration
|
||||
|
||||
27
README_CN.md
27
README_CN.md
@ -9,14 +9,6 @@
|
||||
|
||||
- QQ群号: `546574618`
|
||||
|
||||
## 📍 0.x 迁移到 1.x
|
||||
|
||||
- 升级时请务必备份好数据!
|
||||
- 如果升级失败请尝试执行 `./cmd update` 重试几次。
|
||||
- 如果升级中出现 `没有找到 xxx 容器` 的提示,请运行 `./cmd reup` 后再执行 `./cmd update`。
|
||||
- 如果升级后出现502错误请运行 `./cmd reup` 重启服务即可。
|
||||
- 如果升级后出现 `应用「xxx」未安装` 的提示,请使用管理员账号进入应用商店安装相关应用。
|
||||
|
||||
## 安装程序
|
||||
|
||||
- 必须安装:`Docker v20.10+` 和 `Docker Compose v2.0+`
|
||||
@ -27,6 +19,16 @@
|
||||
|
||||
### 部署项目
|
||||
|
||||
**方式一:一键脚本(推荐)**
|
||||
|
||||
在空目录中执行即自动克隆并安装;在已安装目录中执行则自动检查并升级:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/kuaifan/dootask/pro/bin/install | bash
|
||||
```
|
||||
|
||||
**方式二:手动部署**
|
||||
|
||||
```bash
|
||||
# 1、克隆项目到您的本地或服务器
|
||||
|
||||
@ -105,11 +107,18 @@ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
**注意:在升级之前请备份好你的数据!**
|
||||
|
||||
推荐使用一键脚本升级(在已安装目录中执行,自动拉取最新代码并完成升级,无需重复执行):
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/kuaifan/dootask/pro/bin/install | bash
|
||||
```
|
||||
|
||||
或使用本地命令:
|
||||
|
||||
```bash
|
||||
./cmd update
|
||||
```
|
||||
|
||||
* 跨越大版本升级失败时请重试执行一次。
|
||||
* 如果升级后出现502请运行 `./cmd reup` 重启服务即可。
|
||||
|
||||
## 迁移项目
|
||||
|
||||
296
bin/install
Executable file
296
bin/install
Executable file
@ -0,0 +1,296 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# DooTask 一键安装 / 升级脚本
|
||||
#
|
||||
# 用法(在目标目录执行):
|
||||
# curl -fsSL https://raw.githubusercontent.com/kuaifan/dootask/pro/bin/install | bash
|
||||
#
|
||||
# 脚本会根据「当前目录」自动判断该做什么,无需额外参数:
|
||||
# - 空目录 : 全新安装(克隆代码到当前目录 + ./cmd install)
|
||||
# - 已克隆但未安装 : 继续安装(./cmd install)
|
||||
# - 已安装 : 检查更新,确认后用「线上最新 cmd」执行升级
|
||||
# - 非空且不是 DooTask : 拒绝操作并提示(绝不在此克隆或重置)
|
||||
#
|
||||
# 升级一次到位的关键:升级时从「线上 raw」取最新 cmd 到临时文件执行,
|
||||
# 既不依赖用户机器上那份可能过时的 cmd,也不写本地 .git(规避属主/权限问题),
|
||||
# 真正的 git pull / 依赖 / 迁移 / 重启全部交给这份最新 cmd,避免「升两次」。
|
||||
#
|
||||
# 输出语言:仅当 locale 明确是中文 UTF-8 时显示中文,否则一律英文。
|
||||
#
|
||||
|
||||
set -u
|
||||
|
||||
# ---------- 配置 ----------
|
||||
BRANCH="pro" # 全新安装默认分支(升级时跟随当前分支)
|
||||
REPO_GITHUB="https://github.com/kuaifan/dootask.git"
|
||||
REPO_GITEE="https://gitee.com/aipaw/dootask.git"
|
||||
# raw 基址:升级时取版本号与最新 cmd 用。后期可把 RAW_PRIMARY 换成官网映射的域名。
|
||||
RAW_PRIMARY="https://raw.githubusercontent.com/kuaifan/dootask" # https://<base>/<branch>/<path>
|
||||
RAW_FALLBACK="https://cdn.jsdelivr.net/gh/kuaifan/dootask" # https://<base>@<branch>/<path>
|
||||
|
||||
# ---------- 语言判定 ----------
|
||||
# 默认英文;仅当 locale 明确是「中文 UTF-8」时才用中文(中文非 UTF-8 如 GBK 也用英文以免乱码)。
|
||||
DT_LANG="en"
|
||||
__loc="${LC_ALL:-${LC_MESSAGES:-${LANG:-}}}"
|
||||
case "$__loc" in
|
||||
zh_*|zh-*|zh)
|
||||
case "$__loc" in
|
||||
*[Uu][Tt][Ff]*) DT_LANG="zh" ;; # 明确 UTF-8 → 中文
|
||||
*.*) DT_LANG="en" ;; # 其他编码(如 .GBK)→ 英文,避免乱码
|
||||
*) DT_LANG="zh" ;; # 无编码后缀(裸 zh_CN)→ 现代默认 UTF-8
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
unset __loc
|
||||
|
||||
# ---------- 文案 ----------
|
||||
# 调用处只写中文(动态值用 (*) 占位,顺序对应后续参数,与前端 $L 风格一致)。
|
||||
# 中文环境直接用原文;英文环境在此集中查表翻译,未登记的中文原样返回。
|
||||
msg() {
|
||||
local tpl="$1"; shift
|
||||
local out="$tpl"
|
||||
if [ "$DT_LANG" != "zh" ]; then
|
||||
case "$tpl" in
|
||||
"成功") out="OK" ;;
|
||||
"警告") out="WARN" ;;
|
||||
"错误") out="ERROR" ;;
|
||||
"未知") out="unknown" ;;
|
||||
"git 未安装,请先安装后重试")
|
||||
out="git is not installed. Please install it and retry." ;;
|
||||
"curl 未安装,请先安装后重试")
|
||||
out="curl is not installed. Please install it and retry." ;;
|
||||
"Docker 未安装,请先安装后重试")
|
||||
out="Docker is not installed. Please install it and retry." ;;
|
||||
"docker-compose(或 docker compose 插件)未安装,请先安装后重试")
|
||||
out="docker-compose (or the docker compose plugin) is not installed. Please install it and retry." ;;
|
||||
"当前目录为空,开始全新安装 DooTask ...")
|
||||
out="Current directory is empty. Starting a fresh DooTask installation..." ;;
|
||||
"克隆代码(GitHub)...")
|
||||
out="Cloning source (GitHub)..." ;;
|
||||
"GitHub 克隆失败,尝试 Gitee 镜像 ...")
|
||||
out="GitHub clone failed, trying the Gitee mirror..." ;;
|
||||
"代码克隆失败,请检查网络后重试")
|
||||
out="Failed to clone the source. Please check your network and retry." ;;
|
||||
"代码克隆完成")
|
||||
out="Source cloned." ;;
|
||||
"执行安装 ...")
|
||||
out="Running installation..." ;;
|
||||
"DooTask 安装完成")
|
||||
out="DooTask installation complete." ;;
|
||||
"检测到已克隆但尚未安装,执行安装 ...")
|
||||
out="Repository found but not yet installed. Running installation..." ;;
|
||||
"检测到已安装的 DooTask,正在检查更新 ...")
|
||||
out="Existing DooTask installation detected. Checking for updates..." ;;
|
||||
"无法获取远程版本信息(分支 (*)),请检查网络后重试")
|
||||
out="Unable to fetch remote version info (branch (*)). Please check your network and retry." ;;
|
||||
"当前已是最新版本(v(*))")
|
||||
out="Already up to date (v(*))." ;;
|
||||
"发现新版本:当前 v(*) → 最新 v(*)(分支 (*))")
|
||||
out="New version available: current v(*) -> latest v(*) (branch (*))." ;;
|
||||
"是否立即升级?")
|
||||
out="Upgrade now?" ;;
|
||||
"已取消升级")
|
||||
out="Upgrade cancelled." ;;
|
||||
"获取最新 cmd 失败,请检查网络后重试")
|
||||
out="Failed to fetch the latest cmd. Please check your network and retry." ;;
|
||||
"开始升级 ...")
|
||||
out="Starting upgrade..." ;;
|
||||
"DooTask 升级完成")
|
||||
out="DooTask upgrade complete." ;;
|
||||
"当前目录非空,且不是 DooTask 项目目录。")
|
||||
out="Current directory is not empty and is not a DooTask project." ;;
|
||||
"请在「空目录」中执行全新安装,或进入「已安装的 DooTask 目录」执行升级。")
|
||||
out="Run this in an empty directory for a fresh install, or inside an existing DooTask directory to upgrade." ;;
|
||||
esac
|
||||
fi
|
||||
# 动态值:依次把 (*) 替换为参数
|
||||
local a
|
||||
for a in "$@"; do
|
||||
out="${out/(\*)/$a}"
|
||||
done
|
||||
printf '%s' "$out"
|
||||
}
|
||||
|
||||
# ---------- 输出 ----------
|
||||
if [ -t 1 ]; then
|
||||
Red="\033[31m"; Green="\033[32m"; Yellow="\033[33m"; Blue="\033[36m"; Font="\033[0m"
|
||||
else
|
||||
Red=""; Green=""; Yellow=""; Blue=""; Font=""
|
||||
fi
|
||||
info() { echo -e "${Blue}==>${Font} $1"; }
|
||||
success() { echo -e "${Green}[$(msg 成功)]${Font} $1"; }
|
||||
warning() { echo -e "${Yellow}[$(msg 警告)]${Font} $1"; }
|
||||
error() { echo -e "${Red}[$(msg 错误)]${Font} $1" >&2; }
|
||||
die() { error "$1"; exit 1; }
|
||||
|
||||
# ---------- 交互输入 ----------
|
||||
# curl | bash 时 stdin 被管道占用,交互一律从 /dev/tty 读,否则 read 会读到 EOF
|
||||
has_tty() { [ -e /dev/tty ]; }
|
||||
|
||||
confirm() {
|
||||
# $1=提示语,默认 Y;无终端时返回失败(不擅自执行需确认的操作)
|
||||
local prompt="$1" ans
|
||||
has_tty || return 1
|
||||
read -r -p "$prompt [Y/n] " ans < /dev/tty
|
||||
[[ -z "$ans" || "$ans" =~ ^[Yy]([Ee][Ss])?$ ]]
|
||||
}
|
||||
|
||||
# ---------- 提权执行 ----------
|
||||
# install / update 需要 root;统一用 bash 执行脚本(规避 /tmp noexec),
|
||||
# 交互(含 cmd 内部的 read 与 sudo 密码)接到 /dev/tty。
|
||||
# git clone 不走这里,用当前用户执行,避免代码属主变成 root。
|
||||
run_cmd() {
|
||||
local script="$1"; shift
|
||||
local stdin_src="/dev/stdin"
|
||||
has_tty && stdin_src="/dev/tty"
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
bash "$script" "$@" < "$stdin_src"
|
||||
else
|
||||
sudo bash "$script" "$@" < "$stdin_src"
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------- 前置检查 ----------
|
||||
precheck() {
|
||||
command -v git >/dev/null 2>&1 || die "$(msg 'git 未安装,请先安装后重试')"
|
||||
command -v curl >/dev/null 2>&1 || die "$(msg 'curl 未安装,请先安装后重试')"
|
||||
command -v docker >/dev/null 2>&1 || die "$(msg 'Docker 未安装,请先安装后重试')"
|
||||
if ! docker compose version >/dev/null 2>&1 && ! docker-compose version >/dev/null 2>&1; then
|
||||
die "$(msg 'docker-compose(或 docker compose 插件)未安装,请先安装后重试')"
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------- 工具 ----------
|
||||
# 从 raw 取「指定分支的文件」到 stdout:主源失败时回退 jsdelivr 镜像
|
||||
fetch_raw() {
|
||||
# $1=branch, $2=path
|
||||
curl -fsSL "${RAW_PRIMARY}/$1/$2" 2>/dev/null \
|
||||
|| curl -fsSL "${RAW_FALLBACK}@$1/$2" 2>/dev/null
|
||||
}
|
||||
|
||||
# 从 stdin 读取 package.json 内容并提取版本号
|
||||
read_pkg_version() {
|
||||
grep -m1 '"version"' | sed -E 's/.*"version"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/'
|
||||
}
|
||||
|
||||
is_dootask_project() {
|
||||
# 只读 .git,不写;当前用户读取一般文件不受属主影响
|
||||
if [ -d .git ] && git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
local url; url="$(git config --get remote.origin.url 2>/dev/null || true)"
|
||||
[[ "$url" == *dootask* ]] && return 0
|
||||
fi
|
||||
[ -f cmd ] && [ -f docker-compose.yml ] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
is_installed() { [ -f vendor/autoload.php ]; }
|
||||
|
||||
# 可忽略的系统垃圾文件(判断空目录时忽略;全新安装前会清除以便 git clone .)
|
||||
_IGNORABLE=".DS_Store .localized .Spotlight-V100 .fseventsd .TemporaryItems .Trashes .DocumentRevisions-V100 .VolumeIcon.icns .AppleDouble .AppleDB .AppleDesktop Thumbs.db ehthumbs.db desktop.ini .directory"
|
||||
|
||||
# 是否「可忽略的系统文件」(含 macOS AppleDouble 的 ._xxx)
|
||||
_is_ignorable() {
|
||||
case " $_IGNORABLE " in *" $1 "*) return 0 ;; esac
|
||||
case "$1" in ._*) return 0 ;; esac
|
||||
return 1
|
||||
}
|
||||
|
||||
# 当前目录是否「实质为空」:只剩可忽略的系统垃圾文件也算空
|
||||
dir_empty() {
|
||||
local f
|
||||
while IFS= read -r f; do
|
||||
_is_ignorable "${f##*/}" || return 1
|
||||
done < <(find . -maxdepth 1 -mindepth 1 2>/dev/null)
|
||||
return 0
|
||||
}
|
||||
|
||||
# 清除可忽略的系统垃圾文件(仅白名单),确保 git clone . 不被这些文件挡住
|
||||
clean_ignorable() {
|
||||
local f
|
||||
while IFS= read -r f; do
|
||||
_is_ignorable "${f##*/}" && rm -rf "$f"
|
||||
done < <(find . -maxdepth 1 -mindepth 1 2>/dev/null)
|
||||
}
|
||||
|
||||
current_branch() { git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "$BRANCH"; }
|
||||
|
||||
# ---------- 动作:全新安装 ----------
|
||||
do_fresh_install() {
|
||||
info "$(msg '当前目录为空,开始全新安装 DooTask ...')"
|
||||
clean_ignorable # 清掉 .DS_Store 等系统垃圾,确保 git clone . 不被挡住
|
||||
info "$(msg '克隆代码(GitHub)...')"
|
||||
if ! git clone --depth=1 --branch "$BRANCH" "$REPO_GITHUB" . 2>/dev/null; then
|
||||
warning "$(msg 'GitHub 克隆失败,尝试 Gitee 镜像 ...')"
|
||||
rm -rf .git # 仅清理 clone 残留;若工作树仍有残留,下一步 clone 会报错而非误删
|
||||
git clone --depth=1 --branch "$BRANCH" "$REPO_GITEE" . \
|
||||
|| die "$(msg '代码克隆失败,请检查网络后重试')"
|
||||
fi
|
||||
success "$(msg '代码克隆完成')"
|
||||
info "$(msg '执行安装 ...')"
|
||||
run_cmd ./cmd install
|
||||
success "$(msg 'DooTask 安装完成')"
|
||||
}
|
||||
|
||||
# ---------- 动作:续装 ----------
|
||||
do_install() {
|
||||
info "$(msg '检测到已克隆但尚未安装,执行安装 ...')"
|
||||
run_cmd ./cmd install
|
||||
success "$(msg 'DooTask 安装完成')"
|
||||
}
|
||||
|
||||
# ---------- 动作:升级 ----------
|
||||
do_upgrade() {
|
||||
info "$(msg '检测到已安装的 DooTask,正在检查更新 ...')"
|
||||
local branch; branch="$(current_branch)"
|
||||
|
||||
local local_ver remote_ver
|
||||
local_ver="$( [ -f package.json ] && read_pkg_version < package.json )"
|
||||
remote_ver="$(fetch_raw "$branch" package.json | read_pkg_version)"
|
||||
[ -z "$local_ver" ] && local_ver="$(msg 未知)"
|
||||
|
||||
# 取不到远程版本(网络/分支异常)→ 报错,避免误判
|
||||
[ -z "$remote_ver" ] && die "$(msg '无法获取远程版本信息(分支 (*)),请检查网络后重试' "$branch")"
|
||||
|
||||
if [ "$local_ver" = "$remote_ver" ]; then
|
||||
success "$(msg '当前已是最新版本(v(*))' "$local_ver")"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo
|
||||
info "$(msg '发现新版本:当前 v(*) → 最新 v(*)(分支 (*))' "$local_ver" "$remote_ver" "$branch")"
|
||||
if ! confirm "$(msg '是否立即升级?')"; then
|
||||
warning "$(msg '已取消升级')"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 从 raw 取「线上最新 cmd」到临时文件执行:不碰本地 .git、不依赖磁盘旧 cmd,
|
||||
# 真正的 git pull / 装依赖 / 迁移 / 重启由这份最新 cmd 完成,一次到位。
|
||||
local tmp; tmp="$(mktemp)"
|
||||
if ! fetch_raw "$branch" cmd > "$tmp" || [ ! -s "$tmp" ]; then
|
||||
rm -f "$tmp"; die "$(msg '获取最新 cmd 失败,请检查网络后重试')"
|
||||
fi
|
||||
info "$(msg '开始升级 ...')"
|
||||
run_cmd "$tmp" update
|
||||
rm -f "$tmp"
|
||||
success "$(msg 'DooTask 升级完成')"
|
||||
}
|
||||
|
||||
# ---------- 主流程 ----------
|
||||
main() {
|
||||
precheck
|
||||
if is_dootask_project; then
|
||||
if is_installed; then
|
||||
do_upgrade
|
||||
else
|
||||
do_install
|
||||
fi
|
||||
elif dir_empty; then
|
||||
do_fresh_install
|
||||
else
|
||||
error "$(msg '当前目录非空,且不是 DooTask 项目目录。')"
|
||||
error "$(msg '请在「空目录」中执行全新安装,或进入「已安装的 DooTask 目录」执行升级。')"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
289
cmd
289
cmd
@ -9,10 +9,104 @@ YellowBG="\033[43;37m"
|
||||
RedBG="\033[41;37m"
|
||||
Font="\033[0m"
|
||||
|
||||
# 语言判定:默认英文;仅当 locale 明确是「中文 UTF-8」时才用中文(中文非 UTF-8 如 GBK 也用英文以免乱码)。
|
||||
DT_LANG="en"
|
||||
__loc="${LC_ALL:-${LC_MESSAGES:-${LANG:-}}}"
|
||||
case "$__loc" in
|
||||
zh_*|zh-*|zh)
|
||||
case "$__loc" in
|
||||
*[Uu][Tt][Ff]*) DT_LANG="zh" ;;
|
||||
*.*) DT_LANG="en" ;;
|
||||
*) DT_LANG="zh" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
unset __loc
|
||||
|
||||
# 文案:调用处只写中文(动态值用 (*) 占位,顺序对应后续参数)。
|
||||
# 中文环境直接用原文;英文环境在此集中查表翻译,未登记的中文原样返回。
|
||||
msg() {
|
||||
local tpl="$1"; shift
|
||||
local out="$tpl"
|
||||
if [ "$DT_LANG" != "zh" ]; then
|
||||
case "$tpl" in
|
||||
"警告") out="WARN" ;;
|
||||
"错误") out="ERROR" ;;
|
||||
"地址") out="URL" ;;
|
||||
"(*) 完成") out="(*) done" ;;
|
||||
"(*) 失败") out="(*) failed" ;;
|
||||
"备份数据库") out="Backing up database" ;;
|
||||
"还原数据库") out="Restoring database" ;;
|
||||
"无法创建脚本副本") out="Failed to create script copy" ;;
|
||||
"没有找到 (*) 容器!") out="Container (*) not found!" ;;
|
||||
"请使用 sudo 运行此脚本") out="Please run this script with sudo" ;;
|
||||
"未安装 Docker!") out="Docker is not installed!" ;;
|
||||
"未安装 Docker-compose!") out="Docker-compose is not installed!" ;;
|
||||
"Docker-compose 版本过低,请升级至v2+!") out="Docker-compose is too old. Please upgrade to v2+!" ;;
|
||||
"未安装 npm!") out="npm is not installed!" ;;
|
||||
"未安装 Node.js!") out="Node.js is not installed!" ;;
|
||||
"Node.js 版本过低,请升级至v20+!") out="Node.js is too old. Please upgrade to v20+!" ;;
|
||||
"备份文件:(*)") out="Backup file: (*)" ;;
|
||||
"没有备份文件!") out="No backup files found!" ;;
|
||||
"可用备份列表:") out="Available backups:" ;;
|
||||
"请输入备份文件编号还原:") out="Enter the backup number to restore: " ;;
|
||||
"编号无效,请重新输入。") out="Invalid number, please try again." ;;
|
||||
"HTTP服务端口不是80,是否修改并继续操作? [Y/n]") out="HTTP port is not 80. Change it and continue? [Y/n]" ;;
|
||||
"HTTPS服务端口不是443,是否修改并继续操作? [Y/n]") out="HTTPS port is not 443. Change it and continue? [Y/n]" ;;
|
||||
"继续操作") out="Continuing" ;;
|
||||
"操作终止") out="Operation aborted" ;;
|
||||
"任务已存在,无需添加。") out="Cron job already exists, skipped." ;;
|
||||
"任务已添加。") out="Cron job added." ;;
|
||||
"设置env参数失败!") out="Failed to set env variable!" ;;
|
||||
"APP_ID((*))已被其他实例使用:(*)") out="APP_ID ((*)) is already used by another instance: (*)" ;;
|
||||
"请先清空 .env 中的 APP_ID 和 APP_IPPR 再重新安装") out="Please clear APP_ID and APP_IPPR in .env, then reinstall" ;;
|
||||
"端口 (*) 已被占用,请指定其他端口") out="Port (*) is already in use, please specify another port" ;;
|
||||
"目录权限检测失败!请检查目录权限设置") out="Directory permission check failed! Please check directory permissions" ;;
|
||||
"目录【(*)】权限不足!") out="Directory [(*)] is not writable!" ;;
|
||||
"安装依赖失败") out="Failed to install dependencies" ;;
|
||||
"安装依赖失败,请重试!") out="Failed to install dependencies, please retry!" ;;
|
||||
"生成密钥失败") out="Failed to generate app key" ;;
|
||||
"数据库迁移失败") out="Database migration failed" ;;
|
||||
"安装完成") out="Installation complete" ;;
|
||||
"请先执行安装命令") out="Please run the install command first" ;;
|
||||
"检测到本地修改,是否强制更新?[Y/n]") out="Local changes detected. Force update? [Y/n]" ;;
|
||||
"取消更新,请先处理本地修改") out="Update cancelled, please handle local changes first" ;;
|
||||
"获取远程更新失败") out="Failed to fetch remote updates" ;;
|
||||
"设置远程Fetch配置失败") out="Failed to set remote fetch config" ;;
|
||||
"获取远程分支 (*) 失败") out="Failed to fetch remote branch (*)" ;;
|
||||
"切换分支到 (*) 失败") out="Failed to switch to branch (*)" ;;
|
||||
"数据库有迁移变动,执行数据库备份...") out="Database migrations changed, backing up database..." ;;
|
||||
"数据库备份失败") out="Database backup failed" ;;
|
||||
"数据库备份完成") out="Database backup complete" ;;
|
||||
"强制更新代码失败") out="Failed to force-update code" ;;
|
||||
"代码拉取失败,可能存在冲突,请使用 --force 参数") out="Failed to pull code (possible conflict), please use --force" ;;
|
||||
"更新PHP依赖失败") out="Failed to update PHP dependencies" ;;
|
||||
"执行数据库备份...") out="Backing up database..." ;;
|
||||
"重启服务失败") out="Failed to restart services" ;;
|
||||
"更新完成") out="Update complete" ;;
|
||||
"警告:此操作将永久删除以下内容:") out="WARNING: This will permanently delete:" ;;
|
||||
"- 数据库") out="- Database" ;;
|
||||
"- 应用程序") out="- Application" ;;
|
||||
"- 日志文件") out="- Log files" ;;
|
||||
"确认要继续卸载吗?(y/N): ") out="Confirm uninstall? (y/N): " ;;
|
||||
"开始卸载...") out="Uninstalling..." ;;
|
||||
"终止卸载。") out="Uninstall aborted." ;;
|
||||
"卸载完成") out="Uninstall complete" ;;
|
||||
"修改成功") out="Changed successfully" ;;
|
||||
esac
|
||||
fi
|
||||
# 动态值:依次把 (*) 替换为参数
|
||||
local a
|
||||
for a in "$@"; do
|
||||
out="${out/(\*)/$a}"
|
||||
done
|
||||
printf '%s' "$out"
|
||||
}
|
||||
|
||||
# 通知信息
|
||||
OK="${Green}[OK]${Font}"
|
||||
Warn="${Yellow}[警告]${Font}"
|
||||
Error="${Red}[错误]${Font}"
|
||||
Warn="${Yellow}[$(msg 警告)]${Font}"
|
||||
Error="${Red}[$(msg 错误)]${Font}"
|
||||
|
||||
# 基本参数
|
||||
WORK_DIR="$(pwd)"
|
||||
@ -28,7 +122,7 @@ fi
|
||||
# 缓存执行
|
||||
if [ -z "$CACHED_EXECUTION" ] && [ "$1" == "update" ]; then
|
||||
if ! cat "$0" > ._cmd 2>/dev/null; then
|
||||
error "无法创建脚本副本"
|
||||
error "$(msg '无法创建脚本副本')"
|
||||
exit 1
|
||||
fi
|
||||
chmod +x ._cmd
|
||||
@ -42,10 +136,10 @@ fi
|
||||
# 判断是否成功
|
||||
judge() {
|
||||
if [[ 0 -eq $? ]]; then
|
||||
success "$1 完成"
|
||||
success "$(msg '(*) 完成' "$1")"
|
||||
sleep 1
|
||||
else
|
||||
error "$1 失败"
|
||||
error "$(msg '(*) 失败' "$1")"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
@ -128,7 +222,7 @@ switch_debug() {
|
||||
# 检查是否有sudo
|
||||
check_sudo() {
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
error "请使用 sudo 运行此脚本"
|
||||
error "$(msg '请使用 sudo 运行此脚本')"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
@ -137,21 +231,21 @@ check_sudo() {
|
||||
check_docker() {
|
||||
docker --version &> /dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
error "未安装 Docker!"
|
||||
error "$(msg '未安装 Docker!')"
|
||||
exit 1
|
||||
fi
|
||||
docker-compose version &> /dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
docker compose version &> /dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
error "未安装 Docker-compose!"
|
||||
error "$(msg '未安装 Docker-compose!')"
|
||||
exit 1
|
||||
fi
|
||||
COMPOSE="docker compose"
|
||||
fi
|
||||
if [[ -n `$COMPOSE version | grep -E "\s+v1\."` ]]; then
|
||||
$COMPOSE version
|
||||
error "Docker-compose 版本过低,请升级至v2+!"
|
||||
error "$(msg 'Docker-compose 版本过低,请升级至v2+!')"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
@ -160,17 +254,17 @@ check_docker() {
|
||||
check_node() {
|
||||
npm --version &> /dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
error "未安装 npm!"
|
||||
error "$(msg '未安装 npm!')"
|
||||
exit 1
|
||||
fi
|
||||
node --version &> /dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
error "未安装 Node.js!"
|
||||
error "$(msg '未安装 Node.js!')"
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n `node --version | grep -E "v1"` ]]; then
|
||||
node --version
|
||||
error "Node.js 版本过低,请升级至v20+!"
|
||||
error "$(msg 'Node.js 版本过低,请升级至v20+!')"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
@ -244,7 +338,7 @@ container_exec() {
|
||||
local cmd=$@
|
||||
local name=$(docker_name "$container")
|
||||
if [ -z "$name" ]; then
|
||||
error "没有找到 ${container} 容器!"
|
||||
error "$(msg '没有找到 (*) 容器!' "$container")"
|
||||
exit 1
|
||||
fi
|
||||
docker exec $TTY_FLAG "$name" /bin/sh -c "$cmd"
|
||||
@ -272,8 +366,8 @@ mysql_snapshot() {
|
||||
mkdir -p ${WORK_DIR}/docker/mysql/backup
|
||||
filename="${WORK_DIR}/docker/mysql/backup/${database}_$(date "+%Y%m%d%H%M%S").sql.gz"
|
||||
container_exec mariadb "exec mysqldump --databases $database -u${username} -p${password}" | gzip > $filename
|
||||
judge "备份数据库"
|
||||
[ -f "$filename" ] && echo "备份文件:${filename}"
|
||||
judge "$(msg '备份数据库')"
|
||||
[ -f "$filename" ] && echo "$(msg '备份文件:(*)' "$filename")"
|
||||
elif [ "$1" = "recovery" ]; then
|
||||
database=$(env_get DB_DATABASE)
|
||||
username=$(env_get DB_USERNAME)
|
||||
@ -284,31 +378,31 @@ mysql_snapshot() {
|
||||
backup_files=("${WORK_DIR}/docker/mysql/backup/"*.sql.gz)
|
||||
shopt -u nullglob
|
||||
if [ ${#backup_files[@]} -eq 0 ]; then
|
||||
error "没有备份文件!"
|
||||
error "$(msg '没有备份文件!')"
|
||||
exit 1
|
||||
fi
|
||||
echo "可用备份列表:"
|
||||
echo "$(msg '可用备份列表:')"
|
||||
for idx in "${!backup_files[@]}"; do
|
||||
printf "%2d) %s\n" "$((idx + 1))" "$(basename "${backup_files[$idx]}")"
|
||||
done
|
||||
while true; do
|
||||
read -rp "请输入备份文件编号还原:" selection
|
||||
read -rp "$(msg '请输入备份文件编号还原:')" selection
|
||||
if [[ "$selection" =~ ^[0-9]+$ ]] && [ "$selection" -ge 1 ] && [ "$selection" -le ${#backup_files[@]} ]; then
|
||||
break
|
||||
fi
|
||||
warning "编号无效,请重新输入。"
|
||||
warning "$(msg '编号无效,请重新输入。')"
|
||||
done
|
||||
filename="${backup_files[$((selection - 1))]}"
|
||||
inputname="$(basename "$filename")"
|
||||
container_name=`docker_name mariadb`
|
||||
if [ -z "$container_name" ]; then
|
||||
error "没有找到 mariadb 容器!"
|
||||
error "$(msg '没有找到 (*) 容器!' mariadb)"
|
||||
exit 1
|
||||
fi
|
||||
docker cp "$filename" "${container_name}:/"
|
||||
container_exec mariadb "gunzip < '/${inputname}' | mysql -u${username} -p${password} $database"
|
||||
container_exec php "php artisan migrate"
|
||||
judge "还原数据库"
|
||||
judge "$(msg '还原数据库')"
|
||||
fi
|
||||
}
|
||||
|
||||
@ -339,33 +433,33 @@ remove_by_network() {
|
||||
https_auto() {
|
||||
restart_nginx="n"
|
||||
if [[ "$(env_get APP_PORT)" != "80" ]]; then
|
||||
warning "HTTP服务端口不是80,是否修改并继续操作? [Y/n]"
|
||||
warning "$(msg 'HTTP服务端口不是80,是否修改并继续操作? [Y/n]')"
|
||||
read -r continue_http
|
||||
[[ -z ${continue_http} ]] && continue_http="Y"
|
||||
case $continue_http in
|
||||
[yY][eE][sS] | [yY])
|
||||
success "继续操作"
|
||||
success "$(msg '继续操作')"
|
||||
env_set "APP_PORT" "80"
|
||||
restart_nginx="y"
|
||||
;;
|
||||
*)
|
||||
error "操作终止"
|
||||
error "$(msg '操作终止')"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if [[ "$(env_get APP_SSL_PORT)" != "443" ]]; then
|
||||
warning "HTTPS服务端口不是443,是否修改并继续操作? [Y/n]"
|
||||
warning "$(msg 'HTTPS服务端口不是443,是否修改并继续操作? [Y/n]')"
|
||||
read -r continue_https
|
||||
[[ -z ${continue_https} ]] && continue_https="Y"
|
||||
case $continue_https in
|
||||
[yY][eE][sS] | [yY])
|
||||
success "继续操作"
|
||||
success "$(msg '继续操作')"
|
||||
env_set "APP_SSL_PORT" "443"
|
||||
restart_nginx="y"
|
||||
;;
|
||||
*)
|
||||
error "操作终止"
|
||||
error "$(msg '操作终止')"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@ -380,13 +474,13 @@ https_auto() {
|
||||
new_job="* 6 * * * docker run --rm -v $(pwd):/work nginx:alpine sh /work/bin/https renew"
|
||||
current_crontab=$(crontab -l 2>/dev/null)
|
||||
if ! echo "$current_crontab" | grep -v "https renew"; then
|
||||
echo "任务已存在,无需添加。"
|
||||
echo "$(msg '任务已存在,无需添加。')"
|
||||
else
|
||||
crontab -l |{
|
||||
cat
|
||||
echo "$new_job"
|
||||
} | crontab -
|
||||
echo "任务已添加。"
|
||||
echo "$(msg '任务已添加。')"
|
||||
fi
|
||||
}
|
||||
|
||||
@ -416,7 +510,7 @@ env_set() {
|
||||
docker run $TTY_FLAG --rm -v ${WORK_DIR}:/www nginx:alpine sh -c "sed -i "/^${key}=/c\\${key}=${val}" /www/.env"
|
||||
fi
|
||||
if [ $? -ne 0 ]; then
|
||||
error "设置env参数失败!"
|
||||
error "$(msg '设置env参数失败!')"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
@ -468,7 +562,8 @@ arg_get() {
|
||||
|
||||
# 显示帮助信息
|
||||
show_help() {
|
||||
cat << 'EOF'
|
||||
if [ "$DT_LANG" = "zh" ]; then
|
||||
cat << 'EOF'
|
||||
DooTask 管理脚本
|
||||
|
||||
用法: ./cmd <命令> [参数]
|
||||
@ -516,6 +611,56 @@ DooTask 管理脚本
|
||||
./cmd mysql backup 备份数据库
|
||||
./cmd artisan migrate 执行数据库迁移
|
||||
EOF
|
||||
else
|
||||
cat << 'EOF'
|
||||
DooTask Management Script
|
||||
|
||||
Usage: ./cmd <command> [options]
|
||||
|
||||
📦 Core:
|
||||
install Install DooTask (supports --port <port> --relock)
|
||||
update Update DooTask (supports --branch <branch> --force --local)
|
||||
uninstall Uninstall DooTask
|
||||
|
||||
⚙️ Configuration:
|
||||
port <port> Change service port
|
||||
url <address> Change access URL
|
||||
env <key> <value> Set environment variable
|
||||
debug [true|false] Toggle debug mode
|
||||
repassword [username] Reset database password
|
||||
|
||||
🚀 Build:
|
||||
serve, dev Start dev mode
|
||||
build, prod Production build
|
||||
electron Build desktop app
|
||||
|
||||
🔧 Services:
|
||||
up [service] Start containers
|
||||
down [service] Stop containers
|
||||
restart [service] Restart containers
|
||||
reup Rebuild and start
|
||||
|
||||
💾 Database:
|
||||
mysql backup Back up database
|
||||
mysql recovery Restore database
|
||||
|
||||
🛠️ Dev tools:
|
||||
artisan <command> Run Laravel Artisan command
|
||||
composer <command> Run Composer command
|
||||
php <command> Run PHP command
|
||||
|
||||
📚 Others:
|
||||
doc Generate API docs
|
||||
https Configure HTTPS
|
||||
--help, -h Show this help
|
||||
|
||||
Examples:
|
||||
./cmd install --port 8080 Install on port 8080
|
||||
./cmd update --branch dev Switch to dev branch and update
|
||||
./cmd mysql backup Back up database
|
||||
./cmd artisan migrate Run database migration
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
# 检测APP_ID是否与其他实例冲突
|
||||
@ -524,8 +669,8 @@ check_instance() {
|
||||
local container_name="dootask-php-${app_id}"
|
||||
local mount_path=$(docker inspect "$container_name" --format '{{range .Mounts}}{{if eq .Destination "/var/www"}}{{.Source}}{{end}}{{end}}' 2>/dev/null)
|
||||
if [[ -n "$mount_path" ]] && [[ "$mount_path" != "$WORK_DIR" ]]; then
|
||||
error "APP_ID(${app_id})已被其他实例使用:${mount_path}"
|
||||
error "请先清空 .env 中的 APP_ID 和 APP_IPPR 再重新安装"
|
||||
error "$(msg 'APP_ID((*))已被其他实例使用:(*)' "$app_id" "$mount_path")"
|
||||
error "$(msg '请先清空 .env 中的 APP_ID 和 APP_IPPR 再重新安装')"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
@ -537,7 +682,7 @@ check_port() {
|
||||
local current_port=$2
|
||||
if [[ "$port" -gt 0 ]] && [[ "$port" != "$current_port" ]]; then
|
||||
if ! docker run --rm -p "${port}:80" --entrypoint true nginx:alpine 2>/dev/null; then
|
||||
error "端口 ${port} 已被占用,请指定其他端口"
|
||||
error "$(msg '端口 (*) 已被占用,请指定其他端口' "$port")"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
@ -582,13 +727,13 @@ handle_install() {
|
||||
writable="yes"
|
||||
docker run --rm ${cmda} nginx:alpine sh -c "${cmdb} touch /usr/share/docker/dootask.lock" &> /dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
error "目录权限检测失败!请检查目录权限设置"
|
||||
error "$(msg '目录权限检测失败!请检查目录权限设置')"
|
||||
exit 1
|
||||
fi
|
||||
for vol in "${volumes[@]}"; do
|
||||
if [ ! -f "${vol}/dootask.lock" ]; then
|
||||
if [ $remaining -lt 0 ]; then
|
||||
error "目录【${vol}】权限不足!"
|
||||
error "$(msg '目录【(*)】权限不足!' "$vol")"
|
||||
exit 1
|
||||
else
|
||||
writable="no"
|
||||
@ -619,28 +764,28 @@ handle_install() {
|
||||
$COMPOSE up php -d
|
||||
|
||||
# 安装PHP依赖
|
||||
exec_judge "container_exec php 'composer install --optimize-autoloader'" "安装依赖失败"
|
||||
exec_judge "container_exec php 'composer install --optimize-autoloader'" "$(msg '安装依赖失败')"
|
||||
|
||||
# 最终检查
|
||||
if [ ! -f "${WORK_DIR}/vendor/autoload.php" ]; then
|
||||
error "安装依赖失败,请重试!"
|
||||
error "$(msg '安装依赖失败,请重试!')"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 生成应用密钥
|
||||
[[ -z "$(env_get APP_KEY)" ]] && exec_judge "container_exec php 'php artisan key:generate'" "生成密钥失败"
|
||||
[[ -z "$(env_get APP_KEY)" ]] && exec_judge "container_exec php 'php artisan key:generate'" "$(msg '生成密钥失败')"
|
||||
|
||||
# 设置生产模式
|
||||
switch_debug "false"
|
||||
|
||||
# 数据库迁移
|
||||
exec_judge "container_exec php 'php artisan migrate --seed'" "数据库迁移失败"
|
||||
exec_judge "container_exec php 'php artisan migrate --seed'" "$(msg '数据库迁移失败')"
|
||||
|
||||
# 启动所有容器
|
||||
$COMPOSE up -d --remove-orphans
|
||||
|
||||
success "安装完成"
|
||||
echo -e "地址: http://${GreenBG}127.0.0.1:$(env_get APP_PORT)${Font}"
|
||||
success "$(msg '安装完成')"
|
||||
echo -e "$(msg '地址'): http://${GreenBG}127.0.0.1:$(env_get APP_PORT)${Font}"
|
||||
container_exec mariadb "sh /etc/mysql/repassword.sh"
|
||||
}
|
||||
|
||||
@ -654,7 +799,7 @@ handle_update() {
|
||||
|
||||
# 检查是否已经安装
|
||||
if [ ! -f "${WORK_DIR}/vendor/autoload.php" ]; then
|
||||
error "请先执行安装命令"
|
||||
error "$(msg '请先执行安装命令')"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@ -667,7 +812,7 @@ handle_update() {
|
||||
# 检查本地修改
|
||||
if ! git diff --quiet || ! git diff --cached --quiet; then
|
||||
if [[ "$force_update" != "yes" ]]; then
|
||||
warning "检测到本地修改,是否强制更新?[Y/n]"
|
||||
warning "$(msg '检测到本地修改,是否强制更新?[Y/n]')"
|
||||
read -r confirm_force
|
||||
[[ -z ${confirm_force} ]] && confirm_force="Y"
|
||||
case $confirm_force in
|
||||
@ -675,7 +820,7 @@ handle_update() {
|
||||
force_update="yes"
|
||||
;;
|
||||
*)
|
||||
error "取消更新,请先处理本地修改"
|
||||
error "$(msg '取消更新,请先处理本地修改')"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@ -683,21 +828,21 @@ handle_update() {
|
||||
fi
|
||||
|
||||
# 远程更新模式
|
||||
exec_judge "git fetch --all" "获取远程更新失败"
|
||||
exec_judge "git fetch --all" "$(msg '获取远程更新失败')"
|
||||
|
||||
# 确定目标分支
|
||||
if [[ -n "$target_branch" ]]; then
|
||||
current_branch="$target_branch"
|
||||
if ! git config --get "branch.${current_branch}.remote" | grep -q "origin"; then
|
||||
exec_judge "git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'" "设置远程Fetch配置失败"
|
||||
exec_judge "git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'" "$(msg '设置远程Fetch配置失败')"
|
||||
fi
|
||||
if ! git show-ref --verify --quiet refs/heads/${current_branch}; then
|
||||
exec_judge "git fetch origin ${current_branch}:${current_branch}" "获取远程分支 ${current_branch} 失败"
|
||||
exec_judge "git fetch origin ${current_branch}:${current_branch}" "$(msg '获取远程分支 (*) 失败' "$current_branch")"
|
||||
fi
|
||||
if [[ "$force_update" == "yes" ]]; then
|
||||
exec_judge "git checkout -f ${current_branch}" "切换分支到 ${current_branch} 失败"
|
||||
exec_judge "git checkout -f ${current_branch}" "$(msg '切换分支到 (*) 失败' "$current_branch")"
|
||||
else
|
||||
exec_judge "git checkout ${current_branch}" "切换分支到 ${current_branch} 失败"
|
||||
exec_judge "git checkout ${current_branch}" "$(msg '切换分支到 (*) 失败' "$current_branch")"
|
||||
fi
|
||||
else
|
||||
current_branch=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p')
|
||||
@ -706,27 +851,27 @@ handle_update() {
|
||||
# 检查数据库迁移变动
|
||||
db_changes=$(git diff --name-only HEAD..origin/${current_branch} 2>/dev/null | grep -E "^database/" || true)
|
||||
if [[ -n "$db_changes" ]]; then
|
||||
echo "数据库有迁移变动,执行数据库备份..."
|
||||
exec_judge "mysql_snapshot backup" "数据库备份失败" "数据库备份完成"
|
||||
echo "$(msg '数据库有迁移变动,执行数据库备份...')"
|
||||
exec_judge "mysql_snapshot backup" "$(msg '数据库备份失败')" "$(msg '数据库备份完成')"
|
||||
fi
|
||||
|
||||
# 更新代码
|
||||
if [[ "$force_update" == "yes" ]]; then
|
||||
exec_judge "git reset --hard origin/${current_branch}" "强制更新代码失败"
|
||||
exec_judge "git reset --hard origin/${current_branch}" "$(msg '强制更新代码失败')"
|
||||
else
|
||||
exec_judge "git pull --ff-only origin ${current_branch}" "代码拉取失败,可能存在冲突,请使用 --force 参数"
|
||||
exec_judge "git pull --ff-only origin ${current_branch}" "$(msg '代码拉取失败,可能存在冲突,请使用 --force 参数')"
|
||||
fi
|
||||
|
||||
# 更新依赖
|
||||
exec_judge "container_run php 'composer install --optimize-autoloader'" "更新PHP依赖失败"
|
||||
exec_judge "container_run php 'composer install --optimize-autoloader'" "$(msg '更新PHP依赖失败')"
|
||||
else
|
||||
# 本地更新模式
|
||||
echo "执行数据库备份..."
|
||||
exec_judge "mysql_snapshot backup" "数据库备份失败" "数据库备份完成"
|
||||
echo "$(msg '执行数据库备份...')"
|
||||
exec_judge "mysql_snapshot backup" "$(msg '数据库备份失败')" "$(msg '数据库备份完成')"
|
||||
fi
|
||||
|
||||
# 数据库迁移
|
||||
exec_judge "container_run php 'php artisan migrate'" "数据库迁移失败"
|
||||
exec_judge "container_run php 'php artisan migrate'" "$(msg '数据库迁移失败')"
|
||||
|
||||
# 停止服务
|
||||
$COMPOSE stop php nginx &> /dev/null
|
||||
@ -736,30 +881,30 @@ handle_update() {
|
||||
$COMPOSE up -d --remove-orphans
|
||||
if [[ 0 -ne $? ]]; then
|
||||
$COMPOSE down --remove-orphans
|
||||
exec_judge "$COMPOSE up -d" "重启服务失败"
|
||||
exec_judge "$COMPOSE up -d" "$(msg '重启服务失败')"
|
||||
fi
|
||||
|
||||
env_set UPDATE_TIME "$(date +%s)"
|
||||
success "更新完成"
|
||||
success "$(msg '更新完成')"
|
||||
}
|
||||
|
||||
# 卸载函数
|
||||
handle_uninstall() {
|
||||
check_sudo
|
||||
# 确认卸载
|
||||
echo -e "${RedBG}警告:此操作将永久删除以下内容:${Font}"
|
||||
echo "- 数据库"
|
||||
echo "- 应用程序"
|
||||
echo "- 日志文件"
|
||||
echo -e "${RedBG}$(msg '警告:此操作将永久删除以下内容:')${Font}"
|
||||
echo "$(msg '- 数据库')"
|
||||
echo "$(msg '- 应用程序')"
|
||||
echo "$(msg '- 日志文件')"
|
||||
echo ""
|
||||
read -rp "确认要继续卸载吗?(y/N): " confirm_uninstall
|
||||
read -rp "$(msg '确认要继续卸载吗?(y/N): ')" confirm_uninstall
|
||||
[[ -z ${confirm_uninstall} ]] && confirm_uninstall="N"
|
||||
case $confirm_uninstall in
|
||||
[yY][eE][sS] | [yY])
|
||||
echo -e "${RedBG}开始卸载...${Font}"
|
||||
echo -e "${RedBG}$(msg '开始卸载...')${Font}"
|
||||
;;
|
||||
*)
|
||||
echo -e "${GreenBG}终止卸载。${Font}"
|
||||
echo -e "${GreenBG}$(msg '终止卸载。')${Font}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@ -780,7 +925,7 @@ handle_uninstall() {
|
||||
find "./docker/appstore/log" -name "*.log" -delete 2>/dev/null
|
||||
find "./storage/logs" -name "*.log" -delete 2>/dev/null
|
||||
|
||||
success "卸载完成"
|
||||
success "$(msg '卸载完成')"
|
||||
}
|
||||
|
||||
####################################################################################
|
||||
@ -818,14 +963,14 @@ case "$1" in
|
||||
check_port "$1" "$(env_get APP_PORT)"
|
||||
env_set APP_PORT "$1"
|
||||
$COMPOSE up -d
|
||||
success "修改成功"
|
||||
echo -e "地址: http://${GreenBG}127.0.0.1:$(env_get APP_PORT)${Font}"
|
||||
success "$(msg '修改成功')"
|
||||
echo -e "$(msg '地址'): http://${GreenBG}127.0.0.1:$(env_get APP_PORT)${Font}"
|
||||
;;
|
||||
"url")
|
||||
shift 1
|
||||
env_set APP_URL "$1"
|
||||
restart_php
|
||||
success "修改成功"
|
||||
success "$(msg '修改成功')"
|
||||
;;
|
||||
"env")
|
||||
shift 1
|
||||
@ -833,7 +978,7 @@ case "$1" in
|
||||
env_set $1 "$2"
|
||||
fi
|
||||
restart_php
|
||||
success "修改成功"
|
||||
success "$(msg '修改成功')"
|
||||
;;
|
||||
"repassword")
|
||||
shift 1
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user