因为借助大模型一直在emlog上增加东西,但是线上的目录因为权限、安全的原因又不能直接git pull,因此重新梳理部署的安装流程。

1. 整体思路

线上emlog下有3个目录:

  • releases/<时间戳>:每次发版的只读代码副本
  • shared/:持久写入目录(uploads/ cache/ runtime/ storage/ logs 等)
  • current -> releases/<时间戳>:Nginx/Apache 指向这个软链(原子切换)
    云端/构建机:git pull、构建产物,然后用 rsync 拷到线上新建的 release 目录,最后切软链

1.1 线上服务准备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 新增emlog,专门作为部署emlog
sudo adduser --disabled-password --gecos "" ubuntu || true
sudo usermod -aG www-data ubuntu

# 目录结构
cd /var/www/deployment
sudo mkdir -p ./{releases,shared}
# 共享写入目录(按你项目实际增减)
sudo mkdir -p shared/{uploads,cache,runtime,storage,logs}
sudo mkdir -p shared/content/{backup,cache,uploadfile}

# 权限设置:目录属主 emlog,组 www-data;目录继承组位
cd /var/www
sudo chown -R ubuntu:www-data deployment
sudo find deployment -type d -exec chmod 2775 {} \;
sudo find deployment -type f -exec chmod 0664 {} \;

