From 999a4869283e9b7f41915d5f6d85e800fcff5aa0 Mon Sep 17 00:00:00 2001 From: imdingtalk Date: Mon, 13 Oct 2025 23:52:37 +0800 Subject: [PATCH] Improve update in installation script, decrease downtime(#1422) --- script/install.sh | 141 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 104 insertions(+), 37 deletions(-) diff --git a/script/install.sh b/script/install.sh index c8f3ea0..3842e77 100644 --- a/script/install.sh +++ b/script/install.sh @@ -388,48 +388,115 @@ UNINSTALL() { echo -e "\r\n${GREEN_COLOR}EasyTier was removed successfully! ${RES}\r\n" } +# Minimizes downtime by preparing new files before stopping the service. +# Correctly handles restarting multiple systemd service instances. UPDATE() { if [ ! -f "$INSTALL_PATH/easytier-core" ]; then - echo -e "\r\n${RED_COLOR}Opus${RES}, unable to find EasyTier\r\n" + echo -e "\r\n${RED_COLOR}Error${RES}: EasyTier not found in $INSTALL_PATH. Cannot perform update.\r\n" exit 1 - else - echo - echo -e "${GREEN_COLOR}Stopping EasyTier process${RES}\r\n" - if [ "$INIT_SYSTEM" = "systemd" ]; then - systemctl stop "easytier@*" - else - rc-service easytier stop - fi - # Backup - rm -rf /tmp/easytier_tmp_update - mkdir -p /tmp/easytier_tmp_update - cp -a $INSTALL_PATH/* /tmp/easytier_tmp_update/ - INSTALL - if [ -f $INSTALL_PATH/easytier-core ]; then - echo -e "${GREEN_COLOR} Verify successfully ${RES}" - else - echo -e "${RED_COLOR} Download failed, unable to update${RES}" - echo "Rollback all ..." - rm -rf $INSTALL_PATH/* - mv /tmp/easytier_tmp_update/* $INSTALL_PATH/ - if [ "$INIT_SYSTEM" = "systemd" ]; then - systemctl start "easytier@*" - else - rc-service easytier start - fi - exit 1 - fi - echo -e "\r\n${GREEN_COLOR} Starting EasyTier process${RES}" - if [ "$INIT_SYSTEM" = "systemd" ]; then - systemctl start "easytier@*" - else - rc-service easytier start - fi - echo -e "\r\n${GREEN_COLOR} EasyTier was updated successfully! ${RES}\r\n" - echo -e "\r\n${GREEN_COLOR} EasyTier was the latest stable version! ${RES}\r\n" fi + + # 1. Get the latest version info (while service is still running) + echo -e "${GREEN_COLOR}Checking for the latest version...${RES}" + RESPONSE=$(curl -s "https://api.github.com/repos/EasyTier/EasyTier/releases/latest") + LATEST_VERSION=$(echo "$RESPONSE" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') + LATEST_VERSION=$(echo -e "$LATEST_VERSION" | tr -d '[:space:]') + + if [ -z "$LATEST_VERSION" ]; then + echo -e "\r\n${RED_COLOR}Error${RES}: Failed to get the latest version. Please check your network connection.\r\n" + exit 1 + fi + + echo -e "Latest version found: ${GREEN_COLOR}$LATEST_VERSION${RES}" + + # 2. Download and extract the new version to a temporary directory (while service is still running) + TEMP_UPDATE_DIR=$(mktemp -d /tmp/easytier_update_XXXXXX) + echo -e "${GREEN_COLOR}Downloading new version to temporary directory: $TEMP_UPDATE_DIR${RES}" + + BASE_URL="https://github.com/EasyTier/EasyTier/releases/latest/download/easytier-linux-${ARCH}-${LATEST_VERSION}.zip" + DOWNLOAD_URL=$($NO_GH_PROXY && echo "$BASE_URL" || echo "${GH_PROXY}${BASE_URL}") + + echo -e "Download URL: ${GREEN_COLOR}${DOWNLOAD_URL}${RES}" + curl -L ${DOWNLOAD_URL} -o "$TEMP_UPDATE_DIR/easytier.zip" $CURL_BAR + if [ $? -ne 0 ]; then + echo -e "${RED_COLOR}Download failed!${RES}" + rm -rf "$TEMP_UPDATE_DIR" + exit 1 + fi + + unzip -o "$TEMP_UPDATE_DIR/easytier.zip" -d "$TEMP_UPDATE_DIR/" + + NEW_CORE_FILE="$TEMP_UPDATE_DIR/easytier-linux-${ARCH}/easytier-core" + if [ ! -f "$NEW_CORE_FILE" ]; then + echo -e "${RED_COLOR}Extraction failed or the downloaded archive is invalid.${RES}" + rm -rf "$TEMP_UPDATE_DIR" + exit 1 + fi + + echo -e "${GREEN_COLOR}New version is ready. Starting update process...${RES}" + + # 3. Enter minimal downtime window + + # Record currently running service instances before stopping them + ACTIVE_SERVICES=() + if [ "$INIT_SYSTEM" = "systemd" ]; then + # Get the list of active instances and store them in an array + mapfile -t ACTIVE_SERVICES < <(systemctl list-units --type=service --state=active | grep "easytier@" | awk '{print $1}') + if [ ${#ACTIVE_SERVICES[@]} -gt 0 ]; then + echo -e "\r\n${YELLOW_COLOR}Found running services: ${ACTIVE_SERVICES[*]}${RES}" + echo -e "${YELLOW_COLOR}Stopping EasyTier services...${RES}" + systemctl stop "${ACTIVE_SERVICES[@]}" + else + echo -e "\r\n${YELLOW_COLOR}No running EasyTier services found. Nothing to stop.${RES}" + fi + else # openrc + # openrc script seems to handle a single service, so keep it simple + echo -e "\r\n${YELLOW_COLOR}Stopping EasyTier service...${RES}" + rc-service easytier stop + fi + + # Backup critical files, primarily the configuration + echo "Backing up configuration..." + BACKUP_CONFIG_DIR=$(mktemp -d /tmp/easytier_config_backup_XXXXXX) + if [ -d "$INSTALL_PATH/config" ]; then + cp -a "$INSTALL_PATH/config" "$BACKUP_CONFIG_DIR/" + fi + + echo "Replacing files..." + # Remove old binaries and docs, but not the config directory + rm -f "$INSTALL_PATH/easytier-core" "$INSTALL_PATH/easytier-cli" "$INSTALL_PATH/LICENSE" "$INSTALL_PATH/README.md" + + # Move new files into the installation directory + mv "$TEMP_UPDATE_DIR/easytier-linux-${ARCH}"/* "$INSTALL_PATH/" + chmod +x "$INSTALL_PATH/easytier-core" "$INSTALL_PATH/easytier-cli" + + # Restore configuration to prevent user-defined settings from being overwritten + if [ -d "$BACKUP_CONFIG_DIR/config" ]; then + cp -af "$BACKUP_CONFIG_DIR/config/." "$INSTALL_PATH/config/" + fi + + # 4. Start the services, restoring operation + if [ "$INIT_SYSTEM" = "systemd" ]; then + if [ ${#ACTIVE_SERVICES[@]} -gt 0 ]; then + echo -e "${GREEN_COLOR}Starting new version of EasyTier services: ${ACTIVE_SERVICES[*]}${RES}" + systemctl start "${ACTIVE_SERVICES[@]}" + else + echo -e "${GREEN_COLOR}No services were running before the update. Update complete.${RES}" + fi + else # openrc + echo -e "${GREEN_COLOR}Starting new version of EasyTier service...${RES}" + rc-service easytier start + fi + + # 5. Clean up temporary files + echo "Cleaning up temporary files..." + rm -rf "$TEMP_UPDATE_DIR" + rm -rf "$BACKUP_CONFIG_DIR" + + echo -e "\r\n${GREEN_COLOR}EasyTier was successfully updated to version $LATEST_VERSION!${RES}\r\n" } + # CURL progress if curl --help | grep progress-bar >/dev/null 2>&1; then # $CURL_BAR CURL_BAR="--progress-bar" @@ -461,4 +528,4 @@ else echo -e "\n\r${GREEN_COLOR} install, uninstall, update, help ${RES}" fi -rm -rf /tmp/easytier_tmp_* \ No newline at end of file +rm -rf /tmp/easytier_tmp_*