Shell 案例 --- 一键部署 FileBrowser
1. 问题
- 使用 yum 安装 nginx,别人用的 yum 源里面没有 nginx 或者没有对 nginx 的完整依赖
- 由于网络错误导致 yum 下载失败,以及直接退出脚本的时候,上一个 yum 任务没有正常结束,被中途强制停止
- 因为网络问题导致 curl 抓取失败,而无法完成 FileBrowser 的部署
filebrowser
一直显示 log 不停,脚本无法结束- 当
/etc/nginx/conf.d/filebrowser.conf
的server_name
使用变量的时候,会出现变量虽然正确输出,但是无法应用在这个配置文件上
2. 分析
- 做个检测来让用户的 yum 源和我们的 yum 源保持一致
- yum 下载失败的时候重试,检测 yum 的 pid
- 在下完之后看有没有
filebrowser
的可执行文件 - 考虑后台运行
- 考虑手动输入
server_name
3. 流程图
4. 实现
#!/bin/bash
# 一键部署 FileBrowser 脚本
# version: v1.1.0
# date: 2024-10-21
# author: アニつり a.k.a AnitsuriW
# 指定运行日志的函数
LOG_FILE="/var/log/FileBrowser.log"
# 让日志带时间的函数
log_echo() {
local message="$1"
local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
echo "$timestamp - $message" | tee -a $LOG_FILE
}
# 设置颜色
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color
# 打印带有颜色的标题
print_title() {
local message="$1"
# 打印彩色输出到终端
echo -e "${GREEN}==================================================${NC}"
echo -e "${GREEN}$message${NC}"
echo -e "${GREEN}==================================================${NC}"
# 将消息记录到日志文件中(不带颜色)
log_echo "$message"
}
# 询问用户是手动设置用户名还是使用默认用户名
print_title "设置存储位置"
log_echo "您想手动设置存储位置的用户名还是使用系统默认的存储位置?"
log_echo "手动设置的位置为 /root/(您设置的用户名),自动生成的位置是 /root/admin"
read -p "输入 1 手动设置,输入 2 使用系统默认: " choice
if [ "$choice" == "1" ]; then
# 用户手动输入密码
read -p "请输入存储位置的用户名: " username
echo
log_echo "用户手动设置了存储位置的用户名。"
else
# 自动生成密码
username=admin
log_echo "使用默认用户名:admin"
fi
# 创建用户
log_echo "正在创建用户 ${username} ..."
sudo useradd -s /usr/sbin/nologin ${username}
log_echo "用户 ${username} 创建成功。"
# 将存储位置记录到日志文件中
log_echo "存储位置的用户名为: $username"
log_echo "存储内容的位置在: /home/$username"
# 定义一个函数来运行 yum 并在失败时重试
run_yum() {
local yum_command="$1"
local service_name="$2"
local max_retries=5
local retry_count=0
local yum_pid_file="/var/run/yum.pid"
while [ $retry_count -lt $max_retries ]; do
# 检查是否存在 yum 锁文件
if [ -f "$yum_pid_file" ]; then
local yum_pid=$(cat "$yum_pid_file")
if ps -p $yum_pid > /dev/null 2>&1; then
log_echo "另一个应用程序(PID: $yum_pid)正在持有 yum 锁,正在强制终止该进程..."
sudo kill -9 "$yum_pid" # 强制终止 yum 进程
sudo rm -f "$yum_pid_file" # 移除锁文件
log_echo "已强制终止持有 yum 锁的进程并移除锁文件。"
else
log_echo "检测到 yum 锁文件,但进程 $yum_pid 已不存在,移除锁文件..."
sudo rm -f "$yum_pid_file"
fi
fi
# 尝试运行 yum 命令
if $yum_command; then
log_echo "$service_name 安装成功。"
return 0 # 成功执行,退出函数
else
retry_count=$((retry_count+1))
log_echo "yum 命令 '$yum_command' 失败,重试第 $retry_count 次..."
sleep 5 # 等待 5 秒后重试
fi
done
log_echo "yum 命令 '$yum_command' 多次失败,请检查网络连接或其他问题。"
exit 1
}
# 检查防火墙状态并根据情况停止防火墙
print_title "检查防火墙和SELinux"
log_echo "正在检查防火墙状态..."
firewalld_status=$(systemctl is-active firewalld)
if [ "$firewalld_status" == "active" ]; then
log_echo "防火墙正在运行,正在停止防火墙..."
sudo systemctl stop firewalld
sudo systemctl disable firewalld
log_echo "防火墙已停止并禁用。"
else
log_echo "防火墙是关闭的。"
fi
# 检测并临时关闭 SELinux
log_echo "正在检测 SELinux 状态..."
selinux_status=$(getenforce)
if [ "$selinux_status" == "Enforcing" ]; then
log_echo "SELinux 当前状态为 Enforcing,正在将其设置为 Permissive 模式..."
sudo setenforce 0
log_echo "SELinux 已临时设置为 Permissive 模式。"
elif [ "$selinux_status" == "Permissive" ]; then
log_echo "SELinux 已经处于 Permissive 模式。"
else
log_echo "SELinux 当前状态为 Disabled,无需修改。"
fi
# 检查yum源是否包含 mirrors.aliyun.com
print_title "检查 yum 源"
yum_repolist=$(yum repolist | grep "mirrors.aliyun.com")
if [ -z "$yum_repolist" ]; then
log_echo "未找到阿里云源,让我们配置阿里云 yum 源..."
# 检查是否已安装epel-release
epel_installed=$(rpm -qa | grep epel-release)
sudo mkdir -p /etc/yum.repos.d/backup
sudo mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup/
sudo touch /etc/yum.repos.d/CentOS7-Aliyun.repo
sudo bash -c 'cat > /etc/yum.repos.d/CentOS7-Aliyun.repo << EOF
[base]
name=CentOS-\$releasever - Base - mirrors.aliyun.com
baseurl=http://mirrors.aliyun.com/centos/\$releasever/os/\$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
[updates]
name=CentOS-\$releasever - Updates - mirrors.aliyun.com
baseurl=http://mirrors.aliyun.com/centos/\$releasever/updates/\$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
[extras]
name=CentOS-\$releasever - Extras - mirrors.aliyun.com
baseurl=http://mirrors.aliyun.com/centos/\$releasever/extras/\$basearch/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
EOF'
run_yum "sudo yum clean all" "一键清除所有 yum 源"
run_yum "sudo yum repolist" "阿里 yum 源"
# 如果已安装epel-release,先卸载它
if [ -n "$epel_installed" ]; then
log_echo "检测到已安装epel-release,让我们先移除它..."
run_yum "sudo yum remove -y epel-release" "EPEL 卸载成功,并没有"
fi
# 重新安装epel-release
run_yum "sudo yum install -y epel-release" "epel-release"
run_yum "sudo yum repolist" "所有的 yum 源都"
else
log_echo "阿里云源已存在,跳过阿里yum源的配置。"
# 检查是否已安装epel-release
epel_installed=$(rpm -qa | grep epel-release)
# 如果已安装epel-release,先卸载它
if [ -n "$epel_installed" ]; then
log_echo "检测到已安装epel-release"
else
log_echo "未检测到EPEL源,正在为您安装..."
run_yum "sudo yum install -y epel-release" "EPEL源"
fi
fi
# 安装 nginx
print_title "部署nginx"
log_echo "让我们来安装Nginx..."
run_yum "sudo yum install -y nginx" "nginx"
# 检测主机IP地址
log_echo "正在获取主机的IP地址..."
ipaddress=$(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1 | head -n 1)
log_echo "检测到的IP地址为: $ipaddress"
# 配置 Nginx
log_echo "配置 Nginx..."
cat << EOF > /etc/nginx/conf.d/filebrowser.conf
server {
listen 80;
client_max_body_size 100M;
proxy_read_timeout 300s;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}
EOF
# 检测 Nginx 配置
log_echo "检测 Nginx 配置..."
nginx_test_output=$(nginx -t 2>&1) # 捕获 nginx -t 的输出
if echo "$nginx_test_output" | grep -q 'successful'; then
log_echo "Nginx 配置检测成功。"
log_echo "$nginx_test_output" # 将 Nginx 配置检测的输出写入日志
log_echo "启动并启用 Nginx 服务..."
sudo systemctl start nginx
sudo systemctl enable nginx
else
log_echo "Nginx 配置检测失败!"
log_echo "$nginx_test_output" # 将失败的详细输出也写入日志
exit 1
fi
# 安装 FileBrowser
print_title "部署FileBrowser"
log_echo "安装 FileBrowser..."
curl -fsSL https://moka.anitsuri.top/images/shell/get.sh | bash
# 检测 FileBrowser 是否安装成功
log_echo "正在检测 FileBrowser 是否安装成功..."
filebrowser_installed=$(ls /usr/local/bin/ | grep filebrowser)
if [ -z "$filebrowser_installed" ]; then
log_echo "FileBrowser 下载失败,请重新尝试运行脚本。"
exit 1 # 终止脚本
else
log_echo "FileBrowser 安装成功。"
fi
# 启动 FileBrowser 并使用 nohup 管理
log_echo "正在后台启动 FileBrowser"
log_echo "FileBrowser 输出日志: /var/log/filebrowser.out"
log_echo "FileBrowser 错误日志: /var/log/filebrowser_error.log"
nohup filebrowser -r /home/${username} > /var/log/filebrowser.out 2> /var/log/filebrowser_error.log &
# 输出成功信息
print_title "部署 FileBrowser 成功!"
log_echo "恭喜你,FileBrowser 部署成功!"
log_echo "快来使用 http://${ipaddress}/ 来进行访问吧"
log_echo "默认用户名是 admin"
log_echo "默认密码是 admin"
log_echo "请及时进入 FileBrowser 修改默认密码!"
print_title "备注"
log_echo "PS:如果服务器还部署其他服务的情况下,请去 /etc/nginx/conf.d/filebrowser.conf 的第 3 行添加上 server_name (你的IP或者域名);"
5. 实现解析
- 多个 if else 语句检测 阿里 yum 源和 EPEL yum 源
- 定义一个名叫
run_yum
函数,使用了多个 while if else 语句来检测在运行 yum 并在失败时重试 - 定义了一个
filebrowser_installed
的函数,配合着 if else 语句,如果找不到就让用户重新运行脚本,如果找得到就继续 - 使用
nohup ...... &
语句来保持后台运行并输出运行/错误日志 - 不保留
server_name
并留下一句提示:“如果服务器还部署其他服务的情况下,请去/etc/nginx/conf.d/filebrowser.conf
的第 3 行添加上server_name (你的IP或者域名);
”
6. 结果验证
执行以下命令来进行一键部署
$ curl -fsSL https://moka.anitsuri.top/images/shell/FileBrowser_v1.1.0.sh | bash
# 或者如果想要自定义用户名的话可以
$ curl -O https://moka.anitsuri.top/images/shell/FileBrowser_v1.1.0.sh
$ bash FileBrowser_v1.1.0.sh
Thanks for reading!