本文目录导读:

我来帮你写一个简易的脚本安装器,这里提供几种常见的实现方案:
Bash Shell 脚本安装器(最常用)
#!/bin/bash
# ============================================
# 简易脚本安装器
# 使用方法: ./install.sh
# ============================================
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 安装目录
INSTALL_DIR="/usr/local/bin"
SCRIPT_NAME="my_script.sh"
TEMP_DIR="/tmp/installer_$$"
# 显示帮助信息
usage() {
echo "用法: $0 [选项]"
echo "选项:"
echo " -d DIR 指定安装目录 (默认: $INSTALL_DIR)"
echo " -h 显示此帮助信息"
echo " -u 卸载程序"
}
# 检查是否以root运行
check_root() {
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}错误: 请以root权限运行此安装器${NC}"
exit 1
fi
}
# 检查依赖
check_dependencies() {
local deps=("curl" "wget" "tar")
local missing=()
for dep in "${deps[@]}"; do
if ! command -v $dep &> /dev/null; then
missing+=($dep)
fi
done
if [ ${#missing[@]} -ne 0 ]; then
echo -e "${YELLOW}警告: 缺少依赖包: ${missing[*]}${NC}"
read -p "是否尝试自动安装? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
# 根据系统类型安装
if command -v apt-get &> /dev/null; then
sudo apt-get update
sudo apt-get install -y "${missing[@]}"
elif command -v yum &> /dev/null; then
sudo yum install -y "${missing[@]}"
else
echo -e "${RED}错误: 无法自动安装依赖${NC}"
exit 1
fi
else
echo -e "${RED}错误: 缺少必要依赖${NC}"
exit 1
fi
fi
}
# 下载文件
download_files() {
echo -e "${BLUE}[1/4] 下载文件...${NC}"
# 假设文件从远程服务器下载
local download_url="https://example.com/scripts/$SCRIPT_NAME"
mkdir -p $TEMP_DIR
# 使用curl或wget下载
if command -v curl &> /dev/null; then
curl -ksSL "$download_url" -o "$TEMP_DIR/$SCRIPT_NAME"
elif command -v wget &> /dev/null; then
wget --no-check-certificate -q -O "$TEMP_DIR/$SCRIPT_NAME" "$download_url"
else
echo -e "${RED}错误: 没有可用的下载工具${NC}"
exit 1
fi
if [ $? -ne 0 ]; then
echo -e "${RED}错误: 下载失败${NC}"
cleanup
exit 1
fi
}
# 安装文件
install_files() {
echo -e "${BLUE}[2/4] 复制文件到 $INSTALL_DIR${NC}"
# 创建目标目录(如果不存在)
mkdir -p "$INSTALL_DIR"
# 复制文件
cp "$TEMP_DIR/$SCRIPT_NAME" "$INSTALL_DIR/"
# 设置执行权限
chmod +x "$INSTALL_DIR/$SCRIPT_NAME"
if [ $? -eq 0 ]; then
echo -e "${GREEN}✓ 文件安装成功${NC}"
else
echo -e "${RED}✗ 文件安装失败${NC}"
cleanup
exit 1
fi
}
# 创建配置
create_config() {
echo -e "${BLUE}[3/4] 创建配置文件...${NC}"
# 示例:创建配置文件
if [ ! -f "/etc/my_script.conf" ]; then
cat > "/etc/my_script.conf" << EOF
# 我的脚本配置
INSTALLED=true
VERSION=1.0.0
INSTALL_DATE=$(date)
INSTALL_DIR=$INSTALL_DIR
EOF
echo -e "${GREEN}✓ 配置文件创建成功${NC}"
else
echo -e "${YELLOW}⚠ 配置文件已存在,跳过${NC}"
fi
}
# 清理临时文件
cleanup() {
echo -e "${BLUE}[4/4] 清理临时文件...${NC}"
rm -rf $TEMP_DIR
}
# 卸载函数
uninstall() {
echo -e "${YELLOW}卸载 $SCRIPT_NAME...${NC}"
# 删除安装的文件
if [ -f "$INSTALL_DIR/$SCRIPT_NAME" ]; then
rm -f "$INSTALL_DIR/$SCRIPT_NAME"
echo -e "${GREEN}✓ 已删除主程序${NC}"
fi
# 删除配置文件
if [ -f "/etc/my_script.conf" ]; then
rm -f "/etc/my_script.conf"
echo -e "${GREEN}✓ 已删除配置文件${NC}"
fi
echo -e "${GREEN}卸载完成${NC}"
}
# 主函数
main() {
# 解析命令行参数
while getopts "d:hu" opt; do
case $opt in
d)
INSTALL_DIR=$OPTARG
;;
h)
usage
exit 0
;;
u)
uninstall
exit 0
;;
\?)
usage
exit 1
;;
esac
done
# 显示欢迎信息
echo -e "${GREEN}================================${NC}"
echo -e "${GREEN} 简易脚本安装器 v1.0.0 ${NC}"
echo -e "${GREEN}================================${NC}"
echo
# 检查root权限(可选的,如果不是必需权限则注释掉)
# check_root
# 检查依赖
check_dependencies
# 执行安装步骤
download_files
install_files
create_config
cleanup
# 显示完成信息
echo
echo -e "${GREEN}================================${NC}"
echo -e "${GREEN} 安装成功! ${NC}"
echo -e "${GREEN}================================${NC}"
echo
echo -e "安装位置: ${YELLOW}$INSTALL_DIR/$SCRIPT_NAME${NC}"
echo -e "使用命令: ${YELLOW}$SCRIPT_NAME --help${NC}"
echo -e "配置位置: ${YELLOW}/etc/my_script.conf${NC}"
echo
}
# 执行主函数
main "$@"
交互式安装器(增强版)
#!/bin/bash
# ============================================
# 交互式脚本安装器
# ============================================
# 日志函数
log_info() {
echo -e "\033[1;34m[INFO]\033[0m $1"
}
log_success() {
echo -e "\033[1;32m[SUCCESS]\033[0m $1"
}
log_warn() {
echo -e "\033[1;33m[WARN]\033[0m $1"
}
log_error() {
echo -e "\033[1;31m[ERROR]\033[0m $1"
}
# 进度条函数
show_progress() {
local current=$1
local total=$2
local bar_len=40
local fill_len=$((current * bar_len / total))
printf "["
for ((i=0; i<fill_len; i++)); do
printf "█"
done
for ((i=fill_len; i<bar_len; i++)); do
printf " "
done
printf "] %d%%" $((current * 100 / total))
echo
}
# 确认函数
confirm() {
read -p "$1 (y/n): " -n 1 -r
echo
[[ $REPLY =~ ^[Yy]$ ]]
}
# 安装选项
install_options() {
echo "====================="
echo "请选择要安装的组件:"
echo "====================="
read -p "是否安装核心组件? (y/n): " -n 1 -r core
echo
read -p "是否安装开发文档? (y/n): " -n 1 -r docs
echo
read -p "是否配置环境变量? (y/n): " -n 1 -r env
INSTALL_CORE=${core:-n}
INSTALL_DOCS=${docs:-n}
SETUP_ENV=${env:-n}
}
# 主安装流程
main_install() {
local steps=4
local current=0
# 收集安装选项
install_options
# 步骤1: 检查系统
current=$((current+1))
log_info "步骤 $current/$steps: 检查系统... "
sleep 1
show_progress $current $steps
# 步骤2: 复制文件
current=$((current+1))
log_info "步骤 $current/$steps: 复制文件... "
sleep 1
show_progress $current $steps
# 步骤3: 配置环境
current=$((current+1))
log_info "步骤 $current/$steps: 配置环境... "
sleep 1
show_progress $current $steps
# 步骤4: 完成
current=$((current+1))
log_info "步骤 $current/$steps: 完成... "
sleep 1
show_progress $current $steps
log_success "安装完成!"
}
# 执行安装
main_install
Python 安装器(跨平台)
#!/usr/bin/env python3
# ============================================
# Python 简易安装器
# ============================================
import os
import sys
import shutil
import subprocess
import logging
from pathlib import Path
import argparse
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class Installer:
def __init__(self):
self.install_dir = Path('/usr/local/bin')
self.config_dir = Path('/etc')
self.temp_dir = Path('/tmp/installer')
self.script_name = 'my_script'
def check_os(self):
"""检查操作系统"""
if sys.platform == 'darwin':
logger.info(f'检测到 macOS 系统')
elif sys.platform == 'linux':
logger.info(f'检测到 Linux 系统')
elif sys.platform == 'win32':
logger.info(f'检测到 Windows 系统')
self.install_dir = Path(os.environ.get('APPDATA', '/tmp')) / 'my_script'
else:
logger.warning(f'未知操作系统: {sys.platform}')
def check_dependencies(self):
"""检查依赖"""
requirements = []
# 检查Python模块
try:
import requests
except ImportError:
requirements.append('requests')
try:
import yaml
except ImportError:
requirements.append('pyyaml')
if requirements:
logger.info(f'需要安装的依赖: {", ".join(requirements)}')
if self.confirm('是否需要安装依赖?'):
self.install_dependencies(requirements)
def install_dependencies(self, packages):
"""安装依赖"""
try:
subprocess.check_call(
[sys.executable, '-m', 'pip', 'install', *packages]
)
logger.info('依赖安装成功')
except subprocess.CalledProcessError:
logger.error('依赖安装失败')
sys.exit(1)
def create_temp_dir(self):
"""创建临时目录"""
self.temp_dir.mkdir(parents=True, exist_ok=True)
logger.debug(f'创建临时目录: {self.temp_dir}')
def download_files(self):
"""下载文件(示例)"""
try:
import requests
url = 'https://example.com/scripts/my_script.sh'
response = requests.get(url)
# 保存到临时目录
with open(self.temp_dir / self.script_name, 'wb') as f:
f.write(response.content)
logger.info(f'成功下载脚本到 {self.temp_dir}')
except ImportError:
# 如果没有requests,使用urllib
import urllib.request
url = 'https://example.com/scripts/my_script.sh'
urllib.request.urlretrieve(url, self.temp_dir / self.script_name)
logger.info(f'成功下载脚本到 {self.temp_dir}')
except Exception as e:
logger.error(f'下载失败: {e}')
sys.exit(1)
def install_files(self):
"""安装文件"""
logger.info(f'创建安装目录: {self.install_dir}')
self.install_dir.mkdir(parents=True, exist_ok=True)
# 复制文件
source = self.temp_dir / self.script_name
target = self.install_dir / self.script_name
if source.exists():
shutil.copy2(source, target)
# 设置执行权限
target.chmod(0o755)
logger.info(f'文件已复制到: {target}')
else:
logger.error(f'源文件不存在: {source}')
sys.exit(1)
def create_config(self):
"""创建配置文件"""
config_data = f"""
# 配置文件
[installer]
version = "1.0.0"
install_date = "{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
install_dir = "{self.install_dir}"
[database]
host = "localhost"
port = 3306
database = "my_app"
"""
config_path = self.config_dir / 'my_script.conf'
with open(config_path, 'w') as f:
f.write(config_data)
logger.info(f'配置文件已创建: {config_path}')
def setup_environment(self):
"""设置环境变量"""
# 添加到PATH
export_line = f'export PATH="{self.install_dir}:$PATH"'
# 检查并添加到bashrc/zshrc
shell_rc = Path.home() / '.bashrc'
if sys.platform == 'darwin':
shell_rc = Path.home() / '.zshrc'
if export_line not in shell_rc.read_text():
with open(shell_rc, 'a') as f:
f.write(f'\n# Added by my_script installer\nexport PATH="{self.install_dir}:$PATH"\n')
logger.info(f'已将 {self.install_dir} 添加到 PATH')
def cleanup(self):
"""清理临时文件"""
if self.temp_dir.exists():
shutil.rmtree(self.temp_dir)
logger.debug(f'已清理临时目录: {self.temp_dir}')
def confirm(self, message):
"""确认询问"""
response = input(f'{message} [y/n]: ').lower()
return response in ['y', 'yes']
def uninstall(self):
"""卸载程序"""
logger.info('开始卸载...')
# 删除主程序
target = self.install_dir / self.script_name
if target.exists():
target.unlink()
logger.info(f'已删除: {target}')
# 删除配置
config_path = self.config_dir / 'my_script.conf'
if config_path.exists():
config_path.unlink()
logger.info(f'已删除: {config_path}')
logger.info('卸载完成')
def run(self, uninstall_mode=False):
"""主运行函数"""
if uninstall_mode:
self.uninstall()
return
logger.info("========== 开始安装 ==========")
# 执行安装步骤
self.check_os()
self.check_dependencies()
self.create_temp_dir()
self.download_files()
self.install_files()
self.create_config()
self.setup_environment()
self.cleanup()
logger.info("========== 安装成功 ==========")
logger.info(f'可使用命令: {self.script_name}')
logger.info(f'配置文件: {self.config_dir / "my_script.conf"}')
# 命令行入口
def main():
parser = argparse.ArgumentParser(description='简易脚本安装器')
parser.add_argument('-u', '--uninstall', action='store_true', help='卸载程序')
args = parser.parse_args()
installer = Installer()
installer.run(uninstall_mode=args.uninstall)
if __name__ == '__main__':
main()
自定义安装目录版本
#!/bin/bash
# ============================================
# 自定义安装目录的安装器
# ============================================
VERSION="1.0.0"
DEFAULT_INSTALL_DIR="/usr/local/bin"
# 显示安装信息
show_banner() {
cat << "EOF"
========================================
简易脚本安装器 v1.0.0
适用于 Linux/macOS
========================================
EOF
}
# 选择安装目录
choose_install_dir() {
echo "请选择安装目录:"
echo "1) 保存为默认: $DEFAULT_INSTALL_DIR"
echo "2) 自定义目录"
echo "3) 手动输入"
read -p "请选择 [1-3]: " choice
case $choice in
1)
INSTALL_DIR=$DEFAULT_INSTALL_DIR
;;
2)
INSTALL_DIR="$HOME/.local/bin"
mkdir -p "$INSTALL_DIR"
;;
3)
read -p "请输入安装目录: " INSTALL_DIR
;;
*)
echo "无效选择,使用默认目录"
INSTALL_DIR=$DEFAULT_INSTALL_DIR
;;
esac
echo "安装目录: $INSTALL_DIR"
}
# 备份现有文件
backup_existing() {
local file="$INSTALL_DIR/$SCRIPT_NAME"
if [ -f "$file" ]; then
echo "发现已有文件,进行备份..."
cp "$file" "$file.bak"
echo "备份完成: $file.bak"
fi
}
# 安装与验证
perform_install() {
# 创建临时文件用于测试
SCRIPT_NAME="my_app"
echo "正在创建测试脚本..."
cat > "/tmp/$SCRIPT_NAME" << 'EOF'
#!/bin/bash
echo "Hello from my script!"
EOF
# 安装
install -m 755 "/tmp/$SCRIPT_NAME" "$INSTALL_DIR/$SCRIPT_NAME"
# 验证
if [ -x "$INSTALL_DIR/$SCRIPT_NAME" ]; then
echo "✓ 安装成功: $INSTALL_DIR/$SCRIPT_NAME"
else
echo "✗ 安装失败"
fi
# 清理
rm -f "/tmp/$SCRIPT_NAME"
}
# 添加到PATH
add_to_path() {
case ":$PATH:" in
*":$INSTALL_DIR:"*)
echo "该目录已在PATH中"
;;
*)
echo "export PATH=\"$INSTALL_DIR:\$PATH\"" >> ~/.bashrc
echo "已添加到 PATH,请重启终端或运行 source ~/.bashrc"
;;
esac
}
# 主流程
main() {
show_banner
choose_install_dir
backup_existing
perform_install
add_to_path
echo
echo "安装完成!"
echo "使用: my_app"
}
main "$@"
使用建议
-
选择适当的安装位置:
- 系统级 →
/usr/local/bin(需要root权限) - 用户级 →
~/.local/bin或~/.bin(无需root权限)
- 系统级 →
-
安全考虑:
- 验证下载文件的完整性(校验和)
- 使用可靠的下载源
- 安装前进行基本的安装检查
-
错误处理:
- 捕获所有可能的错误
- 提供清晰的错误信息
- 支持回滚机制
-
兼容性:
- 检测系统类型
- 处理不同的包管理器
- 考虑各种特殊情况
-
日志记录:
- 记录安装过程
- 方便问题排查
- 支持调试模式
你可以根据实际需要选择适合的版本,并根据具体的安装场景进行适当修改。