fix config
This commit is contained in:
parent
a2483d3c5d
commit
7cb84ae9ca
310
install_service.md
Normal file
310
install_service.md
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
# install_service.sh 规则与参考原则
|
||||||
|
|
||||||
|
本文档说明 `shell/install_service.sh` 的配置规则、安装流程和后续维护原则。
|
||||||
|
|
||||||
|
## 目标
|
||||||
|
|
||||||
|
`install_service.sh` 用于自动安装并通过 systemd 管理 `iot` 和 `efka` 服务。
|
||||||
|
|
||||||
|
脚本负责:
|
||||||
|
|
||||||
|
- 下载服务发布包。
|
||||||
|
- 解压到 `WORK_DIR`。
|
||||||
|
- 创建运行所需目录。
|
||||||
|
- 生成 `/etc/systemd/system/<service>.service`。
|
||||||
|
- 将服务环境变量写入对应 `.service` 文件。
|
||||||
|
- 执行 `systemctl daemon-reload`。
|
||||||
|
- 设置服务开机启动并启动服务。
|
||||||
|
|
||||||
|
## 顶部配置规则
|
||||||
|
|
||||||
|
脚本顶部是主要维护区域。后续修改下载包、启动命令、环境变量、目录变量时,应优先修改顶部配置。
|
||||||
|
|
||||||
|
### INSTALL_IOT / INSTALL_EFKA
|
||||||
|
|
||||||
|
`INSTALL_IOT` 和 `INSTALL_EFKA` 分别配置服务安装信息,不再合并成统一的 `INSTALL_ITEMS`。
|
||||||
|
|
||||||
|
格式:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
INSTALL_<APP>=(
|
||||||
|
"service_name"
|
||||||
|
"download_url"
|
||||||
|
"start_command"
|
||||||
|
"stop_command"
|
||||||
|
"service_user"
|
||||||
|
"service_group"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
字段说明:
|
||||||
|
|
||||||
|
- `service_name`: systemd 服务名,例如 `iot`、`efka`。
|
||||||
|
- `download_url`: 发布包下载地址,仅支持 `.tar.gz` 或 `.tgz`。
|
||||||
|
- `start_command`: systemd `ExecStart` 命令。
|
||||||
|
- `stop_command`: systemd `ExecStop` 命令,可为空。
|
||||||
|
- `service_user`: 服务运行用户,可为空;为空时使用脚本默认 `SERVICE_USER`。
|
||||||
|
- `service_group`: 服务运行组,可为空;为空时使用脚本默认 `SERVICE_GROUP`。
|
||||||
|
|
||||||
|
命令中可使用占位符:
|
||||||
|
|
||||||
|
- `{install_dir}`: 解压后的服务安装目录。
|
||||||
|
- `{work_dir}`: 脚本工作目录。
|
||||||
|
- `{service_name}`: 当前服务名。
|
||||||
|
|
||||||
|
### IOT_ENV / EFKA_ENV
|
||||||
|
|
||||||
|
`IOT_ENV` 和 `EFKA_ENV` 配置对应项目的生产环境变量,来源参考各项目 `env.file` 中的 `[prod]` 配置。
|
||||||
|
|
||||||
|
格式:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
IOT_ENV=(
|
||||||
|
"KEY=value"
|
||||||
|
)
|
||||||
|
|
||||||
|
EFKA_ENV=(
|
||||||
|
"KEY=value"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
这些变量不会写入 `/etc/default/*`,也不会使用 `EnvironmentFile=`。
|
||||||
|
|
||||||
|
脚本会直接将它们写入对应 systemd service:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
Environment="KEY=value"
|
||||||
|
```
|
||||||
|
|
||||||
|
这样环境变量由 systemd unit 统一管理,可通过 `systemctl cat <service>` 查看最终配置。
|
||||||
|
|
||||||
|
### IOT_DIR_ENV_KEYS / EFKA_DIR_ENV_KEYS
|
||||||
|
|
||||||
|
`IOT_DIR_ENV_KEYS` 和 `EFKA_DIR_ENV_KEYS` 声明哪些环境变量的值是目录。
|
||||||
|
|
||||||
|
格式:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
IOT_DIR_ENV_KEYS=(
|
||||||
|
"ENDPOINT_ROOT_DIR"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
安装时脚本会:
|
||||||
|
|
||||||
|
- 从对应 `*_ENV` 中读取变量值。
|
||||||
|
- 替换占位符。
|
||||||
|
- 要求目录必须是绝对路径。
|
||||||
|
- 如果目录不存在,则创建。
|
||||||
|
- 将目录 owner 设置为服务用户和服务组。
|
||||||
|
|
||||||
|
当前 iot 会创建:
|
||||||
|
|
||||||
|
- `/var/lib/endpoint/database/`
|
||||||
|
- `/var/lib/endpoint/endpoint_log`
|
||||||
|
- `/var/lib/iot/mnesia/`
|
||||||
|
|
||||||
|
当前 efka 会创建:
|
||||||
|
|
||||||
|
- `/var/lib/efka/dets/`
|
||||||
|
- `/var/lib/efka/docker/`
|
||||||
|
- `/var/lib/efka/mnesia`
|
||||||
|
|
||||||
|
## 安装流程
|
||||||
|
|
||||||
|
脚本执行顺序:
|
||||||
|
|
||||||
|
1. 解析命令行参数。
|
||||||
|
2. 校验 `WORK_DIR` 和服务配置。
|
||||||
|
3. 检查依赖命令:`wget`、`tar`、`systemctl`。
|
||||||
|
4. 创建 `WORK_DIR`。
|
||||||
|
5. 依次安装 `iot` 和 `efka`。
|
||||||
|
6. 重新加载 systemd。
|
||||||
|
7. enable 并 start 已安装服务。
|
||||||
|
|
||||||
|
单个服务安装流程:
|
||||||
|
|
||||||
|
1. 校验服务名、下载地址、启动命令。
|
||||||
|
2. 根据下载地址推导压缩包名和安装目录。
|
||||||
|
3. 下载压缩包到临时文件。
|
||||||
|
4. 保存压缩包到 `WORK_DIR`。
|
||||||
|
5. 创建安装目录。
|
||||||
|
6. 解压压缩包。
|
||||||
|
7. 设置安装目录 owner。
|
||||||
|
8. 根据 `*_DIR_ENV_KEYS` 创建数据目录。
|
||||||
|
9. 生成 systemd service 文件。
|
||||||
|
10. 记录服务名,后续统一 enable/start。
|
||||||
|
|
||||||
|
## systemd service 生成规则
|
||||||
|
|
||||||
|
每个服务会生成:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/etc/systemd/system/<service_name>.service
|
||||||
|
```
|
||||||
|
|
||||||
|
service 文件包含:
|
||||||
|
|
||||||
|
- `User`
|
||||||
|
- `Group`
|
||||||
|
- `WorkingDirectory`
|
||||||
|
- 多行 `Environment="KEY=value"`
|
||||||
|
- `ExecStart`
|
||||||
|
- `ExecStop`
|
||||||
|
- `Restart=on-failure`
|
||||||
|
- `RestartSec=5`
|
||||||
|
|
||||||
|
环境变量必须写入服务自己的 `.service` 文件,而不是外部环境文件。
|
||||||
|
|
||||||
|
## 目录创建原则
|
||||||
|
|
||||||
|
只有明确列入 `IOT_DIR_ENV_KEYS` 或 `EFKA_DIR_ENV_KEYS` 的环境变量才会作为目录创建。
|
||||||
|
|
||||||
|
这样做的原因:
|
||||||
|
|
||||||
|
- 避免误把 URL、token、host 等普通变量当成路径。
|
||||||
|
- 新增目录型变量时行为明确。
|
||||||
|
- 目录创建逻辑和环境变量配置保持关联。
|
||||||
|
|
||||||
|
新增目录型环境变量时,需要同时修改两处:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
IOT_ENV=(
|
||||||
|
"NEW_DATA_DIR=/var/lib/iot/new_data"
|
||||||
|
)
|
||||||
|
|
||||||
|
IOT_DIR_ENV_KEYS=(
|
||||||
|
"NEW_DATA_DIR"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
非目录型环境变量只需要加入 `*_ENV`,不要加入 `*_DIR_ENV_KEYS`。
|
||||||
|
|
||||||
|
## 权限原则
|
||||||
|
|
||||||
|
脚本支持 root 或普通用户运行。
|
||||||
|
|
||||||
|
- 如果当前是 root,直接执行需要 root 权限的命令。
|
||||||
|
- 如果不是 root,通过 `sudo` 执行。
|
||||||
|
- 数据目录和安装目录 owner 会设置为服务运行用户和组。
|
||||||
|
- systemd service 文件写入 `/etc/systemd/system`,需要 root 权限。
|
||||||
|
|
||||||
|
默认服务用户:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
SERVICE_USER="${SERVICE_USER:-$CURRENT_USER}"
|
||||||
|
SERVICE_GROUP="${SERVICE_GROUP:-$(id -gn "$SERVICE_USER")}"
|
||||||
|
```
|
||||||
|
|
||||||
|
可通过参数覆盖:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./install_service.sh --user app --group app
|
||||||
|
```
|
||||||
|
|
||||||
|
## 占位符原则
|
||||||
|
|
||||||
|
以下位置支持占位符:
|
||||||
|
|
||||||
|
- 启动命令。
|
||||||
|
- 停止命令。
|
||||||
|
- 环境变量值。
|
||||||
|
- 目录路径。
|
||||||
|
|
||||||
|
支持的占位符:
|
||||||
|
|
||||||
|
- `{install_dir}`
|
||||||
|
- `{work_dir}`
|
||||||
|
- `{service_name}`
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
"LOG_DIR={work_dir}/var/log/{service_name}"
|
||||||
|
```
|
||||||
|
|
||||||
|
如果该变量是目录,需要加入对应 `*_DIR_ENV_KEYS`。
|
||||||
|
|
||||||
|
## 修改和扩展原则
|
||||||
|
|
||||||
|
### 修改环境变量
|
||||||
|
|
||||||
|
只修改顶部对应数组:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
IOT_ENV=(
|
||||||
|
"IOT_API_URL=http://127.0.0.1/api/v1"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
修改后重新执行安装脚本,会重新生成 service 文件。
|
||||||
|
|
||||||
|
### 新增目录
|
||||||
|
|
||||||
|
同时修改:
|
||||||
|
|
||||||
|
- `IOT_ENV` 或 `EFKA_ENV`
|
||||||
|
- `IOT_DIR_ENV_KEYS` 或 `EFKA_DIR_ENV_KEYS`
|
||||||
|
|
||||||
|
### 修改下载包
|
||||||
|
|
||||||
|
只修改:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
INSTALL_IOT=(
|
||||||
|
"iot"
|
||||||
|
"https://example.com/iot-x.y.z.tar.gz"
|
||||||
|
...
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
下载包后缀必须是:
|
||||||
|
|
||||||
|
- `.tar.gz`
|
||||||
|
- `.tgz`
|
||||||
|
|
||||||
|
### 新增服务
|
||||||
|
|
||||||
|
新增服务时应保持当前结构:
|
||||||
|
|
||||||
|
1. 新增 `INSTALL_<APP>`。
|
||||||
|
2. 新增 `<APP>_ENV`。
|
||||||
|
3. 新增 `<APP>_DIR_ENV_KEYS`。
|
||||||
|
4. 在 `validate_args` 中增加配置校验。
|
||||||
|
5. 在 `service_env_lines` 中映射服务名到 env 数组。
|
||||||
|
6. 在 `service_dir_env_keys` 中映射服务名到目录 key 数组。
|
||||||
|
7. 在 `install_programs` 中调用 `install_program_from_config`。
|
||||||
|
|
||||||
|
## 兼容性原则
|
||||||
|
|
||||||
|
脚本当前兼容 Bash 3.2,不使用 `local -n` 等较新的 Bash 特性。
|
||||||
|
|
||||||
|
读取动态数组时使用 `eval`,因此数组名必须由脚本内部固定传入,不应使用用户输入构造数组名。
|
||||||
|
|
||||||
|
## 验证建议
|
||||||
|
|
||||||
|
修改脚本后至少执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash -n shell/install_service.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
建议额外验证 service 渲染结果:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash -c "$(sed '$d' shell/install_service.sh); render_service_file iot app app /opt/app/iot-0.1.0 '/opt/app/iot-0.1.0/bin/iot foreground' '/opt/app/iot-0.1.0/bin/iot stop'"
|
||||||
|
```
|
||||||
|
|
||||||
|
如果目标机器有 `systemd-analyze`,可进一步验证生成后的 unit 文件:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemd-analyze verify /etc/systemd/system/iot.service
|
||||||
|
systemd-analyze verify /etc/systemd/system/efka.service
|
||||||
|
```
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
- 环境变量中如包含空格或特殊字符,需要确认 systemd `Environment=` 语法是否仍然正确。
|
||||||
|
- token 等敏感信息会写入 systemd service 文件,需控制 `/etc/systemd/system/*.service` 的读取权限和服务器访问权限。
|
||||||
|
- 数据目录必须使用绝对路径。
|
||||||
|
- 现有卸载脚本如果需要同步目录清理规则,应按 `IOT_DIR_ENV_KEYS` / `EFKA_DIR_ENV_KEYS` 的思路同步调整。
|
||||||
Loading…
x
Reference in New Issue
Block a user