Add Linux account workspace runtime
This commit is contained in:
+105
-11
@@ -3,7 +3,7 @@ set -euo pipefail
|
||||
|
||||
# Ubuntu 一键部署/更新脚本。
|
||||
# - 首次执行会交互式生成 .env.deploy,本机保存,不提交 git。
|
||||
# - 后续执行会拉取代码、更新依赖、构建前端、安装/重启用户级 systemd 服务。
|
||||
# - 后续执行会拉取代码、更新依赖、构建前端、安装/重启 systemd 服务。
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
ENV_FILE="${ROOT_DIR}/.env.deploy"
|
||||
@@ -12,14 +12,17 @@ DEPLOY_INSTANCE="${CLAW_DEPLOY_INSTANCE:-zk-data-agent}"
|
||||
BACKEND_SERVICE="${CLAW_BACKEND_SERVICE:-${DEPLOY_INSTANCE}-backend}"
|
||||
FRONTEND_SERVICE="${CLAW_FRONTEND_SERVICE:-${DEPLOY_INSTANCE}-frontend}"
|
||||
USER_SYSTEMD_DIR="${HOME}/.config/systemd/user"
|
||||
SYSTEM_SYSTEMD_DIR="/etc/systemd/system"
|
||||
BRANCH=""
|
||||
FORCE=0
|
||||
SKIP_GIT=0
|
||||
BOOTSTRAP_SYSTEM=0
|
||||
SERVICE_SCOPE="${CLAW_SERVICE_SCOPE:-}"
|
||||
ENABLE_LINUX_ACCOUNTS="${CLAW_ENABLE_LINUX_ACCOUNTS:-}"
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: bash scripts/deploy-ubuntu.sh [branch] [--force] [--skip-git] [--bootstrap-system]
|
||||
Usage: bash scripts/deploy-ubuntu.sh [branch] [--force] [--skip-git] [--bootstrap-system] [--system-service] [--user-service] [--enable-linux-accounts]
|
||||
|
||||
Options:
|
||||
branch 要部署的 git 分支;不传则使用当前分支
|
||||
@@ -27,6 +30,12 @@ Options:
|
||||
--skip-git 跳过 git 拉取,只部署当前工作区
|
||||
--bootstrap-system
|
||||
强制使用 sudo 安装 Ubuntu 系统依赖;首次安装会默认执行
|
||||
--system-service
|
||||
安装 root/system 级 systemd 服务;以 root 执行时默认启用
|
||||
--user-service
|
||||
安装当前用户级 systemd 服务
|
||||
--enable-linux-accounts
|
||||
启用平台账号同名 Linux 用户工作区;要求 system 服务和 root 权限
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -44,6 +53,18 @@ while [[ $# -gt 0 ]]; do
|
||||
BOOTSTRAP_SYSTEM=1
|
||||
shift
|
||||
;;
|
||||
--system-service)
|
||||
SERVICE_SCOPE="system"
|
||||
shift
|
||||
;;
|
||||
--user-service)
|
||||
SERVICE_SCOPE="user"
|
||||
shift
|
||||
;;
|
||||
--enable-linux-accounts)
|
||||
ENABLE_LINUX_ACCOUNTS="1"
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
@@ -60,6 +81,9 @@ while [[ $# -gt 0 ]]; do
|
||||
esac
|
||||
done
|
||||
|
||||
REQUESTED_SERVICE_SCOPE="${SERVICE_SCOPE}"
|
||||
REQUESTED_ENABLE_LINUX_ACCOUNTS="${ENABLE_LINUX_ACCOUNTS}"
|
||||
|
||||
log() {
|
||||
printf "\n\033[1;34m==>\033[0m %s\n" "$1"
|
||||
}
|
||||
@@ -77,6 +101,16 @@ configure_instance_names() {
|
||||
DEPLOY_INSTANCE="${CLAW_DEPLOY_INSTANCE:-${DEPLOY_INSTANCE:-zk-data-agent}}"
|
||||
BACKEND_SERVICE="${CLAW_BACKEND_SERVICE:-${DEPLOY_INSTANCE}-backend}"
|
||||
FRONTEND_SERVICE="${CLAW_FRONTEND_SERVICE:-${DEPLOY_INSTANCE}-frontend}"
|
||||
if [[ -z "${SERVICE_SCOPE}" ]]; then
|
||||
if [[ "${EUID}" == "0" ]]; then
|
||||
SERVICE_SCOPE="system"
|
||||
else
|
||||
SERVICE_SCOPE="user"
|
||||
fi
|
||||
fi
|
||||
if [[ -z "${ENABLE_LINUX_ACCOUNTS}" ]]; then
|
||||
ENABLE_LINUX_ACCOUNTS="${CLAW_ENABLE_LINUX_ACCOUNTS:-0}"
|
||||
fi
|
||||
}
|
||||
|
||||
require_command() {
|
||||
@@ -120,6 +154,9 @@ bootstrap_system_packages() {
|
||||
libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \
|
||||
libffi-dev liblzma-dev libncursesw5-dev xz-utils tk-dev \
|
||||
systemd
|
||||
if [[ "${ENABLE_LINUX_ACCOUNTS}" == "1" ]]; then
|
||||
sudo apt-get install -y passwd python3 python3-venv
|
||||
fi
|
||||
}
|
||||
|
||||
configure_nginx_upload_limit() {
|
||||
@@ -180,15 +217,42 @@ export CLAW_BACKEND_PORT=$(printf "%q" "${backend_port}")
|
||||
export CLAW_FRONTEND_HOST=$(printf "%q" "${frontend_host}")
|
||||
export CLAW_FRONTEND_PORT=$(printf "%q" "${frontend_port}")
|
||||
export CLAW_API_URL=$(printf "%q" "${claw_api_url}")
|
||||
export CLAW_SERVICE_SCOPE=$(printf "%q" "${SERVICE_SCOPE}")
|
||||
export CLAW_ENABLE_LINUX_ACCOUNTS=$(printf "%q" "${ENABLE_LINUX_ACCOUNTS:-0}")
|
||||
EOF
|
||||
chmod 600 "${ENV_FILE}"
|
||||
}
|
||||
|
||||
upsert_env_export() {
|
||||
local key="$1"
|
||||
local value="$2"
|
||||
local tmp_file
|
||||
tmp_file="$(mktemp)"
|
||||
grep -v -E "^export ${key}=" "${ENV_FILE}" >"${tmp_file}" || true
|
||||
printf 'export %s=%s\n' "${key}" "$(printf "%q" "${value}")" >>"${tmp_file}"
|
||||
install -m 0600 "${tmp_file}" "${ENV_FILE}"
|
||||
rm -f "${tmp_file}"
|
||||
}
|
||||
|
||||
ensure_env_file() {
|
||||
if [[ -f "${ENV_FILE}" ]]; then
|
||||
# shellcheck disable=SC1090
|
||||
source "${ENV_FILE}"
|
||||
if [[ -n "${REQUESTED_SERVICE_SCOPE}" ]]; then
|
||||
SERVICE_SCOPE="${REQUESTED_SERVICE_SCOPE}"
|
||||
export CLAW_SERVICE_SCOPE="${REQUESTED_SERVICE_SCOPE}"
|
||||
fi
|
||||
if [[ -n "${REQUESTED_ENABLE_LINUX_ACCOUNTS}" ]]; then
|
||||
ENABLE_LINUX_ACCOUNTS="${REQUESTED_ENABLE_LINUX_ACCOUNTS}"
|
||||
export CLAW_ENABLE_LINUX_ACCOUNTS="${REQUESTED_ENABLE_LINUX_ACCOUNTS}"
|
||||
fi
|
||||
configure_instance_names
|
||||
if [[ -n "${REQUESTED_SERVICE_SCOPE}" ]]; then
|
||||
upsert_env_export CLAW_SERVICE_SCOPE "${SERVICE_SCOPE}"
|
||||
fi
|
||||
if [[ -n "${REQUESTED_ENABLE_LINUX_ACCOUNTS}" ]]; then
|
||||
upsert_env_export CLAW_ENABLE_LINUX_ACCOUNTS "${ENABLE_LINUX_ACCOUNTS}"
|
||||
fi
|
||||
if [[ -z "${OPENAI_API_KEY:-}" ]]; then
|
||||
fail "${ENV_FILE} 缺少 OPENAI_API_KEY,请编辑该文件补齐。"
|
||||
fi
|
||||
@@ -197,6 +261,8 @@ ensure_env_file() {
|
||||
echo "OPENAI_BASE_URL=${OPENAI_BASE_URL:-}"
|
||||
echo "OPENAI_MODEL=${OPENAI_MODEL:-}"
|
||||
echo "OPENAI_TIMEOUT_SECONDS=${OPENAI_TIMEOUT_SECONDS:-3600}"
|
||||
echo "CLAW_SERVICE_SCOPE=${SERVICE_SCOPE}"
|
||||
echo "CLAW_ENABLE_LINUX_ACCOUNTS=${CLAW_ENABLE_LINUX_ACCOUNTS:-0}"
|
||||
echo "OPENAI_API_KEY=已配置"
|
||||
return
|
||||
fi
|
||||
@@ -214,6 +280,9 @@ ensure_env_file() {
|
||||
prompt_value base_url "请输入 OPENAI_BASE_URL" "http://model.mify.ai.srv/v1"
|
||||
prompt_value model "请输入 OPENAI_MODEL" "tongyi/deepseek-v4-pro"
|
||||
configure_instance_names
|
||||
if [[ "${ENABLE_LINUX_ACCOUNTS}" == "1" && "${SERVICE_SCOPE}" != "system" ]]; then
|
||||
fail "--enable-linux-accounts 需要 --system-service,并建议使用 sudo/root 执行部署。"
|
||||
fi
|
||||
prompt_value backend_host "请输入后端监听地址" "127.0.0.1"
|
||||
prompt_value backend_port "请输入后端端口" "8765"
|
||||
prompt_value frontend_host "请输入前端监听地址" "0.0.0.0"
|
||||
@@ -304,14 +373,21 @@ EOF
|
||||
install_systemd_service() {
|
||||
local service_name="$1"
|
||||
local template_path="$2"
|
||||
local target_path="${USER_SYSTEMD_DIR}/${service_name}.service"
|
||||
local target_dir="${USER_SYSTEMD_DIR}"
|
||||
local wanted_by="default.target"
|
||||
if [[ "${SERVICE_SCOPE}" == "system" ]]; then
|
||||
target_dir="${SYSTEM_SYSTEMD_DIR}"
|
||||
wanted_by="multi-user.target"
|
||||
fi
|
||||
local target_path="${target_dir}/${service_name}.service"
|
||||
local tmp_path
|
||||
tmp_path="$(mktemp)"
|
||||
mkdir -p "${USER_SYSTEMD_DIR}"
|
||||
mkdir -p "${target_dir}"
|
||||
sed \
|
||||
-e "s#__PROJECT_ROOT__#${ROOT_DIR}#g" \
|
||||
-e "s#__BACKEND_SERVICE__#${BACKEND_SERVICE}#g" \
|
||||
-e "s#__FRONTEND_SERVICE__#${FRONTEND_SERVICE}#g" \
|
||||
-e "s#WantedBy=default.target#WantedBy=${wanted_by}#g" \
|
||||
"${template_path}" >"${tmp_path}"
|
||||
install -m 0644 "${tmp_path}" "${target_path}"
|
||||
rm -f "${tmp_path}"
|
||||
@@ -319,17 +395,30 @@ install_systemd_service() {
|
||||
|
||||
install_services() {
|
||||
require_command systemctl "当前系统不支持 systemd,无法安装服务。"
|
||||
log "安装/更新用户级 systemd 服务"
|
||||
if [[ "${ENABLE_LINUX_ACCOUNTS}" == "1" && "${SERVICE_SCOPE}" != "system" ]]; then
|
||||
fail "CLAW_ENABLE_LINUX_ACCOUNTS=1 需要 system 服务。请用 sudo bash scripts/deploy-ubuntu.sh --system-service --enable-linux-accounts。"
|
||||
fi
|
||||
log "安装/更新 ${SERVICE_SCOPE} systemd 服务"
|
||||
install_systemd_service "${BACKEND_SERVICE}" "${ROOT_DIR}/deploy/systemd/zk-data-agent-backend.service.template"
|
||||
install_systemd_service "${FRONTEND_SERVICE}" "${ROOT_DIR}/deploy/systemd/zk-data-agent-frontend.service.template"
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable "${BACKEND_SERVICE}" "${FRONTEND_SERVICE}"
|
||||
if [[ "${SERVICE_SCOPE}" == "system" ]]; then
|
||||
systemctl daemon-reload
|
||||
systemctl enable "${BACKEND_SERVICE}" "${FRONTEND_SERVICE}"
|
||||
else
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable "${BACKEND_SERVICE}" "${FRONTEND_SERVICE}"
|
||||
fi
|
||||
}
|
||||
|
||||
restart_services() {
|
||||
log "重启服务"
|
||||
systemctl --user restart "${BACKEND_SERVICE}"
|
||||
systemctl --user restart "${FRONTEND_SERVICE}"
|
||||
if [[ "${SERVICE_SCOPE}" == "system" ]]; then
|
||||
systemctl restart "${BACKEND_SERVICE}"
|
||||
systemctl restart "${FRONTEND_SERVICE}"
|
||||
else
|
||||
systemctl --user restart "${BACKEND_SERVICE}"
|
||||
systemctl --user restart "${FRONTEND_SERVICE}"
|
||||
fi
|
||||
}
|
||||
|
||||
health_check() {
|
||||
@@ -348,8 +437,13 @@ health_check() {
|
||||
sleep 0.5
|
||||
done
|
||||
warn "健康检查失败,输出最近日志。"
|
||||
journalctl --user -u "${BACKEND_SERVICE}" -n 80 --no-pager || true
|
||||
journalctl --user -u "${FRONTEND_SERVICE}" -n 80 --no-pager || true
|
||||
if [[ "${SERVICE_SCOPE}" == "system" ]]; then
|
||||
journalctl -u "${BACKEND_SERVICE}" -n 80 --no-pager || true
|
||||
journalctl -u "${FRONTEND_SERVICE}" -n 80 --no-pager || true
|
||||
else
|
||||
journalctl --user -u "${BACKEND_SERVICE}" -n 80 --no-pager || true
|
||||
journalctl --user -u "${FRONTEND_SERVICE}" -n 80 --no-pager || true
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ ENV_FILE="${ROOT_DIR}/.env.deploy"
|
||||
DEPLOY_INSTANCE="${CLAW_DEPLOY_INSTANCE:-zk-data-agent}"
|
||||
BACKEND_SERVICE="${CLAW_BACKEND_SERVICE:-${DEPLOY_INSTANCE}-backend}"
|
||||
FRONTEND_SERVICE="${CLAW_FRONTEND_SERVICE:-${DEPLOY_INSTANCE}-frontend}"
|
||||
SERVICE_SCOPE="${CLAW_SERVICE_SCOPE:-}"
|
||||
BRANCH="${1:-}"
|
||||
|
||||
log() {
|
||||
@@ -26,6 +27,13 @@ configure_instance_names() {
|
||||
DEPLOY_INSTANCE="${CLAW_DEPLOY_INSTANCE:-${DEPLOY_INSTANCE:-zk-data-agent}}"
|
||||
BACKEND_SERVICE="${CLAW_BACKEND_SERVICE:-${DEPLOY_INSTANCE}-backend}"
|
||||
FRONTEND_SERVICE="${CLAW_FRONTEND_SERVICE:-${DEPLOY_INSTANCE}-frontend}"
|
||||
if [[ -z "${SERVICE_SCOPE}" ]]; then
|
||||
if [[ "${EUID}" == "0" ]]; then
|
||||
SERVICE_SCOPE="system"
|
||||
else
|
||||
SERVICE_SCOPE="user"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
resolve_npm_bin() {
|
||||
@@ -99,12 +107,20 @@ npm_bin="$(resolve_npm_bin)"
|
||||
export PATH="$(dirname "${npm_bin}"):${PATH}"
|
||||
"${npm_bin}" run build
|
||||
|
||||
log "重启用户服务"
|
||||
systemctl --user restart "${BACKEND_SERVICE}" "${FRONTEND_SERVICE}"
|
||||
log "重启 ${SERVICE_SCOPE} 服务"
|
||||
if [[ "${SERVICE_SCOPE}" == "system" ]]; then
|
||||
systemctl restart "${BACKEND_SERVICE}" "${FRONTEND_SERVICE}"
|
||||
else
|
||||
systemctl --user restart "${BACKEND_SERVICE}" "${FRONTEND_SERVICE}"
|
||||
fi
|
||||
|
||||
log "健康检查"
|
||||
sleep 1
|
||||
systemctl --user --no-pager --lines=0 status "${BACKEND_SERVICE}" "${FRONTEND_SERVICE}"
|
||||
if [[ "${SERVICE_SCOPE}" == "system" ]]; then
|
||||
systemctl --no-pager --lines=0 status "${BACKEND_SERVICE}" "${FRONTEND_SERVICE}"
|
||||
else
|
||||
systemctl --user --no-pager --lines=0 status "${BACKEND_SERVICE}" "${FRONTEND_SERVICE}"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "快速更新完成。"
|
||||
|
||||
Reference in New Issue
Block a user