本文目录导读:

我来给你介绍几种自动更新脚本的方法,从简单到复杂:
最简单的版本检查(推荐入门)
#!/bin/bash
# 简单的自我更新脚本
# 脚本当前版本
VERSION="1.0.0"
# 远程版本文件地址
REMOTE_VERSION_URL="https://example.com/version.txt"
# 脚本远程地址
SCRIPT_URL="https://example.com/script.sh"
# 脚本保存路径
SCRIPT_PATH="$0"
echo "当前版本: $VERSION"
# 检查远程版本
REMOTE_VERSION=$(curl -s "$REMOTE_VERSION_URL")
if [ "$REMOTE_VERSION" != "$VERSION" ]; then
echo "发现新版本: $REMOTE_VERSION,开始更新..."
# 下载新版本到临时文件
curl -s "$SCRIPT_URL" -o "$SCRIPT_PATH.tmp"
# 检查下载是否成功
if [ $? -eq 0 ] && [ -s "$SCRIPT_PATH.tmp" ]; then
# 替换原脚本
mv "$SCRIPT_PATH.tmp" "$SCRIPT_PATH"
chmod +x "$SCRIPT_PATH"
echo "更新完成!"
# 重新执行新脚本
exec "$SCRIPT_PATH"
else
echo "下载失败,保持原版本"
rm -f "$SCRIPT_PATH.tmp"
fi
else
echo "已经是最新版本"
fi
带备份和回滚机制
#!/bin/bash
# 带备份和回滚的更新脚本
VERSION="2.0.0"
REMOTE_INFO="https://example.com/update_info.json"
SCRIPT_PATH="$0"
BACKUP_PATH="${SCRIPT_PATH}.backup"
echo "检查更新中..."
# 获取远程版本信息
if command -v jq &> /dev/null; then
REMOTE_INFO_DATA=$(curl -s "$REMOTE_INFO")
REMOTE_VERSION=$(echo "$REMOTE_INFO_DATA" | jq -r '.version')
DOWNLOAD_URL=$(echo "$REMOTE_INFO_DATA" | jq -r '.download_url')
CHANGELOG=$(echo "$REMOTE_INFO_DATA" | jq -r '.changelog')
else
# 如果没有 jq,使用 grep/sed 解析
REMOTE_VERSION=$(curl -s "$REMOTE_INFO" | grep -o '"version":"[^"]*"' | cut -d'"' -f4)
DOWNLOAD_URL=$(curl -s "$REMOTE_INFO" | grep -o '"url":"[^"]*"' | cut -d'"' -f4)
CHANGELOG="有新版本可用"
fi
echo "当前版本: $VERSION"
echo "远程版本: $REMOTE_VERSION"
# 版本比较函数
version_compare() {
[ "$1" = "$2" ] && return 0
[ "$1" = "$(echo -e "$1\n$2" | sort -V | head -n1)" ] && return 2 || return 1
}
version_compare "$REMOTE_VERSION" "$VERSION"
RESULT=$?
if [ $RESULT -eq 1 ]; then
echo "发现新版本!更新内容:"
echo "$CHANGELOG"
# 询问用户是否更新
read -p "是否更新?(y/N): " CONFIRM
if [[ "$CONFIRM" != "y" && "$CONFIRM" != "Y" ]]; then
echo "取消更新"
exit 0
fi
# 备份当前脚本
cp "$SCRIPT_PATH" "$BACKUP_PATH"
echo "已备份当前版本到 $BACKUP_PATH"
# 下载新版本
echo "下载新版本..."
curl -sL "$DOWNLOAD_URL" -o "$SCRIPT_PATH.tmp"
# 验证下载的脚本
if [ -s "$SCRIPT_PATH.tmp" ] && file "$SCRIPT_PATH.tmp" | grep -q "script"; then
# 替换脚本
mv "$SCRIPT_PATH.tmp" "$SCRIPT_PATH"
chmod +x "$SCRIPT_PATH"
echo "更新成功!"
# 询问是否立即执行新版本
read -p "是否立即执行新版本?(Y/n): " EXECUTE_NEW
if [[ "$EXECUTE_NEW" != "n" && "$EXECUTE_NEW" != "N" ]]; then
echo "正在启动新版本..."
exec "$SCRIPT_PATH" "$@"
fi
else
echo "下载的脚本无效,回滚到备份版本"
mv "$BACKUP_PATH" "$SCRIPT_PATH"
chmod +x "$SCRIPT_PATH"
fi
else
echo "已经是最新版本"
fi
Python脚本自动更新
#!/usr/bin/env python3
"""
Python脚本自动更新示例
"""
import sys
import os
import json
import urllib.request
import hashlib
import tempfile
import shutil
import subprocess
from pathlib import Path
class AutoUpdater:
def __init__(self, version="1.0.0"):
self.version = version
self.update_url = "https://example.com/update_info.json"
self.script_path = Path(sys.argv[0]).resolve()
def check_update(self):
"""检查是否有更新"""
try:
with urllib.request.urlopen(self.update_url, timeout=10) as response:
data = json.loads(response.read())
remote_version = data['version']
download_url = data['download_url']
remote_md5 = data.get('md5', '')
changelog = data.get('changelog', '')
if self.version != remote_version:
print(f"发现新版本: {remote_version}")
if changelog:
print(f"更新说明: {changelog}")
return True, download_url, remote_md5
else:
return False, None, None
except Exception as e:
print(f"检查更新失败: {e}")
return False, None, None
def download_script(self, url):
"""下载新版本脚本"""
try:
print("下载新版本...")
with urllib.request.urlopen(url, timeout=30) as response:
data = response.read()
# 保存到临时文件
temp_file = tempfile.NamedTemporaryFile(
mode='wb',
delete=False,
suffix='.py'
)
temp_file.write(data)
temp_file.close()
return temp_file.name
except Exception as e:
print(f"下载失败: {e}")
return None
def validate_script(self, file_path, expected_md5=None):
"""验证下载的脚本"""
if not os.path.exists(file_path):
return False
if expected_md5:
with open(file_path, 'rb') as f:
md5 = hashlib.md5(f.read()).hexdigest()
if md5 != expected_md5:
print("MD5校验失败")
return False
# 检查文件是否包含有效的Python代码
try:
with open(file_path, 'r', encoding='utf-8') as f:
compile(f.read(), file_path, 'exec')
return True
except:
return False
def backup_current(self):
"""备份当前脚本"""
backup_path = Path(f"{self.script_path}.backup")
shutil.copy2(self.script_path, backup_path)
print(f"备份到: {backup_path}")
return backup_path
def update(self):
"""执行更新"""
has_update, download_url, md5 = self.check_update()
if not has_update:
print("已经是最新版本")
return True
# 备份
backup_path = self.backup_current()
# 下载新版本
new_file = self.download_script(download_url)
if not new_file:
print("更新失败")
return False
# 验证新文件
if not self.validate_script(new_file, md5):
print("新版本验证失败,回滚中...")
self.rollback(backup_path)
return False
# 替换文件
try:
os.replace(new_file, self.script_path)
os.chmod(self.script_path, 0o755) # 添加执行权限
print("更新成功!")
# 询问是否重启
choice = input("是否重新运行新版本?(y/n): ")
if choice.lower() == 'y':
print("正在启动新版本...")
subprocess.run([sys.executable, str(self.script_path)])
return True
except Exception as e:
print(f"更新失败: {e}")
self.rollback(backup_path)
return False
def rollback(self, backup_path):
"""回滚到备份版本"""
if backup_path.exists():
shutil.copy2(backup_path, self.script_path)
print("已回滚到备份版本")
def run(self):
"""主函数"""
# 检查更新
if "--check-update" in sys.argv:
self.check_update()
return
# 执行更新(默认自动检查更新)
print(f"脚本版本: {self.version}")
choice = input("是否检查更新?(y/n): ")
if choice.lower() == 'y':
self.update()
# 这里是你的主要功能代码
print("执行主要功能...")
# 你的其他代码...
if __name__ == "__main__":
updater = AutoUpdater(version="1.0.0")
updater.run()
使用Git进行更新
#!/bin/bash
# 基于Git的自动更新脚本
VERSION_FILE=".version"
REPO_URL="https://github.com/yourname/yourscript.git"
# 获取当前版本
get_current_version() {
if [ -f "$VERSION_FILE" ]; then
cat "$VERSION_FILE"
else
echo "0.0.0"
fi
}
# 检查Git仓库更新
check_git_update() {
echo "检查Git仓库更新..."
# 初始化Git仓库(如果不存在)
if [ ! -d ".git" ]; then
git init
git remote add origin "$REPO_URL"
git fetch origin 2>/dev/null
git checkout -f origin/main 2>/dev/null
return 1
fi
# 获取远程更新
git remote update 2>/dev/null
# 比较本地和远程
LOCAL=$(git rev-parse @ 2>/dev/null)
REMOTE=$(git rev-parse @{u} 2>/dev/null)
if [ "$LOCAL" != "$REMOTE" ]; then
return 0 # 有更新
else
return 1 # 没有更新
fi
}
# 执行Git更新
git_update() {
echo "发现新版本,开始更新..."
# 保存当前工作目录
CUR_DIR=$(pwd)
# 备份当前版本
cp -r "$CUR_DIR" "$CUR_DIR.backup"
# 拉取更新
git pull origin main 2>/dev/null
if [ $? -eq 0 ]; then
# 设置新版本号
echo "$(date +%Y%m%d.%H%M%S)" > "$VERSION_FILE"
echo "更新成功!"
# 询问是否重启
read -p "是否重新运行?(y/n): " RESTART
if [ "$RESTART" = "y" ]; then
exec ./$(basename "$0")
fi
else
echo "更新失败,回滚中..."
rm -rf "$CUR_DIR"
mv "$CUR_DIR.backup" "$CUR_DIR"
fi
}
# 主程序
echo "当前版本: $(get_current_version)"
if check_git_update; then
git_update
else
echo "已经是最新版本"
fi
# 以下是主要功能代码
echo "执行主要功能..."
使用建议
- 版本管理:始终保留一个稳定版本号
- 备份机制:更新前总是备份当前版本
- 验证机制:下载后验证文件完整性
- 回滚功能:万一更新失败能回退
- 安全检查:确保来源可信,可使用MD5/SHA校验
- 用户确认:重要更新前询问用户
最简单的方案(适合个人使用)
#!/bin/bash # 最简单的一行更新命令 # 放在脚本开头 curl -s https://example.com/updater.sh | bash
根据你的需求选择合适的方案,如果是生产环境建议使用带备份和回滚的方法。