fix md
This commit is contained in:
parent
16e63a5c74
commit
719b539b3f
@ -152,6 +152,15 @@ strip_archive_suffix() {
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
archive_name_from_url() {
|
||||||
|
local download_url="$1"
|
||||||
|
local clean_url="$download_url"
|
||||||
|
|
||||||
|
clean_url="${clean_url%%\?*}"
|
||||||
|
clean_url="${clean_url%%#*}"
|
||||||
|
basename "$clean_url"
|
||||||
|
}
|
||||||
|
|
||||||
parse_args() {
|
parse_args() {
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
@ -394,21 +403,17 @@ install_program() {
|
|||||||
local stop_command="$4"
|
local stop_command="$4"
|
||||||
local service_user="$5"
|
local service_user="$5"
|
||||||
local service_group="$6"
|
local service_group="$6"
|
||||||
local clean_url="$download_url"
|
|
||||||
local archive_name
|
local archive_name
|
||||||
|
|
||||||
validate_install_item "$service_name" "$download_url" "$start_command"
|
validate_install_item "$service_name" "$download_url" "$start_command"
|
||||||
|
|
||||||
clean_url="${clean_url%%\?*}"
|
archive_name="$(archive_name_from_url "$download_url")"
|
||||||
clean_url="${clean_url%%#*}"
|
|
||||||
archive_name="$(basename "$clean_url")"
|
|
||||||
[[ -n "$archive_name" ]] || fail "Cannot parse archive filename from URL: $download_url"
|
[[ -n "$archive_name" ]] || fail "Cannot parse archive filename from URL: $download_url"
|
||||||
|
|
||||||
local app_dir_name
|
strip_archive_suffix "$archive_name" >/dev/null
|
||||||
app_dir_name="$(strip_archive_suffix "$archive_name")"
|
|
||||||
|
|
||||||
local archive_path="${WORK_DIR}/${archive_name}"
|
local archive_path="${WORK_DIR}/${archive_name}"
|
||||||
local install_dir="${WORK_DIR}/${app_dir_name}"
|
local install_dir="${WORK_DIR}/${service_name}"
|
||||||
local service_file="/etc/systemd/system/${service_name}.service"
|
local service_file="/etc/systemd/system/${service_name}.service"
|
||||||
local temp_archive
|
local temp_archive
|
||||||
temp_archive="$(mktemp)"
|
temp_archive="$(mktemp)"
|
||||||
@ -429,6 +434,9 @@ install_program() {
|
|||||||
log "Extracting archive to $install_dir"
|
log "Extracting archive to $install_dir"
|
||||||
run_as_root tar -zxvf "$archive_path" -C "$install_dir"
|
run_as_root tar -zxvf "$archive_path" -C "$install_dir"
|
||||||
|
|
||||||
|
log "Removing downloaded archive: $archive_path"
|
||||||
|
run_as_root rm -f "$archive_path"
|
||||||
|
|
||||||
log "Setting owner for install directory: ${service_user}:${service_group}"
|
log "Setting owner for install directory: ${service_user}:${service_group}"
|
||||||
run_as_root chown -R "${service_user}:${service_group}" "$install_dir"
|
run_as_root chown -R "${service_user}:${service_group}" "$install_dir"
|
||||||
|
|
||||||
|
|||||||
@ -158,6 +158,15 @@ strip_archive_suffix() {
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
archive_name_from_url() {
|
||||||
|
local download_url="$1"
|
||||||
|
local clean_url="$download_url"
|
||||||
|
|
||||||
|
clean_url="${clean_url%%\?*}"
|
||||||
|
clean_url="${clean_url%%#*}"
|
||||||
|
basename "$clean_url"
|
||||||
|
}
|
||||||
|
|
||||||
parse_args() {
|
parse_args() {
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
@ -441,6 +450,18 @@ create_parent_dependency_dirs_from_env() {
|
|||||||
done < <(service_parent_dir_env_keys "$service_name")
|
done < <(service_parent_dir_env_keys "$service_name")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
link_iot_ctrl() {
|
||||||
|
local install_dir="$1"
|
||||||
|
local iot_ctrl_path="${install_dir}/bin/iot_ctrl"
|
||||||
|
local link_path="/usr/local/bin/iot_ctrl"
|
||||||
|
|
||||||
|
[[ -x "$iot_ctrl_path" ]] || fail "Missing executable iot control tool: $iot_ctrl_path. Build it before packaging the release"
|
||||||
|
|
||||||
|
log "Linking iot control tool: $link_path -> $iot_ctrl_path"
|
||||||
|
run_as_root install -d -m 0755 "$(dirname "$link_path")"
|
||||||
|
run_as_root ln -sfn "$iot_ctrl_path" "$link_path"
|
||||||
|
}
|
||||||
|
|
||||||
install_program() {
|
install_program() {
|
||||||
local service_name="$1"
|
local service_name="$1"
|
||||||
local download_url="$2"
|
local download_url="$2"
|
||||||
@ -448,21 +469,17 @@ install_program() {
|
|||||||
local stop_command="$4"
|
local stop_command="$4"
|
||||||
local service_user="$5"
|
local service_user="$5"
|
||||||
local service_group="$6"
|
local service_group="$6"
|
||||||
local clean_url="$download_url"
|
|
||||||
local archive_name
|
local archive_name
|
||||||
|
|
||||||
validate_install_item "$service_name" "$download_url" "$start_command"
|
validate_install_item "$service_name" "$download_url" "$start_command"
|
||||||
|
|
||||||
clean_url="${clean_url%%\?*}"
|
archive_name="$(archive_name_from_url "$download_url")"
|
||||||
clean_url="${clean_url%%#*}"
|
|
||||||
archive_name="$(basename "$clean_url")"
|
|
||||||
[[ -n "$archive_name" ]] || fail "Cannot parse archive filename from URL: $download_url"
|
[[ -n "$archive_name" ]] || fail "Cannot parse archive filename from URL: $download_url"
|
||||||
|
|
||||||
local app_dir_name
|
strip_archive_suffix "$archive_name" >/dev/null
|
||||||
app_dir_name="$(strip_archive_suffix "$archive_name")"
|
|
||||||
|
|
||||||
local archive_path="${WORK_DIR}/${archive_name}"
|
local archive_path="${WORK_DIR}/${archive_name}"
|
||||||
local install_dir="${WORK_DIR}/${app_dir_name}"
|
local install_dir="${WORK_DIR}/${service_name}"
|
||||||
local service_file="/etc/systemd/system/${service_name}.service"
|
local service_file="/etc/systemd/system/${service_name}.service"
|
||||||
local temp_archive
|
local temp_archive
|
||||||
temp_archive="$(mktemp)"
|
temp_archive="$(mktemp)"
|
||||||
@ -483,11 +500,15 @@ install_program() {
|
|||||||
log "Extracting archive to $install_dir"
|
log "Extracting archive to $install_dir"
|
||||||
run_as_root tar -zxvf "$archive_path" -C "$install_dir"
|
run_as_root tar -zxvf "$archive_path" -C "$install_dir"
|
||||||
|
|
||||||
|
log "Removing downloaded archive: $archive_path"
|
||||||
|
run_as_root rm -f "$archive_path"
|
||||||
|
|
||||||
log "Setting owner for install directory: ${service_user}:${service_group}"
|
log "Setting owner for install directory: ${service_user}:${service_group}"
|
||||||
run_as_root chown -R "${service_user}:${service_group}" "$install_dir"
|
run_as_root chown -R "${service_user}:${service_group}" "$install_dir"
|
||||||
|
|
||||||
create_dependency_dirs_from_env "$service_name" "$install_dir" "$service_user" "$service_group"
|
create_dependency_dirs_from_env "$service_name" "$install_dir" "$service_user" "$service_group"
|
||||||
create_parent_dependency_dirs_from_env "$service_name" "$install_dir" "$service_user" "$service_group"
|
create_parent_dependency_dirs_from_env "$service_name" "$install_dir" "$service_user" "$service_group"
|
||||||
|
link_iot_ctrl "$install_dir"
|
||||||
|
|
||||||
write_service_file "$service_file" "$service_name" "$service_user" "$service_group" "$install_dir" "$start_command" "$stop_command"
|
write_service_file "$service_file" "$service_name" "$service_user" "$service_group" "$install_dir" "$start_command" "$stop_command"
|
||||||
INSTALLED_SERVICES+=("$service_name")
|
INSTALLED_SERVICES+=("$service_name")
|
||||||
@ -549,6 +570,7 @@ main() {
|
|||||||
require_command wget
|
require_command wget
|
||||||
require_root_runner
|
require_root_runner
|
||||||
require_command dirname
|
require_command dirname
|
||||||
|
require_command ln
|
||||||
require_command tar
|
require_command tar
|
||||||
require_command systemctl
|
require_command systemctl
|
||||||
|
|
||||||
|
|||||||
@ -13,11 +13,13 @@
|
|||||||
|
|
||||||
- 下载服务发布包。
|
- 下载服务发布包。
|
||||||
- 解压到 `WORK_DIR`。
|
- 解压到 `WORK_DIR`。
|
||||||
|
- 删除下载到 `WORK_DIR` 的压缩包。
|
||||||
- 创建运行所需目录。
|
- 创建运行所需目录。
|
||||||
- 生成 `/etc/systemd/system/<service>.service`。
|
- 生成 `/etc/systemd/system/<service>.service`。
|
||||||
- 将服务环境变量写入对应 `.service` 文件。
|
- 将服务环境变量写入对应 `.service` 文件。
|
||||||
- 执行 `systemctl daemon-reload`。
|
- 执行 `systemctl daemon-reload`。
|
||||||
- 设置服务开机启动。
|
- 设置服务开机启动。
|
||||||
|
- `install_iot.sh` 会将 `{install_dir}/bin/iot_ctrl` 软链接到 `/usr/local/bin/iot_ctrl`。
|
||||||
|
|
||||||
## 入口规则
|
## 入口规则
|
||||||
|
|
||||||
@ -72,7 +74,7 @@ INSTALL_<APP>=(
|
|||||||
|
|
||||||
命令中可使用占位符:
|
命令中可使用占位符:
|
||||||
|
|
||||||
- `{install_dir}`: 解压后的服务安装目录。
|
- `{install_dir}`: 解压后的服务安装目录,当前为 `{work_dir}/{service_name}`,例如 `/opt/app/iot`、`/opt/app/efka`。
|
||||||
- `{work_dir}`: 脚本工作目录。
|
- `{work_dir}`: 脚本工作目录。
|
||||||
- `{service_name}`: 当前服务名。
|
- `{service_name}`: 当前服务名。
|
||||||
|
|
||||||
@ -123,7 +125,7 @@ Environment="KEY=value"
|
|||||||
|
|
||||||
1. 解析命令行参数。
|
1. 解析命令行参数。
|
||||||
2. 校验 `WORK_DIR` 和服务配置。
|
2. 校验 `WORK_DIR` 和服务配置。
|
||||||
3. 检查依赖命令:`wget`、`dirname`、`tar`、`systemctl`。
|
3. 检查依赖命令:`wget`、`dirname`、`ln`、`tar`、`systemctl`。
|
||||||
4. 创建 `WORK_DIR`。
|
4. 创建 `WORK_DIR`。
|
||||||
5. 安装当前服务。
|
5. 安装当前服务。
|
||||||
6. 重新加载 systemd。
|
6. 重新加载 systemd。
|
||||||
@ -132,15 +134,51 @@ Environment="KEY=value"
|
|||||||
单个服务安装流程:
|
单个服务安装流程:
|
||||||
|
|
||||||
1. 校验服务名、下载地址、启动命令。
|
1. 校验服务名、下载地址、启动命令。
|
||||||
2. 根据下载地址推导压缩包名和安装目录。
|
2. 根据服务名推导安装目录,默认是 `/opt/app/<service_name>`。
|
||||||
3. 下载压缩包到临时文件。
|
3. 下载压缩包到临时文件。
|
||||||
4. 保存压缩包到 `WORK_DIR`。
|
4. 保存压缩包到 `WORK_DIR`。
|
||||||
5. 创建安装目录。
|
5. 创建安装目录。
|
||||||
6. 解压压缩包。
|
6. 解压压缩包。
|
||||||
7. 设置安装目录 owner。
|
7. 删除保存到 `WORK_DIR` 的压缩包。
|
||||||
8. 根据 `*_DIR_ENV_KEYS` 创建数据目录,并根据 `*_PARENT_DIR_ENV_KEYS` 创建文件路径父目录。
|
8. 设置安装目录 owner。
|
||||||
9. 生成 systemd service 文件。
|
9. 根据 `*_DIR_ENV_KEYS` 创建数据目录,并根据 `*_PARENT_DIR_ENV_KEYS` 创建文件路径父目录。
|
||||||
10. 记录服务名,后续统一 enable。
|
10. iot 安装时创建 `/usr/local/bin/iot_ctrl` 软链接。
|
||||||
|
11. 生成 systemd service 文件。
|
||||||
|
12. 记录服务名,后续统一 enable。
|
||||||
|
|
||||||
|
## iot_ctrl 构建和打包原则
|
||||||
|
|
||||||
|
`iot_ctrl` 位于 `iot/go_extend`,应在发布包构建阶段编译,不在 `install_iot.sh` 中编译。
|
||||||
|
|
||||||
|
目标机器不应依赖 Go 编译环境。发布包需要提前包含:
|
||||||
|
|
||||||
|
```text
|
||||||
|
iot/
|
||||||
|
bin/
|
||||||
|
iot
|
||||||
|
iot_ctrl
|
||||||
|
```
|
||||||
|
|
||||||
|
安装后脚本会检查 `{install_dir}/bin/iot_ctrl` 是否存在且可执行。如果不存在,安装会失败并提示需要在打包前构建该工具。
|
||||||
|
|
||||||
|
安装成功后会创建软链接:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/usr/local/bin/iot_ctrl -> /opt/app/iot/bin/iot_ctrl
|
||||||
|
```
|
||||||
|
|
||||||
|
构建示例:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd iot/go_extend
|
||||||
|
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 make build
|
||||||
|
```
|
||||||
|
|
||||||
|
如果目标机器是 arm64:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 make build
|
||||||
|
```
|
||||||
|
|
||||||
## systemd service 生成规则
|
## systemd service 生成规则
|
||||||
|
|
||||||
@ -233,6 +271,8 @@ SERVICE_GROUP="${SERVICE_GROUP:-$(id -gn "$SERVICE_USER")}"
|
|||||||
|
|
||||||
如果该变量是目录,需要加入对应 `*_DIR_ENV_KEYS`。如果该变量是文件路径,需要加入对应 `*_PARENT_DIR_ENV_KEYS`。
|
如果该变量是目录,需要加入对应 `*_DIR_ENV_KEYS`。如果该变量是文件路径,需要加入对应 `*_PARENT_DIR_ENV_KEYS`。
|
||||||
|
|
||||||
|
`{install_dir}` 不从压缩包文件名推导,不带版本号,固定使用服务名作为目录名。
|
||||||
|
|
||||||
## 修改和扩展原则
|
## 修改和扩展原则
|
||||||
|
|
||||||
### 修改环境变量
|
### 修改环境变量
|
||||||
@ -309,8 +349,8 @@ bash -n shell/install_efka.sh
|
|||||||
建议额外验证 service 渲染结果:
|
建议额外验证 service 渲染结果:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bash -c "$(sed '$d' shell/install_iot.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'"
|
bash -c "$(sed '$d' shell/install_iot.sh); render_service_file iot app app /opt/app/iot '/opt/app/iot/bin/iot foreground' '/opt/app/iot/bin/iot stop'"
|
||||||
bash -c "$(sed '$d' shell/install_efka.sh); render_service_file efka app app /opt/app/efka-0.1.0 '/opt/app/efka-0.1.0/bin/efka foreground' '/opt/app/efka-0.1.0/bin/efka stop'"
|
bash -c "$(sed '$d' shell/install_efka.sh); render_service_file efka app app /opt/app/efka '/opt/app/efka/bin/efka foreground' '/opt/app/efka/bin/efka stop'"
|
||||||
```
|
```
|
||||||
|
|
||||||
如果目标机器有 `systemd-analyze`,可进一步验证生成后的 unit 文件:
|
如果目标机器有 `systemd-analyze`,可进一步验证生成后的 unit 文件:
|
||||||
@ -325,4 +365,5 @@ systemd-analyze verify /etc/systemd/system/efka.service
|
|||||||
- 环境变量中如包含空格或特殊字符,需要确认 systemd `Environment=` 语法是否仍然正确。
|
- 环境变量中如包含空格或特殊字符,需要确认 systemd `Environment=` 语法是否仍然正确。
|
||||||
- token 等敏感信息会写入 systemd service 文件,需控制 `/etc/systemd/system/*.service` 的读取权限和服务器访问权限。
|
- token 等敏感信息会写入 systemd service 文件,需控制 `/etc/systemd/system/*.service` 的读取权限和服务器访问权限。
|
||||||
- 数据目录和文件路径型变量必须使用绝对路径。
|
- 数据目录和文件路径型变量必须使用绝对路径。
|
||||||
|
- iot 发布包必须包含可执行的 `bin/iot_ctrl`,否则不会创建 `/usr/local/bin/iot_ctrl` 链接。
|
||||||
- 现有卸载脚本如果需要同步目录清理规则,应按 `IOT_DIR_ENV_KEYS` / `EFKA_DIR_ENV_KEYS` 的思路同步调整。
|
- 现有卸载脚本如果需要同步目录清理规则,应按 `IOT_DIR_ENV_KEYS` / `EFKA_DIR_ENV_KEYS` 的思路同步调整。
|
||||||
|
|||||||
@ -27,7 +27,8 @@ Default behavior:
|
|||||||
- Disable services from boot.
|
- Disable services from boot.
|
||||||
- Remove /etc/systemd/system/<service>.service and service backups.
|
- Remove /etc/systemd/system/<service>.service and service backups.
|
||||||
- Run systemctl daemon-reload and reset-failed.
|
- Run systemctl daemon-reload and reset-failed.
|
||||||
- Remove downloaded archives and extracted program directories under WORK_DIR.
|
- Remove downloaded archives and service-name program directories under WORK_DIR.
|
||||||
|
- Remove /usr/local/bin/iot_ctrl.
|
||||||
- Keep dependency/data directories unless --purge-data is passed.
|
- Keep dependency/data directories unless --purge-data is passed.
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
@ -100,16 +101,6 @@ validate_args() {
|
|||||||
[[ "$item_count" -gt 0 ]] || fail "No programs configured. Fill INSTALL_ITEMS inside this script"
|
[[ "$item_count" -gt 0 ]] || fail "No programs configured. Fill INSTALL_ITEMS inside this script"
|
||||||
}
|
}
|
||||||
|
|
||||||
strip_archive_suffix() {
|
|
||||||
local filename="$1"
|
|
||||||
|
|
||||||
case "$filename" in
|
|
||||||
*.tar.gz) printf '%s\n' "${filename%.tar.gz}" ;;
|
|
||||||
*.tgz) printf '%s\n' "${filename%.tgz}" ;;
|
|
||||||
*) fail "Unsupported archive suffix: $filename. Expected .tar.gz or .tgz" ;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
archive_name_from_url() {
|
archive_name_from_url() {
|
||||||
local download_url="$1"
|
local download_url="$1"
|
||||||
local clean_url="$download_url"
|
local clean_url="$download_url"
|
||||||
@ -191,7 +182,6 @@ remove_program_files() {
|
|||||||
local service_user
|
local service_user
|
||||||
local service_group
|
local service_group
|
||||||
local archive_name
|
local archive_name
|
||||||
local app_dir_name
|
|
||||||
local archive_path
|
local archive_path
|
||||||
local install_dir
|
local install_dir
|
||||||
|
|
||||||
@ -205,9 +195,8 @@ remove_program_files() {
|
|||||||
archive_name="$(archive_name_from_url "$download_url")"
|
archive_name="$(archive_name_from_url "$download_url")"
|
||||||
[[ -n "$archive_name" ]] || fail "Cannot parse archive filename from URL: $download_url"
|
[[ -n "$archive_name" ]] || fail "Cannot parse archive filename from URL: $download_url"
|
||||||
|
|
||||||
app_dir_name="$(strip_archive_suffix "$archive_name")"
|
|
||||||
archive_path="${WORK_DIR}/${archive_name}"
|
archive_path="${WORK_DIR}/${archive_name}"
|
||||||
install_dir="${WORK_DIR}/${app_dir_name}"
|
install_dir="${WORK_DIR}/${service_name}"
|
||||||
|
|
||||||
log "Removing downloaded archive: $archive_path"
|
log "Removing downloaded archive: $archive_path"
|
||||||
run_as_root rm -f "$archive_path"
|
run_as_root rm -f "$archive_path"
|
||||||
@ -223,6 +212,13 @@ remove_program_files() {
|
|||||||
set -u
|
set -u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remove_global_links() {
|
||||||
|
local link_path="/usr/local/bin/iot_ctrl"
|
||||||
|
|
||||||
|
log "Removing global command link: $link_path"
|
||||||
|
run_as_root rm -f "$link_path"
|
||||||
|
}
|
||||||
|
|
||||||
remove_dependency_dirs() {
|
remove_dependency_dirs() {
|
||||||
local dependency_dirs="$1"
|
local dependency_dirs="$1"
|
||||||
local install_dir="$2"
|
local install_dir="$2"
|
||||||
@ -263,6 +259,7 @@ main() {
|
|||||||
stop_and_disable_services
|
stop_and_disable_services
|
||||||
remove_service_files
|
remove_service_files
|
||||||
reload_systemd
|
reload_systemd
|
||||||
|
remove_global_links
|
||||||
remove_program_files
|
remove_program_files
|
||||||
|
|
||||||
log "Uninstall completed"
|
log "Uninstall completed"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user