Files
J-Board-Lite/scripts/uninstall-jboard-panel.sh
2026-05-01 01:50:37 +10:00

175 lines
4.3 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
set -euo pipefail
CONFIG_FILE="${JETBOARD_CONFIG:-/etc/jetboard.conf}"
APP_DIR="${JBOARD_APP_DIR:-${APP_DIR:-}}"
COMPOSE="${COMPOSE:-docker compose}"
if [ -z "${BACKUP_ROOT:-}" ]; then
if [ "$(id -u)" -eq 0 ]; then
BACKUP_ROOT="/root"
else
BACKUP_ROOT="${HOME:-/tmp}"
fi
fi
UNINSTALL_CONFIRM="${UNINSTALL_CONFIRM:-}"
if [ -z "$APP_DIR" ] && [ -r "$CONFIG_FILE" ]; then
# shellcheck disable=SC1090
. "$CONFIG_FILE"
APP_DIR="${JBOARD_APP_DIR:-${APP_DIR:-}}"
COMPOSE="${COMPOSE:-docker compose}"
fi
APP_DIR="${APP_DIR:-/opt/jboard}"
is_interactive() {
[ -r /dev/tty ] && [ -w /dev/tty ]
}
prompt_print() {
if is_interactive; then
printf '%b' "$*" > /dev/tty
else
printf '%b' "$*" >&2
fi
}
prompt_read() {
local __var="$1"
if is_interactive; then
IFS= read -r "$__var" < /dev/tty || true
else
return 1
fi
}
run_as_root() {
if [ "$(id -u)" -eq 0 ]; then
"$@"
elif command -v sudo >/dev/null 2>&1; then
sudo "$@"
else
echo "需要 root 权限。请使用 root 用户运行,或先安装 sudo。" >&2
exit 1
fi
}
compose() {
if [ "$(id -u)" -eq 0 ]; then
$COMPOSE "$@"
else
run_as_root $COMPOSE "$@"
fi
}
line() {
printf '%s\n' "------------------------------------------------------------"
}
section() {
echo
line
printf '%s\n' "$1"
line
}
confirm_uninstall() {
if [ "$UNINSTALL_CONFIRM" = "YES" ]; then
return
fi
if ! is_interactive; then
echo "非交互卸载请设置 UNINSTALL_CONFIRM=YES。" >&2
exit 1
fi
section "确认卸载 J-Board Lite Docker 部署"
printf '将停止并删除 Docker Compose 服务和 SQLite volume。\n'
printf '将删除安装目录:%s\n' "$APP_DIR"
printf '将删除命令:/usr/local/bin/jetboard、/usr/local/bin/JetBoard\n'
printf '将删除配置:%s\n' "$CONFIG_FILE"
echo "卸载前会尝试备份 .env、backups 和 SQLite 数据库到 ${BACKUP_ROOT}"
echo
prompt_print "请输入 YES 确认卸载: "
local answer=""
prompt_read answer || true
if [ "$answer" != "YES" ]; then
echo "已取消卸载。"
exit 0
fi
}
backup_before_remove() {
if [ ! -d "$APP_DIR" ]; then
echo "安装目录不存在,跳过备份:$APP_DIR"
return
fi
local backup_dir backup_file sqlite_backup
backup_dir="${BACKUP_ROOT%/}/jboard-docker-uninstall-backup-$(date +%F-%H%M%S)"
backup_file="${backup_dir}.tar.gz"
sqlite_backup="$backup_dir/sqlite-storage.tar.gz"
run_as_root mkdir -p "$backup_dir"
if [ "$(id -u)" -ne 0 ]; then
run_as_root chown "$(id -u):$(id -g)" "$backup_dir"
fi
if [ -f "$APP_DIR/.env" ]; then
run_as_root cp "$APP_DIR/.env" "$backup_dir/.env"
fi
if [ -d "$APP_DIR/backups" ]; then
run_as_root cp -R "$APP_DIR/backups" "$backup_dir/backups"
fi
if [ -f "$APP_DIR/docker-compose.yml" ]; then
local backup_cmd='cd /app/storage 2>/dev/null && if [ -f jboard.db ]; then set -- jboard.db; [ -f jboard.db-wal ] && set -- "$@" jboard.db-wal; [ -f jboard.db-shm ] && set -- "$@" jboard.db-shm; tar -czf - "$@"; fi'
(
cd "$APP_DIR"
if compose ps --services --filter status=running 2>/dev/null | grep -qx app; then
compose exec -T app sh -lc "$backup_cmd" > "$sqlite_backup" || true
fi
if [ ! -s "$sqlite_backup" ]; then
compose --profile setup run --rm -T --entrypoint sh init -lc "$backup_cmd" > "$sqlite_backup" || true
fi
)
if [ ! -s "$sqlite_backup" ]; then
rm -f "$sqlite_backup"
echo "未找到可备份的 SQLite volume跳过数据库备份。"
fi
fi
run_as_root tar -C "$(dirname "$backup_dir")" -czf "$backup_file" "$(basename "$backup_dir")"
run_as_root rm -rf "$backup_dir"
echo "卸载备份已保存:$backup_file"
}
remove_compose_stack() {
section "删除 Docker Compose 服务"
if [ -f "$APP_DIR/docker-compose.yml" ]; then
(
cd "$APP_DIR"
compose down --volumes --remove-orphans || true
)
fi
}
remove_files() {
section "删除文件"
cd /
run_as_root rm -f /usr/local/bin/jetboard /usr/local/bin/JetBoard
run_as_root rm -f "$CONFIG_FILE"
run_as_root rm -rf "$APP_DIR"
}
main() {
confirm_uninstall
backup_before_remove
remove_compose_stack
remove_files
echo
echo "J-Board Lite Docker 部署已卸载。Docker 本身不会被删除。"
}
main "$@"