Files
go_blog/install_linux.sh
T
dsh bd3a875403 fix: embed static assets into the binary and never render blank content
The merged markdown-rendering change served /static from a disk directory,
but the live deployment only replaced the binary and templates, so
/static/js/markdown.js and /static/css/markdown.css 404'd and every
article/comment rendered empty (BlogMD was undefined and threw).

- main.go: serve /static from an embedded FS (go:embed) — deployments
  now only need to replace the executable; no static dir to copy.
- install_linux.sh: drop the static directory copy (no longer needed).
- article.html / comment_list.html: if BlogMD is unavailable, fall back
  to plain (HTML-escaped) text for the article body, comment bodies and
  the comment preview, so content is never blank.
- README: document the static/ directory.

Verified locally: /static/* serve 200 even with the disk directory
removed; normal render path (25 checks) and the fallback path both pass.
2026-08-18 06:18:08 -04:00

100 lines
2.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
SERVICE_NAME="blog_go"
SERVICE_USER="blog_go"
CONFIG_DIR="/etc/${SERVICE_NAME}"
DATA_DIR="/srv/${SERVICE_NAME}"
INSTALL_DIR="/opt/${SERVICE_NAME}"
BINARY_NAME="${SERVICE_NAME}"
SOCKET_DIR="/run/${SERVICE_NAME}"
SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
if [[ "${EUID}" -ne 0 ]]; then
echo "请使用 root 权限运行: sudo $0" >&2
exit 1
fi
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "${SCRIPT_DIR}"
echo "拉取最新代码..."
git pull
echo "编译 Go 程序..."
go build -o "${BINARY_NAME}" .
echo "检查系统用户..."
if ! id -u "${SERVICE_USER}" >/dev/null 2>&1; then
useradd --system --home-dir "${DATA_DIR}" --shell /usr/sbin/nologin "${SERVICE_USER}"
fi
echo "创建目录..."
install -d -m 0750 -o "${SERVICE_USER}" -g "${SERVICE_USER}" "${CONFIG_DIR}" "${DATA_DIR}"
install -d -m 0755 -o "${SERVICE_USER}" -g "${SERVICE_USER}" "${INSTALL_DIR}"
install -d -m 0755 "${SOCKET_DIR}"
chown "${SERVICE_USER}:${SERVICE_USER}" "${SOCKET_DIR}"
echo "安装程序和模板文件..."
install -m 0755 -o root -g root "${SCRIPT_DIR}/${BINARY_NAME}" "${INSTALL_DIR}/${BINARY_NAME}"
rm -rf "${INSTALL_DIR}/templates"
cp -a "${SCRIPT_DIR}/templates" "${INSTALL_DIR}/templates"
chown -R root:root "${INSTALL_DIR}/templates"
# static 资源已通过 go:embed 编入二进制,无需单独拷贝
chown "${SERVICE_USER}:${SERVICE_USER}" "${INSTALL_DIR}"
chmod 0755 "${INSTALL_DIR}"
find "${INSTALL_DIR}/templates" -type d -exec chmod 0755 {} \;
find "${INSTALL_DIR}/templates" -type f -exec chmod 0644 {} \;
SOCKET_PATH="${SOCKET_DIR}/web.sock"
if [[ ! -f "${CONFIG_DIR}/config.yaml" ]]; then
SECRET=$(openssl rand -hex 32)
cat > "${CONFIG_DIR}/config.yaml" <<EOF
database:
type: sqlite
dsn: ""
web:
port: "8080"
socket: ${SOCKET_PATH}
path: ${DATA_DIR}
secret: ${SECRET}
EOF
chown "${SERVICE_USER}:${SERVICE_USER}" "${CONFIG_DIR}/config.yaml"
chmod 0640 "${CONFIG_DIR}/config.yaml"
fi
echo "写入 systemd 服务文件..."
cat > "${SERVICE_FILE}" <<EOF
[Unit]
Description=Blog Go Service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=${SERVICE_USER}
Group=${SERVICE_USER}
WorkingDirectory=${INSTALL_DIR}
ExecStart=${INSTALL_DIR}/${BINARY_NAME} -config ${CONFIG_DIR}/config.yaml
ExecStartPost=/bin/sh -c 'while [ ! -S ${SOCKET_DIR}/web.sock ]; do sleep 0.1; done; chmod 666 ${SOCKET_DIR}/web.sock'
Restart=on-failure
RestartSec=5s
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ReadWritePaths=${CONFIG_DIR} ${DATA_DIR} ${INSTALL_DIR} ${SOCKET_DIR}
RuntimeDirectory=${SERVICE_NAME}
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable "${SERVICE_NAME}"
systemctl restart "${SERVICE_NAME}"
echo "部署完成,服务状态:"
systemctl --no-pager --full status "${SERVICE_NAME}"