# 共享目录给 www-data 可写(其余代码保持只读)
cd /var/www
for d in uploads cache runtime storage logs content/*; do
sudo chown -R www-data:www-data ./deployment/shared/$d
sudo find ./deployment/shared/$d -type d -exec chmod 2775 {} \;
sudo find ./deployment/shared/$d -type f -exec chmod 0664 {} \;
done

# 创建数据和配置文件
cd /var/www
sudo mkdir -p ./deployment/shared/mysql_data
sudo chown -R mysql:mysql ./deployment/shared/mysql_data
sudo find ./deployment/shared/mysql_data -type d -exec sudo chmod 0750 {} \;
sudo find ./deployment/shared/mysql_data -type f -exec sudo chmod 0640 {} \;

sudo touch ./deployment/shared/config.php
sudo chown ubuntu:www-data ./deployment/shared/config.php
sudo chmod 0640 ./deployment/shared/config.php

# Web 站点根指向 /var/www/yourapp/current
# 并确保禁止访问 .git(双保险)
# Nginx:
# location ~ /\.git { deny all; }
# Apache:
# RedirectMatch 404 /\.git

1.2 git clone

下载对应代码

1
2
cd /var/www
git clone https://github.com/apostle9891/emlog_modify.git

新建同步代码vim emlog_sync.sh,需要修改WWW_DIR的目录地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#!/bin/bash
set -euo pipefail
umask 002 # 新文件组可写(配合 www-data 组)

WWW_DIR="/var/www"
REPO_URL="https://github.com/apostle9891/emlog_modify.git" # 改成你的仓库地址(https 或 ssh 都行)
BUILD="$WWW_DIR/emlog_modify"
REMOTE="$WWW_DIR/deployment"
TS="$(date +%Y%m%d%H%M%S)"
RELEASE="$REMOTE/releases/$TS"

# 1) 在“构建区”拉代码与构建(不在 web 根)
if [ ! -d "$BUILD/.git" ]; then
mkdir -p "$BUILD"
# 初次 clone(若用 ssh,需要 ubuntu 用户已配好私钥)
git clone "$REPO_URL" "$BUILD"
fi
cd "$BUILD"
git pull --ff-only

# === 按你的技术栈选择开启(示例) ===
# PHP: composer install --no-dev -o
# Node: npm ci && npm run build
# Python: pip install -r requirements.txt --target .venv # 或 poetry export + 构建
# 前端产物:确保已生成到 dist/ 或 public/build/ 等目录
# ===================================

# 2) 准备新版本目录
mkdir -p "$RELEASE"

# 3) 本地 rsync 到 RELEASE(不走 ssh;排除 .git 与写入目录)
rsync -a --delete \
--exclude '.git' \
--exclude '.github' \
--exclude 'node_modules' \
--exclude 'uploads' --exclude 'cache' --exclude 'runtime' --exclude 'storage' --exclude 'logs' \
--exclude 'config.php' --exclude 'mysql_data' \
"$BUILD"/ "$RELEASE"/

# 4) 在 RELEASE 里把写入型目录挂到 shared
cd "$RELEASE"
for d in uploads cache runtime storage logs mysql_data content/cache content/backup content/uploadfile; do
rm -rf "$d"
ln -s "$REMOTE/shared/$d" "$d"
done

# 单文件软链:config.php
rm -f config.php
ln -s "$REMOTE/shared/config.php" config.php

# 5) 统一权限(代码只读;写入目录已 www-data 可写)
chown -R ubuntu:www-data "$RELEASE"
find "$RELEASE" -type d -exec chmod 2755 {} \;
find "$RELEASE" -type f -exec chmod 0644 {} \;

# 6) 原子切换 current(零停机)
ln -sfn "$RELEASE" "$REMOTE/current"

# 7) 可选:重载服务(按需开启)
# systemctl reload php7.4-fpm || true
# systemctl reload nginx || true

echo "Deployed $BUILD -> $RELEASE"

设置权限

1
sudo chmod +x ./emlog_sync.sh

1.3 原有emlog迁移

因为已经部署了emlog的代码,我们需要把对应的缓存数据迁移到share中。执行以下脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!/usr/bin/env bash
set -euo pipefail

########################################
# 可根据需要修改
########################################
SRC="/var/www/emlog" # 现有已部署目录
DST="/var/www/deployment/share" # 目标共享目录
CODE_USER="ubuntu" # 代码/配置文件属主
CODE_GROUP="www-data" # 代码/配置文件属组
WRITE_USER="www-data" # 运行期目录写入用户
WRITE_GROUP="www-data" # 运行期目录写入组
MYSQL_OWNER="mysql:mysql" # mysql_data 的属主(若不用本机 MySQL,可留成 www-data)
MOVE_DIRS=(uploads cache runtime storage logs mysql_data)
CONFIG_FILE="config.php"

########################################
# 前置检查
########################################
if [[ ! -d "$SRC" ]]; then
echo "ERROR: 源目录不存在:$SRC" >&2
exit 1
fi

mkdir -p "$DST"

########################################
# 备份(可选)
########################################
TS="$(date +%Y%m%d%H%M%S)"
BACKUP="/tmp/emlog_migrate_backup_${TS}.tgz"
echo "将迁移以下内容:${MOVE_DIRS[*]} 以及 ${CONFIG_FILE}"
read -rp "是否先备份这些内容到 ${BACKUP}? [Y/n] " ans
ans=${ans:-Y}
if [[ "$ans" =~ ^[Yy]$ ]]; then
echo ">>> 备份中..."
INCLUDES=()
for d in "${MOVE_DIRS[@]}"; do
[[ -e "$SRC/$d" ]] && INCLUDES+=("$d")
done
[[ -f "$SRC/$CONFIG_FILE" ]] && INCLUDES+=("$CONFIG_FILE")
if ((${#INCLUDES[@]})); then
tar -C "$SRC" -czf "$BACKUP" "${INCLUDES[@]}"
echo ">>> 备份完成:$BACKUP"
else
echo ">>> 源中无需备份的对象,跳过打包。"
fi
fi

########################################
# 准备目标目录与权限基线
########################################
chown -R "$CODE_USER:$CODE_GROUP" "$DST"
find "$DST" -type d -exec chmod 2775 {} \; 2>/dev/null || true
find "$DST" -type f -exec chmod 0664 {} \; 2>/dev/null || true

########################################
# 迁移目录函数(合并 -> 删除源 -> 建软链 -> 权限)
########################################
move_dir() {
local name="$1"
local src="$SRC/$name"
local dst="$DST/$name"

# 若源已经是软链,跳过
if [[ -L "$src" ]]; then
echo "跳过:$src 已是软链。"
return 0
fi

# 目标目录准备好
mkdir -p "$dst"

if [[ -d "$src" ]]; then
echo ">>> 同步 $src -> $dst"
# 合并同步;尽量保持权限/时间;如果没有子内容,rsync 会返回非零,用 || true 忽略
rsync -a --delete "$src"/ "$dst"/ 2>/dev/null || rsync -a "$src"/ "$dst"/ || true
echo ">>> 移除源并创建软链 $src -> $dst"
rm -rf "$src"
ln -s "$dst" "$src"
else
echo "提示:$src 不存在,创建软链到目标空目录。"
ln -s "$dst" "$src"
fi

# 权限:运行期目录给运行用户/组;mysql_data 单独处理
if [[ "$name" == "mysql_data" ]]; then
# 若你确实把 MySQL 的 datadir 放到这里,建议用 mysql:mysql;否则可改为 www-data
chown -R "$MYSQL_OWNER" "$dst" 2>/dev/null || chown -R "$WRITE_USER:$WRITE_GROUP" "$dst"
find "$dst" -type d -exec chmod 0750 {} \; 2>/dev/null || true
find "$dst" -type f -exec chmod 0640 {} \; 2>/dev/null || true
else
chown -R "$WRITE_USER:$WRITE_GROUP" "$dst"
find "$dst" -type d -exec chmod 2775 {} \;
find "$dst" -type f -exec chmod 0664 {} \;
fi
}

########################################
# 执行目录迁移
########################################
for d in "${MOVE_DIRS[@]}"; do
move_dir "$d"
done

########################################
# 迁移 config.php(单文件)
########################################
SRC_CFG="$SRC/$CONFIG_FILE"
DST_CFG="$DST/$CONFIG_FILE"

# 若目标不存在,从源复制;存在则以目标为准
if [[ -f "$SRC_CFG" && ! -e "$DST_CFG" ]]; then
echo ">>> 复制 $SRC_CFG -> $DST_CFG"
install -o "$CODE_USER" -g "$CODE_GROUP" -m 0640 "$SRC_CFG" "$DST_CFG"
elif [[ -f "$SRC_CFG" && -f "$DST_CFG" ]]; then
echo ">>> 目标已存在 $DST_CFG,保留目标,源将改为软链。"
elif [[ ! -f "$SRC_CFG" && ! -e "$DST_CFG" ]]; then
echo "提示:未发现 $CONFIG_FILE(源与目标都没有),跳过。"
fi

# 源侧替换为软链(若源存在实体或目标已存在)
if [[ -e "$DST_CFG" ]]; then
[[ -e "$SRC_CFG" && ! -L "$SRC_CFG" ]] && rm -f "$SRC_CFG"
[[ -L "$SRC_CFG" ]] || ln -s "$DST_CFG" "$SRC_CFG"
chown "$CODE_USER:$CODE_GROUP" "$DST_CFG"
chmod 0640 "$DST_CFG"
fi

########################################
# 最后:源目录的其它文件权限(可选微调)
########################################
find "$SRC" -maxdepth 1 -mindepth 1 -type d ! -lname '*' -exec true {} \; >/dev/null 2>&1 || true
chown -R "$CODE_USER:$CODE_GROUP" "$SRC"
find "$SRC" -type d -exec chmod 2755 {} \; 2>/dev/null || true
find "$SRC" -type f -exec chmod 0644 {} \; 2>/dev/null || true

echo "✅ 迁移完成:
- 目录:${MOVE_DIRS[*]} 已迁至 $DST 并在 $SRC 建立软链
- 文件:$CONFIG_FILE 已放置于 $DST 并在 $SRC 建立软链
请确认服务正常运行。"

1.4 迁移成功

执行1.3的脚本,迁移完毕后,可以进行同步,记得nginx的根目录/var/www/deployment/current

1
sudo -u ubuntu ./emlog_sync.sh