fix config
This commit is contained in:
parent
1b94a10b57
commit
2fd88401f5
@ -10,17 +10,40 @@ CURRENT_USER="${SUDO_USER:-$(id -un)}"
|
||||
SERVICE_USER="${SERVICE_USER:-$CURRENT_USER}"
|
||||
SERVICE_GROUP="${SERVICE_GROUP:-$(id -gn "$SERVICE_USER")}"
|
||||
|
||||
# Configure multiple programs here before publishing this script.
|
||||
# Configure programs here before publishing this script.
|
||||
# Format:
|
||||
# "service_name|download_url|start_command|stop_command|dependency_dirs|service_user|service_group"
|
||||
# INSTALL_<APP>=(
|
||||
# "service_name"
|
||||
# "download_url"
|
||||
# "start_command"
|
||||
# "stop_command"
|
||||
# "service_user"
|
||||
# "service_group"
|
||||
# )
|
||||
#
|
||||
# Environment variables are rendered into the corresponding systemd service
|
||||
# file by service_env_lines(), using the [prod] sections from iot/env.file and
|
||||
# efka/env.file. Directory creation is driven by those service env values.
|
||||
#
|
||||
# Use {install_dir}, {work_dir} and {service_name} in commands and directories.
|
||||
# dependency_dirs is a comma-separated list. dependency_dirs, service_user and
|
||||
# service_group are optional.
|
||||
# service_user and service_group are optional.
|
||||
|
||||
INSTALL_ITEMS=(
|
||||
"iot|https://punchsky.cn/down/iot-0.1.0.tar.gz|{install_dir}/bin/iot foreground|{install_dir}/bin/iot stop|/var/lib/iot/mnesia,/var/lib/endpoint/database,/var/lib/endpoint/endpoint_log"
|
||||
"efka|https://punchsky.cn/down/efka-0.1.0.tar.gz|{install_dir}/bin/efka foreground|{install_dir}/bin/efka stop|/var/lib/efka/mnesia,/var/lib/efka/dets,/var/lib/efka/docker"
|
||||
INSTALL_IOT=(
|
||||
"iot"
|
||||
"https://punchsky.cn/down/iot-0.1.0.tar.gz"
|
||||
"{install_dir}/bin/iot foreground"
|
||||
"{install_dir}/bin/iot stop"
|
||||
""
|
||||
""
|
||||
)
|
||||
|
||||
INSTALL_EFKA=(
|
||||
"efka"
|
||||
"https://punchsky.cn/down/efka-0.1.0.tar.gz"
|
||||
"{install_dir}/bin/efka foreground"
|
||||
"{install_dir}/bin/efka stop"
|
||||
""
|
||||
""
|
||||
)
|
||||
TEMP_FILES=()
|
||||
INSTALLED_SERVICES=()
|
||||
@ -43,13 +66,18 @@ Options:
|
||||
-h, --help Show this help.
|
||||
|
||||
Array config inside script:
|
||||
INSTALL_ITEMS=(
|
||||
"iot|https://punchsky.cn/down/iot-0.1.0.tar.gz|{install_dir}/bin/iot foreground|{install_dir}/bin/iot stop|{work_dir}/var/lib/iot/mnesia,{work_dir}/var/log/iot,{work_dir}/var/run/iot"
|
||||
"efka|https://punchsky.cn/down/efka-0.1.0.tar.gz|{install_dir}/bin/efka foreground|{install_dir}/bin/efka stop|{work_dir}/var/lib/efka/mnesia,{work_dir}/var/log/efka,{work_dir}/var/run/efka"
|
||||
)
|
||||
INSTALL_IOT
|
||||
INSTALL_EFKA
|
||||
|
||||
Package format:
|
||||
"service_name|download_url|start_command|stop_command|dependency_dirs|service_user|service_group"
|
||||
INSTALL_<APP>=(
|
||||
"service_name"
|
||||
"download_url"
|
||||
"start_command"
|
||||
"stop_command"
|
||||
"service_user"
|
||||
"service_group"
|
||||
)
|
||||
|
||||
Placeholders:
|
||||
{install_dir} will be replaced with the extracted package directory.
|
||||
@ -148,11 +176,8 @@ validate_args() {
|
||||
[[ -n "$WORK_DIR" ]] || fail "--work-dir is required"
|
||||
[[ "$WORK_DIR" = /* ]] || fail "--work-dir must be an absolute path"
|
||||
|
||||
set +u
|
||||
local item_count="${#INSTALL_ITEMS[@]}"
|
||||
set -u
|
||||
|
||||
[[ "$item_count" -gt 0 ]] || fail "No programs configured. Fill INSTALL_ITEMS inside this script"
|
||||
require_install_config INSTALL_IOT
|
||||
require_install_config INSTALL_EFKA
|
||||
}
|
||||
|
||||
prepare_work_dir() {
|
||||
@ -167,6 +192,7 @@ render_service_file() {
|
||||
local install_dir="$4"
|
||||
local start_command="$5"
|
||||
local stop_command="$6"
|
||||
local env_line
|
||||
|
||||
cat <<EOF
|
||||
[Unit]
|
||||
@ -179,10 +205,16 @@ Type=simple
|
||||
User=${service_user}
|
||||
Group=${service_group}
|
||||
WorkingDirectory=${install_dir}
|
||||
|
||||
ExecStart=${start_command}
|
||||
EOF
|
||||
|
||||
while IFS= read -r env_line; do
|
||||
[[ -n "$env_line" ]] || continue
|
||||
validate_environment_line "$env_line"
|
||||
printf 'Environment="%s"\n' "$env_line"
|
||||
done < <(service_env_lines "$service_name")
|
||||
|
||||
printf 'ExecStart=%s\n' "$start_command"
|
||||
|
||||
if [[ -n "$stop_command" ]]; then
|
||||
printf 'ExecStop=%s\n' "$stop_command"
|
||||
fi
|
||||
@ -226,6 +258,24 @@ validate_install_item() {
|
||||
[[ "$service_name" =~ ^[a-zA-Z0-9_.@-]+$ ]] || fail "Invalid service name: $service_name"
|
||||
}
|
||||
|
||||
require_install_config() {
|
||||
local config_name="$1"
|
||||
local config_count
|
||||
local service_name
|
||||
local download_url
|
||||
local start_command
|
||||
|
||||
eval "config_count=\${#${config_name}[@]}"
|
||||
eval "service_name=\"\${${config_name}[0]:-}\""
|
||||
eval "download_url=\"\${${config_name}[1]:-}\""
|
||||
eval "start_command=\"\${${config_name}[2]:-}\""
|
||||
|
||||
[[ "$config_count" -ge 4 ]] || fail "Invalid $config_name config. Expected service name, URL and commands"
|
||||
[[ -n "$service_name" ]] || fail "Invalid $config_name config: service name is empty"
|
||||
[[ -n "$download_url" ]] || fail "Invalid $config_name config: download URL is empty"
|
||||
[[ -n "$start_command" ]] || fail "Invalid $config_name config: start command is empty"
|
||||
}
|
||||
|
||||
replace_placeholders() {
|
||||
local value="$1"
|
||||
local install_dir="$2"
|
||||
@ -238,29 +288,101 @@ replace_placeholders() {
|
||||
printf '%s\n' "$value"
|
||||
}
|
||||
|
||||
create_dependency_dirs() {
|
||||
local dependency_dirs="$1"
|
||||
validate_environment_line() {
|
||||
local env_line="$1"
|
||||
local env_key="${env_line%%=*}"
|
||||
|
||||
[[ "$env_line" == *=* ]] || fail "Invalid environment line: $env_line"
|
||||
[[ "$env_key" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]] || fail "Invalid environment key: $env_key"
|
||||
}
|
||||
|
||||
service_env_lines() {
|
||||
local service_name="$1"
|
||||
|
||||
case "$service_name" in
|
||||
iot)
|
||||
cat <<'EOF'
|
||||
IOT_API_URL=http://127.0.0.1/api/v1
|
||||
ENDPOINT_ROOT_DIR=/var/lib/endpoint/database/
|
||||
ENDPOINT_LOG_PATH=/var/lib/endpoint/endpoint_log
|
||||
IOT_MNESIA_DIR=/var/lib/iot/mnesia/
|
||||
EOF
|
||||
;;
|
||||
efka)
|
||||
cat <<'EOF'
|
||||
EFKA_DETS_DIR=/var/lib/efka/dets/
|
||||
EFKA_IOT_HOST=localhost
|
||||
EFKA_AUTH_UUID=qbxmjyzrkpntfgswaevodhluicqzxplkm
|
||||
EFKA_AUTH_TOKEN=zpxlkvmqwnbghytrujsdieofazxcvbnm
|
||||
EFKA_DOCKER_ROOT_DIR=/var/lib/efka/docker/
|
||||
EFKA_MNESIA_DIR=/var/lib/efka/mnesia
|
||||
EOF
|
||||
;;
|
||||
*)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
service_dir_env_keys() {
|
||||
local service_name="$1"
|
||||
|
||||
case "$service_name" in
|
||||
iot)
|
||||
cat <<'EOF'
|
||||
ENDPOINT_ROOT_DIR
|
||||
ENDPOINT_LOG_PATH
|
||||
IOT_MNESIA_DIR
|
||||
EOF
|
||||
;;
|
||||
efka)
|
||||
cat <<'EOF'
|
||||
EFKA_DETS_DIR
|
||||
EFKA_DOCKER_ROOT_DIR
|
||||
EFKA_MNESIA_DIR
|
||||
EOF
|
||||
;;
|
||||
*)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
env_value_for_key() {
|
||||
local service_name="$1"
|
||||
local env_key="$2"
|
||||
local env_line
|
||||
local value
|
||||
|
||||
while IFS= read -r env_line; do
|
||||
[[ "$env_line" == "${env_key}="* ]] || continue
|
||||
value="${env_line#*=}"
|
||||
printf '%s\n' "$value"
|
||||
return 0
|
||||
done < <(service_env_lines "$service_name")
|
||||
|
||||
fail "Missing env key $env_key for $service_name"
|
||||
}
|
||||
|
||||
create_dependency_dirs_from_env() {
|
||||
local service_name="$1"
|
||||
local install_dir="$2"
|
||||
local service_name="$3"
|
||||
local service_user="$4"
|
||||
local service_group="$5"
|
||||
local service_user="$3"
|
||||
local service_group="$4"
|
||||
local env_key
|
||||
local dependency_dir
|
||||
local dependency_dir_list
|
||||
local -a dependency_dir_array
|
||||
|
||||
[[ -n "$dependency_dirs" ]] || return 0
|
||||
while IFS= read -r env_key; do
|
||||
[[ -n "$env_key" ]] || continue
|
||||
dependency_dir="$(env_value_for_key "$service_name" "$env_key")"
|
||||
dependency_dir="$(replace_placeholders "$dependency_dir" "$install_dir" "$service_name")"
|
||||
|
||||
dependency_dir_list="$(replace_placeholders "$dependency_dirs" "$install_dir" "$service_name")"
|
||||
|
||||
IFS=',' read -ra dependency_dir_array <<< "$dependency_dir_list"
|
||||
for dependency_dir in "${dependency_dir_array[@]}"; do
|
||||
[[ -n "$dependency_dir" ]] || continue
|
||||
[[ "$dependency_dir" = /* ]] || fail "Dependency directory must be an absolute path: $dependency_dir"
|
||||
|
||||
log "Creating dependency directory: $dependency_dir"
|
||||
log "Creating dependency directory from $env_key: $dependency_dir"
|
||||
run_as_root install -d -m 0755 "$dependency_dir"
|
||||
run_as_root chown -R "${service_user}:${service_group}" "$dependency_dir"
|
||||
done
|
||||
done < <(service_dir_env_keys "$service_name")
|
||||
}
|
||||
|
||||
install_program() {
|
||||
@ -268,9 +390,8 @@ install_program() {
|
||||
local download_url="$2"
|
||||
local start_command="$3"
|
||||
local stop_command="$4"
|
||||
local dependency_dirs="$5"
|
||||
local service_user="$6"
|
||||
local service_group="$7"
|
||||
local service_user="$5"
|
||||
local service_group="$6"
|
||||
local clean_url="$download_url"
|
||||
local archive_name
|
||||
|
||||
@ -309,30 +430,40 @@ install_program() {
|
||||
log "Setting owner for install directory: ${service_user}:${service_group}"
|
||||
run_as_root chown -R "${service_user}:${service_group}" "$install_dir"
|
||||
|
||||
create_dependency_dirs "$dependency_dirs" "$install_dir" "$service_name" "$service_user" "$service_group"
|
||||
create_dependency_dirs_from_env "$service_name" "$install_dir" "$service_user" "$service_group"
|
||||
|
||||
write_service_file "$service_file" "$service_name" "$service_user" "$service_group" "$install_dir" "$start_command" "$stop_command"
|
||||
INSTALLED_SERVICES+=("$service_name")
|
||||
}
|
||||
|
||||
install_programs() {
|
||||
local item
|
||||
install_program_from_config() {
|
||||
local config_name="$1"
|
||||
local service_name
|
||||
local download_url
|
||||
local start_command
|
||||
local stop_command
|
||||
local dependency_dirs
|
||||
local service_user
|
||||
local service_group
|
||||
|
||||
set +u
|
||||
for item in "${INSTALL_ITEMS[@]}"; do
|
||||
set -u
|
||||
IFS='|' read -r service_name download_url start_command stop_command dependency_dirs service_user service_group <<< "$item"
|
||||
install_program "$service_name" "$download_url" "$start_command" "$stop_command" "$dependency_dirs" "$service_user" "$service_group"
|
||||
set +u
|
||||
done
|
||||
set -u
|
||||
eval "service_name=\"\${${config_name}[0]:-}\""
|
||||
eval "download_url=\"\${${config_name}[1]:-}\""
|
||||
eval "start_command=\"\${${config_name}[2]:-}\""
|
||||
eval "stop_command=\"\${${config_name}[3]:-}\""
|
||||
eval "service_user=\"\${${config_name}[4]:-}\""
|
||||
eval "service_group=\"\${${config_name}[5]:-}\""
|
||||
|
||||
install_program \
|
||||
"$service_name" \
|
||||
"$download_url" \
|
||||
"$start_command" \
|
||||
"$stop_command" \
|
||||
"$service_user" \
|
||||
"$service_group"
|
||||
}
|
||||
|
||||
install_programs() {
|
||||
install_program_from_config INSTALL_IOT
|
||||
install_program_from_config INSTALL_EFKA
|
||||
}
|
||||
|
||||
reload_systemd() {
|
||||
|
||||
271
uninstall_service.sh
Executable file
271
uninstall_service.sh
Executable file
@ -0,0 +1,271 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
WORK_DIR="${WORK_DIR:-/opt/app}"
|
||||
PURGE_DATA="${PURGE_DATA:-0}"
|
||||
|
||||
# Keep this list in sync with install_service.sh.
|
||||
# Format:
|
||||
# "service_name|download_url|start_command|stop_command|dependency_dirs|service_user|service_group"
|
||||
INSTALL_ITEMS=(
|
||||
"iot|https://punchsky.cn/down/iot-0.1.0.tar.gz|{install_dir}/bin/iot foreground|{install_dir}/bin/iot stop|/var/lib/iot/mnesia,/var/lib/endpoint/database,/var/lib/endpoint/endpoint_log"
|
||||
"efka|https://punchsky.cn/down/efka-0.1.0.tar.gz|{install_dir}/bin/efka foreground|{install_dir}/bin/efka stop|/var/lib/efka/mnesia,/var/lib/efka/dets,/var/lib/efka/docker"
|
||||
)
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
sudo ./uninstall_service.sh [options]
|
||||
|
||||
Options:
|
||||
-w, --work-dir Working directory used during installation. Default: /opt/app.
|
||||
--purge-data Also remove dependency/data directories from INSTALL_ITEMS.
|
||||
-h, --help Show this help.
|
||||
|
||||
Default behavior:
|
||||
- Stop services in reverse INSTALL_ITEMS order.
|
||||
- Disable services from boot.
|
||||
- Remove /etc/systemd/system/<service>.service and service backups.
|
||||
- Run systemctl daemon-reload and reset-failed.
|
||||
- Remove downloaded archives and extracted program directories under WORK_DIR.
|
||||
- Keep dependency/data directories unless --purge-data is passed.
|
||||
EOF
|
||||
}
|
||||
|
||||
log() {
|
||||
printf '[uninstall] %s\n' "$*"
|
||||
}
|
||||
|
||||
fail() {
|
||||
printf '[uninstall][error] %s\n' "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
require_command() {
|
||||
command -v "$1" >/dev/null 2>&1 || fail "Missing required command: $1"
|
||||
}
|
||||
|
||||
require_option_value() {
|
||||
local option="$1"
|
||||
local value="${2:-}"
|
||||
|
||||
[[ -n "$value" ]] || fail "$option requires a value"
|
||||
}
|
||||
|
||||
require_root_runner() {
|
||||
if [[ "${EUID}" -ne 0 ]]; then
|
||||
require_command sudo
|
||||
fi
|
||||
}
|
||||
|
||||
run_as_root() {
|
||||
if [[ "${EUID}" -eq 0 ]]; then
|
||||
"$@"
|
||||
else
|
||||
sudo "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-w|--work-dir)
|
||||
require_option_value "$1" "${2:-}"
|
||||
WORK_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--purge-data)
|
||||
PURGE_DATA=1
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
fail "Unknown argument: $1"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
validate_args() {
|
||||
[[ -n "$WORK_DIR" ]] || fail "--work-dir is required"
|
||||
[[ "$WORK_DIR" = /* ]] || fail "--work-dir must be an absolute path"
|
||||
|
||||
set +u
|
||||
local item_count="${#INSTALL_ITEMS[@]}"
|
||||
set -u
|
||||
|
||||
[[ "$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() {
|
||||
local download_url="$1"
|
||||
local clean_url="$download_url"
|
||||
|
||||
clean_url="${clean_url%%\?*}"
|
||||
clean_url="${clean_url%%#*}"
|
||||
basename "$clean_url"
|
||||
}
|
||||
|
||||
replace_placeholders() {
|
||||
local value="$1"
|
||||
local install_dir="$2"
|
||||
local service_name="$3"
|
||||
|
||||
value="${value//\{install_dir\}/$install_dir}"
|
||||
value="${value//\{work_dir\}/$WORK_DIR}"
|
||||
value="${value//\{service_name\}/$service_name}"
|
||||
|
||||
printf '%s\n' "$value"
|
||||
}
|
||||
|
||||
service_name_from_item() {
|
||||
local item="$1"
|
||||
local service_name
|
||||
|
||||
IFS='|' read -r service_name _ <<< "$item"
|
||||
printf '%s\n' "$service_name"
|
||||
}
|
||||
|
||||
stop_and_disable_services() {
|
||||
local index
|
||||
local service_name
|
||||
|
||||
set +u
|
||||
for ((index=${#INSTALL_ITEMS[@]} - 1; index >= 0; index--)); do
|
||||
set -u
|
||||
service_name="$(service_name_from_item "${INSTALL_ITEMS[$index]}")"
|
||||
[[ -n "$service_name" ]] || continue
|
||||
|
||||
log "Stopping service: ${service_name}.service"
|
||||
run_as_root systemctl stop "${service_name}.service" || log "Service not running or not found: ${service_name}.service"
|
||||
|
||||
log "Disabling service on boot: ${service_name}.service"
|
||||
run_as_root systemctl disable "${service_name}.service" || log "Service not enabled or not found: ${service_name}.service"
|
||||
set +u
|
||||
done
|
||||
set -u
|
||||
}
|
||||
|
||||
remove_service_files() {
|
||||
local item
|
||||
local service_name
|
||||
local service_file
|
||||
|
||||
set +u
|
||||
for item in "${INSTALL_ITEMS[@]}"; do
|
||||
set -u
|
||||
service_name="$(service_name_from_item "$item")"
|
||||
[[ -n "$service_name" ]] || continue
|
||||
|
||||
service_file="/etc/systemd/system/${service_name}.service"
|
||||
log "Removing systemd service file: $service_file"
|
||||
run_as_root rm -f "$service_file"
|
||||
|
||||
log "Removing systemd service backups: ${service_file}.bak.*"
|
||||
run_as_root sh -c 'rm -f "$1".bak.*' sh "$service_file"
|
||||
set +u
|
||||
done
|
||||
set -u
|
||||
}
|
||||
|
||||
remove_program_files() {
|
||||
local item
|
||||
local service_name
|
||||
local download_url
|
||||
local start_command
|
||||
local stop_command
|
||||
local dependency_dirs
|
||||
local service_user
|
||||
local service_group
|
||||
local archive_name
|
||||
local app_dir_name
|
||||
local archive_path
|
||||
local install_dir
|
||||
|
||||
set +u
|
||||
for item in "${INSTALL_ITEMS[@]}"; do
|
||||
set -u
|
||||
IFS='|' read -r service_name download_url start_command stop_command dependency_dirs service_user service_group <<< "$item"
|
||||
[[ -n "$service_name" ]] || continue
|
||||
[[ -n "$download_url" ]] || fail "Invalid package config for $service_name: download URL is empty"
|
||||
|
||||
archive_name="$(archive_name_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}"
|
||||
install_dir="${WORK_DIR}/${app_dir_name}"
|
||||
|
||||
log "Removing downloaded archive: $archive_path"
|
||||
run_as_root rm -f "$archive_path"
|
||||
|
||||
log "Removing installed program directory: $install_dir"
|
||||
run_as_root rm -rf "$install_dir"
|
||||
|
||||
if [[ "$PURGE_DATA" = "1" ]]; then
|
||||
remove_dependency_dirs "$dependency_dirs" "$install_dir" "$service_name"
|
||||
fi
|
||||
set +u
|
||||
done
|
||||
set -u
|
||||
}
|
||||
|
||||
remove_dependency_dirs() {
|
||||
local dependency_dirs="$1"
|
||||
local install_dir="$2"
|
||||
local service_name="$3"
|
||||
local dependency_dir
|
||||
local dependency_dir_list
|
||||
local -a dependency_dir_array
|
||||
|
||||
[[ -n "$dependency_dirs" ]] || return 0
|
||||
|
||||
dependency_dir_list="$(replace_placeholders "$dependency_dirs" "$install_dir" "$service_name")"
|
||||
|
||||
IFS=',' read -ra dependency_dir_array <<< "$dependency_dir_list"
|
||||
for dependency_dir in "${dependency_dir_array[@]}"; do
|
||||
[[ -n "$dependency_dir" ]] || continue
|
||||
[[ "$dependency_dir" = /* ]] || fail "Dependency directory must be an absolute path: $dependency_dir"
|
||||
|
||||
log "Removing dependency/data directory: $dependency_dir"
|
||||
run_as_root rm -rf "$dependency_dir"
|
||||
done
|
||||
}
|
||||
|
||||
reload_systemd() {
|
||||
log "Reloading systemd"
|
||||
run_as_root systemctl daemon-reload
|
||||
|
||||
log "Resetting failed systemd state"
|
||||
run_as_root systemctl reset-failed || true
|
||||
}
|
||||
|
||||
main() {
|
||||
parse_args "$@"
|
||||
validate_args
|
||||
|
||||
require_root_runner
|
||||
require_command systemctl
|
||||
|
||||
stop_and_disable_services
|
||||
remove_service_files
|
||||
reload_systemd
|
||||
remove_program_files
|
||||
|
||||
log "Uninstall completed"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Loading…
x
Reference in New Issue
Block a user