Files
script/frpc.sh

656 lines
17 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# FRP Client 自动安装/卸载脚本
# 支持自动检测架构amd64/arm64并下载对应安装包
#
# 使用方法:
# chmod +x frpc.sh && ./frpc.sh # 交互式主菜单
# ./frpc.sh manage # 进入服务管理界面
#
# 快速安装:
# curl -sS -O https://gitea.tohub.top/Share/script/raw/branch/main/frpc.sh && chmod +x frpc.sh && ./frpc.sh
#
# 功能说明:
# 1. 自动检测系统架构amd64/arm64
# 2. 自动下载对应架构的安装包
# 3. 验证安装包完整性
# 4. 安装并配置 frpc 服务
# 5. 提供完整的服务管理功能
# 彩色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# 配置变量
INSTALL_DIR="/root/data/docker_data/frpc"
BASE_URL="https://gitea.tohub.top/Share/script/raw/branch/main/frpc"
FRPC_VERSION="0.65.0"
set -e
# 日志函数
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 兼容旧函数名
log_info() {
print_info "$1"
}
log_warn() {
print_warning "$1"
}
log_error() {
print_error "$1"
}
# 检查是否为root用户
check_root() {
if [[ $EUID -ne 0 ]]; then
print_error "此脚本需要root权限运行"
print_info "请使用: sudo $0"
exit 1
fi
}
# 检测系统架构
detect_arch() {
local arch=$(uname -m)
case "$arch" in
x86_64)
echo "amd64"
;;
aarch64)
echo "arm64"
;;
*)
print_error "不支持的系统架构: $arch"
print_info "仅支持 x86_64(amd64) 和 aarch64(arm64)"
exit 1
;;
esac
}
# 创建安装目录
create_install_dir() {
if [[ ! -d "$INSTALL_DIR" ]]; then
print_info "创建安装目录: $INSTALL_DIR"
mkdir -p "$INSTALL_DIR"
if [[ $? -ne 0 ]]; then
print_error "创建目录失败"
exit 1
fi
fi
}
# 下载文件
download_file() {
local url=$1
local output=$2
print_info "正在下载: $url"
# 如果存在旧的不完整文件,先删除
if [[ -f "$output" ]]; then
rm -f "$output"
fi
if command -v wget &> /dev/null; then
wget -q --show-progress "$url" -O "$output"
elif command -v curl &> /dev/null; then
curl -# -L "$url" -o "$output"
else
print_error "未找到 wget 或 curl请先安装"
exit 1
fi
# 检查下载是否成功
if [[ $? -eq 0 ]] && [[ -f "$output" ]] && [[ -s "$output" ]]; then
print_success "下载完成: $output"
return 0
else
print_error "下载失败: $url"
rm -f "$output"
return 1
fi
}
# 验证tar.gz文件是否有效
verify_tar_file() {
local file=$1
if [[ ! -f "$file" ]]; then
return 1
fi
if [[ ! -s "$file" ]]; then
print_warning "文件为空: $file"
return 1
fi
# 尝试列出tar文件内容来验证完整性
if ! tar -tzf "$file" >/dev/null 2>&1; then
print_warning "文件不是有效的 tar.gz 包: $file"
return 1
fi
return 0
}
# 下载安装包
download_packages() {
local arch=$(detect_arch)
print_info "检测到系统架构: $arch"
create_install_dir
local frp_file="frp_${FRPC_VERSION}_linux_${arch}.tar.gz"
local download_failed=0
# 下载 FRP
if [[ ! -f "$INSTALL_DIR/$frp_file" ]]; then
if ! download_file "$BASE_URL/$frp_file" "$INSTALL_DIR/$frp_file"; then
download_failed=1
fi
else
print_warning "文件已存在,跳过下载: $frp_file"
fi
# 下载配置文件(如果不存在)
if [[ ! -f "$INSTALL_DIR/frpc.toml" ]]; then
print_info "下载配置文件模板..."
if ! download_file "$BASE_URL/frpc.toml" "$INSTALL_DIR/frpc.toml"; then
print_warning "配置文件下载失败,需要手动创建"
fi
fi
return $download_failed
}
# 创建frp用户
create_frp_user() {
if ! id "frp" &>/dev/null; then
log_info "创建 frp 用户..."
useradd -r -s /bin/false frp
else
log_info "frp 用户已存在"
fi
}
# 解压安装包
extract_archive() {
local arch=$(detect_arch)
local frp_file="$INSTALL_DIR/frp_${FRPC_VERSION}_linux_${arch}.tar.gz"
# 检查文件是否存在
if [[ ! -f "$frp_file" ]]; then
print_warning "安装包不存在,开始下载..."
if ! download_packages; then
print_error "下载失败,无法继续安装"
return 1
fi
fi
# 验证文件完整性
print_info "验证安装包完整性..."
if ! verify_tar_file "$frp_file"; then
print_error "安装包验证失败,请重新下载"
rm -f "$frp_file"
return 1
fi
print_success "安装包验证通过"
print_info "解压 frp_${FRPC_VERSION}_linux_${arch}.tar.gz..."
# 创建临时目录
TEMP_DIR=$(mktemp -d)
# 解压到临时目录
tar -xzf "$frp_file" -C "$TEMP_DIR"
# 复制文件到安装目录
cp "$TEMP_DIR"/frp_${FRPC_VERSION}_linux_${arch}/frpc "$INSTALL_DIR/"
# 清理临时目录
rm -rf "$TEMP_DIR"
# 设置权限 - 确保 frp 用户可以访问和执行
# 设置目录权限,允许 frp 用户访问
chmod 755 /root
chmod 755 /root/data
chmod 755 /root/data/docker_data
chmod 755 "$INSTALL_DIR"
# 设置文件所有者和权限
chown root:frp "$INSTALL_DIR/frpc"
chmod 755 "$INSTALL_DIR/frpc"
# 删除压缩包
print_info "清理下载的压缩包..."
rm -f "$frp_file"
print_success "已删除压缩包"
print_success "frpc 已安装到 $INSTALL_DIR/"
}
# 配置frpc
configure_frpc() {
print_info "配置 frpc..."
# 检查配置文件是否已存在
if [[ -f "$INSTALL_DIR/frpc.toml" ]]; then
print_success "配置文件已存在: $INSTALL_DIR/frpc.toml"
elif [[ -f "frpc.toml" ]]; then
# 如果当前目录有配置文件,复制它
cp frpc.toml "$INSTALL_DIR/"
print_success "配置文件已复制到 $INSTALL_DIR/frpc.toml"
else
print_error "找不到配置文件 frpc.toml"
print_info "请手动创建配置文件: $INSTALL_DIR/frpc.toml"
return 1
fi
chown root:frp "$INSTALL_DIR/frpc.toml"
chmod 640 "$INSTALL_DIR/frpc.toml"
}
# 创建systemd服务
create_service() {
print_info "创建 systemd 服务..."
cat > /etc/systemd/system/frpc.service << EOF
[Unit]
Description=Frp Client Service
After=network.target
[Service]
Type=simple
User=frp
Restart=on-failure
RestartSec=5s
ExecStart=${INSTALL_DIR}/frpc -c ${INSTALL_DIR}/frpc.toml
ExecReload=/bin/kill -s HUP \$MAINPID
KillMode=mixed
TimeoutStopSec=5s
[Install]
WantedBy=multi-user.target
EOF
# 重新加载systemd
systemctl daemon-reload
print_success "systemd 服务已创建"
}
# 启动服务
start_service() {
print_info "启动 frpc 服务..."
# 启用开机自启
systemctl enable frpc
# 启动服务
systemctl start frpc
# 检查服务状态
if systemctl is-active --quiet frpc; then
print_success "frpc 服务启动成功"
else
print_error "frpc 服务启动失败"
print_error "请检查日志: journalctl -u frpc -f"
return 1
fi
}
# 显示状态信息
show_status() {
echo ""
print_success "============================================"
print_success "FRP Client 安装完成!"
print_success "============================================"
echo ""
echo "服务状态:"
systemctl status frpc --no-pager
echo ""
print_info "常用命令:"
echo " 启动服务: systemctl start frpc"
echo " 停止服务: systemctl stop frpc"
echo " 重启服务: systemctl restart frpc"
echo " 查看状态: systemctl status frpc"
echo " 查看日志: journalctl -u frpc -f"
echo ""
print_info "配置文件位置: $INSTALL_DIR/frpc.toml"
print_info "程序位置: $INSTALL_DIR/frpc"
print_success "============================================"
echo ""
}
# 安装frpc主函数
install_frpc() {
print_info "开始安装 FRP Client..."
create_frp_user
extract_archive || return 1
configure_frpc || return 1
create_service
start_service || return 1
show_status
print_success "FRP Client 安装完成!"
}
# 卸载frpc
uninstall_frpc() {
print_warning "即将卸载 FRP Client"
read -p "是否继续?[y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_info "已取消卸载"
return
fi
# 停止服务
print_info "停止 frpc 服务..."
systemctl stop frpc 2>/dev/null || true
# 禁用开机自启
print_info "禁用开机自启..."
systemctl disable frpc 2>/dev/null || true
# 删除服务文件
print_info "删除服务文件..."
rm -f /etc/systemd/system/frpc.service
systemctl daemon-reload
# 删除程序文件
print_info "删除程序文件..."
rm -rf "$INSTALL_DIR"
# 删除frp用户
print_info "删除 frp 用户..."
userdel frp 2>/dev/null || true
echo ""
print_success "FRP Client 已完全卸载"
}
# 检查安装状态
check_status() {
local arch=$(detect_arch)
local frp_file="$INSTALL_DIR/frp_${FRPC_VERSION}_linux_${arch}.tar.gz"
echo ""
print_info "============================================"
print_info "检查 FRP Client 状态"
print_info "============================================"
# 检查程序是否安装
if [[ -f "$INSTALL_DIR/frpc" ]]; then
print_success "FRP Client 已安装"
print_info " 程序位置: $INSTALL_DIR/frpc"
# 获取程序版本
if [[ -x "$INSTALL_DIR/frpc" ]]; then
local version=$("$INSTALL_DIR/frpc" --version 2>/dev/null | head -n 1 || echo "未知")
print_info " 版本信息: $version"
fi
# 检查服务状态
if systemctl is-active --quiet frpc; then
print_success "frpc 服务运行中"
else
print_warning "frpc 服务未运行"
fi
if systemctl is-enabled --quiet frpc; then
print_success "开机自启已启用"
else
print_warning "开机自启未启用"
fi
# 检查配置文件
if [[ -f "$INSTALL_DIR/frpc.toml" ]]; then
print_success "配置文件存在"
else
print_warning "配置文件不存在"
fi
else
print_warning "FRP Client 未安装"
fi
# 检查frp用户
if id "frp" &>/dev/null; then
print_success "frp 用户存在"
else
print_warning "frp 用户不存在"
fi
# 检查安装包状态
echo ""
print_info "安装包状态:"
if [[ -f "$frp_file" ]]; then
local size=$(du -h "$frp_file" 2>/dev/null | cut -f1)
print_info " FRP 压缩包: ${CYAN}已下载${NC} (${size})"
else
print_warning " FRP 压缩包: 未下载"
fi
if [[ -f "$INSTALL_DIR/frpc.toml" ]]; then
print_info " 配置文件: ${CYAN}存在${NC}"
else
print_warning " 配置文件: 不存在"
fi
print_info "============================================"
echo ""
}
# 交互式服务管理菜单
interactive_menu() {
while true; do
echo ""
echo "==============================================="
echo " FRP Client 服务管理"
echo "==============================================="
echo "1. 启动服务 (start)"
echo "2. 停止服务 (stop)"
echo "3. 重启服务 (restart)"
echo "4. 查看状态 (status)"
echo "5. 查看日志 (logs)"
echo "6. 查看配置文件 (config)"
echo "7. 编辑配置文件 (edit)"
echo "8. 卸载服务 (uninstall)"
echo "0. 退出 (exit)"
echo "==============================================="
read -p "请选择操作 [0-8]: " choice
case $choice in
1|start)
log_info "启动 frpc 服务..."
systemctl start frpc
if systemctl is-active --quiet frpc; then
log_info "服务启动成功"
else
log_error "服务启动失败"
fi
systemctl status frpc --no-pager
;;
2|stop)
log_info "停止 frpc 服务..."
systemctl stop frpc
log_info "服务已停止"
;;
3|restart)
log_info "重启 frpc 服务..."
systemctl restart frpc
if systemctl is-active --quiet frpc; then
log_info "服务重启成功"
else
log_error "服务重启失败"
fi
systemctl status frpc --no-pager
;;
4|status)
echo "服务状态:"
systemctl status frpc --no-pager
;;
5|logs)
log_info "查看服务日志 (按 Ctrl+C 退出):"
sleep 1
journalctl -u frpc -f
;;
6|config)
echo "配置文件内容:"
echo "----------------------------------------"
cat "$INSTALL_DIR/frpc.toml"
echo "----------------------------------------"
;;
7|edit)
print_info "编辑配置文件..."
if command -v nano >/dev/null 2>&1; then
nano "$INSTALL_DIR/frpc.toml"
elif command -v vi >/dev/null 2>&1; then
vi "$INSTALL_DIR/frpc.toml"
else
print_error "未找到文本编辑器,请手动编辑: $INSTALL_DIR/frpc.toml"
fi
read -p "是否重启服务使配置生效? [y/N]: " restart_choice
if [[ $restart_choice =~ ^[Yy]$ ]]; then
systemctl restart frpc
print_info "服务已重启"
fi
;;
8|uninstall)
uninstall_frpc
if [[ $? -eq 0 ]]; then
exit 0
fi
;;
0|exit|quit|q)
log_info "退出管理界面"
exit 0
;;
*)
log_error "无效选择,请输入 0-8 或对应命令"
;;
esac
read -p "按回车键继续..."
done
}
# 主菜单
show_main_menu() {
clear
echo -e "${CYAN}"
echo "============================================"
echo " FRP Client 自动安装/卸载脚本"
echo "============================================"
echo -e "${NC}"
echo -e "${GREEN}1.${NC} 安装 FRP Client"
echo -e "${GREEN}2.${NC} 卸载 FRP Client"
echo -e "${GREEN}3.${NC} 检查状态"
echo -e "${GREEN}4.${NC} 下载安装包"
echo -e "${GREEN}5.${NC} 服务管理"
echo -e "${GREEN}0.${NC} 退出"
echo ""
echo -e "${CYAN}============================================${NC}"
}
# 主函数
main() {
check_root
# 检查是否为管理模式
if [[ "$1" == "manage" || "$1" == "menu" || "$1" == "-m" ]]; then
interactive_menu
return
fi
# 如果没有参数,显示交互式主菜单
if [[ $# -eq 0 ]]; then
while true; do
show_main_menu
read -p "请选择操作 [0-5]: " choice
case $choice in
1)
install_frpc
read -p "按任意键继续..." -n 1
;;
2)
uninstall_frpc
read -p "按任意键继续..." -n 1
;;
3)
check_status
read -p "按任意键继续..." -n 1
;;
4)
print_info "开始下载安装包..."
if download_packages; then
print_success "下载完成!"
else
print_error "下载失败"
fi
read -p "按任意键继续..." -n 1
;;
5)
interactive_menu
;;
0)
print_info "退出脚本"
exit 0
;;
*)
print_error "无效的选择,请重新输入"
sleep 2
;;
esac
done
else
# 兼容旧的直接安装模式(如果有参数的话)
print_info "开始安装 FRP Client..."
install_frpc
echo ""
# 询问是否进入交互管理界面
read -p "是否进入服务管理界面? [y/N]: " enter_menu
if [[ $enter_menu =~ ^[Yy]$ ]]; then
interactive_menu
else
echo ""
print_info "可使用以下命令:"
echo " $0 # 进入主菜单"
echo " $0 manage # 进入服务管理界面"
echo " systemctl [start|stop|restart|status] frpc"
fi
fi
}
# 运行主函数
main "$@"