解决Docker容器中MySQL连接因LANG环境变量缺失导致的问题
解决Docker容器中MySQL连接因LANG环境变量缺失导致的问题问题描述在使用Docker容器部署Spring Boot应用时，遇到以下错误：java.lang.IllegalStateException: DBAppender cannot function if the JDBC driver does not support getGeneratedKeys method *and* without a specific SQL dialect环境信息：Docker容器：基于Ubuntu 22.04，运行宝塔面板数据库：MySQL 8.0.26（独立容器）应用：Spring Boot + Logback + MySQL Connector 8.0.16关键发现：同样的JAR包在虚拟机上运行正常，在容器中无法启动快速解决方案根本解决方案（推荐）：apt-get update && apt-get install -y locales && locale-gen en_US.UTF-8 && update-locale LANG=en_US.UTF-8 && export LANG=en_US.UTF-8 && export LC_ALL=en_US.UTF-8 && echo 'export LANG=en_US.UTF-8' >> ~/.bashrc && echo 'export LC_ALL=en_US.UTF-8' >> ~/.bashrc && source ~/.bashrc临时解决方案（连接参数）：在数据库连接URL中添加：allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8spring: datasource: url: jdbc:mysql://127.0.0.1:3306/your_database?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8或者在启动容器时添加环境变量：docker run -d \ --name your-container \ --net=host \ --restart always \ --privileged \ -e LANG=C.UTF-8 \ -e LC_ALL=C.UTF-8 \ your-image:tag详细排查过程初期错误理解最初看到错误信息，以为是Logback配置问题，尝试了多种方案：取消注释SQL方言配置 ❌<sqlDialect class="ch.qos.logback.core.db.dialect.MySQLDialect"/>使用DriverManagerConnectionSource ❌升级/降级Logback版本 ❌使用HikariCP替代Commons DBCP ❌暂时禁用DBAppender ✅（临时方案，不是根本解决）转换思路：环境差异分析经过两天的配置调试无果后，开始从环境角度分析问题。1. Java版本对比# 容器和虚拟机都是相同版本 java version "1.8.0_381" Java(TM) SE Runtime Environment (build 1.8.0_381-b09)2. 环境变量对比容器环境：JAVA_HOME=/home/root/soft/jdk1.8.0_381 PATH=/home/root/soft/jdk1.8.0_381/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin # 缺失 LANG 和 LC_* 变量虚拟机环境：JAVA_HOME=/home/root/soft/jdk1.8.0_381 LANG=en_US.UTF-8 # 关键差异！ PATH=/home/root/soft/jdk1.8.0_381/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin3. MySQL驱动行为测试创建测试程序验证MySQL驱动的getGeneratedKeys支持：import java.sql.*; public class TestMySQLDriver { public static void main(String[] args) { try { Class.forName("com.mysql.cj.jdbc.Driver"); Connection conn = DriverManager.getConnection( "jdbc:mysql://127.0.0.1:3306/your_database?useSSL=false", "username", "password"); DatabaseMetaData meta = conn.getMetaData(); System.out.println("supportsGetGeneratedKeys: " + meta.supportsGetGeneratedKeys()); System.out.println("Driver version: " + meta.getDriverVersion()); System.out.println("Database version: " + meta.getDatabaseProductVersion()); conn.close(); } catch (Exception e) { e.printStackTrace(); } } }测试结果对比：容器中：java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:110) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:835) ... at TestMySQLDriver.main(TestMySQLDriver.java:7)虚拟机中：supportsGetGeneratedKeys: true Driver version: mysql-connector-java-8.0.16 Database version: 8.0.26关键发现： 容器环境尝试设置LANG环境变量时出现警告：export LANG=en_US.UTF-8 export LC_ALL=en_US.UTF-8 -bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)根因分析核心问题： 容器环境缺少LANG和LC_ALL环境变量，导致：Public Key Retrieval错误 - 这是MySQL 8.0的安全特性，在字符编码异常时更容易触发字符编码处理异常 - MySQL连接器在处理字符编码时出现问题SSL/TLS握手失败 - 编码问题影响了安全连接的建立getGeneratedKeys方法识别失败 - 驱动无法正确识别数据库功能支持本质问题： Public Key Retrieval is not allowed 错误在MySQL 8.0中很常见，但通常在环境正常的情况下可以通过连接参数解决。然而在缺少locale的容器环境中，这个错误变得更加顽固。解决方案详解方案1：修复LANG环境变量（根本解决方案，推荐）# 1. 安装locale支持 apt-get update apt-get install -y locales # 2. 生成UTF-8 locale locale-gen en_US.UTF-8 update-locale LANG=en_US.UTF-8 # 3. 设置环境变量 export LANG=en_US.UTF-8 export LC_ALL=en_US.UTF-8 # 4. 永久化配置 echo 'export LANG=en_US.UTF-8' >> ~/.bashrc echo 'export LC_ALL=en_US.UTF-8' >> ~/.bashrc source ~/.bashrc # 5. 验证配置 locale方案2：连接字符串参数解决（临时方案）如果无法修改容器环境，可以通过调整MySQL连接参数来绕过这个问题：// 添加 allowPublicKeyRetrieval=true 参数 String url = "jdbc:mysql://127.0.0.1:3306/your_database?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8";完整连接参数建议：String url = "jdbc:mysql://127.0.0.1:3306/your_database?" + "useSSL=false&" + "allowPublicKeyRetrieval=true&" + "useUnicode=true&" + "characterEncoding=UTF-8&" + "serverTimezone=Asia/Shanghai";Spring Boot配置文件：spring: datasource: url: jdbc:mysql://127.0.0.1:3306/your_database?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai username: username password: password driver-class-name: com.mysql.cj.jdbc.Driver注意： 方案2虽然能解决连接问题，但不能根本解决locale缺失问题，可能在其他功能上仍有隐患。推荐优先使用方案1。方案3：Docker启动时配置docker run -d \ --name baota \ --net=host \ --restart always \ --privileged \ -e LANG=C.UTF-8 \ -e LC_ALL=C.UTF-8 \ -v /path/to/data:/data \ your-image:tag方案4：Dockerfile中预设FROM ubuntu:22.04 # 安装locale并设置环境变量 RUN apt-get update && \ apt-get install -y locales && \ locale-gen en_US.UTF-8 && \ update-locale LANG=en_US.UTF-8 ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 # 其他配置...验证解决效果修复后重新测试MySQL连接：java -cp .:mysql-connector-java-8.0.16.jar TestMySQLDriver期望输出：supportsGetGeneratedKeys: true Driver version: mysql-connector-java-8.0.16 Database version: 8.0.26经验总结环境一致性的重要性 - 看似相同的环境可能存在关键差异字符编码的影响范围 - LANG环境变量不仅影响显示，还会影响网络通信和数据库连接问题定位思路 - 当配置层面无法解决时，要从环境层面分析Docker容器的注意事项 - 容器环境通常是精简的，可能缺少一些基础的系统配置相关问题和预防类似问题可能出现在：其他需要字符编码的Java应用Python应用的数据库连接文件上传/下载功能国际化(i18n)应用预防措施：构建Docker镜像时主动设置LANG环境变量在CI/CD流程中添加环境一致性检查制作标准化的基础镜像，包含必要的locale配置关键要点：根本问题是locale缺失：Public Key Retrieval is not allowed 在MySQL 8.0中很常见，但在locale正常的环境中通常可以通过连接参数解决。在Docker容器的精简环境中，locale缺失使这个问题变得更加复杂。两种解决思路：治本：修复容器的locale环境，这样应用的各个方面都能正常工作治标：通过连接参数绕过验证，但可能在其他功能上仍有隐患环境一致性：Docker容器环境的精简性可能导致一些看似无关的系统配置缺失，而这些配置对应用的正常运行至关重要。在排查此类问题时，环境差异分析往往比配置调优更有效。
一、镜像特点全程自动安装依赖自动安装宝塔面板、环境、插件自动修改默认面板端口、用户名、密码、安全入口自动配置镜像SSH自动同意首次登陆的用户协议自动取消强制登录自动降级为7.7.0版本修复面板XSS高危漏洞兼容新版本面板运行环境去除专业/企业应用安装权限去除宝塔面板强制绑定账号去除各种删除操作时的计算题与延时等待去除创建网站自动创建的垃圾文件（index.html、404.html、.htaccess）关闭未绑定域名提示页面，防止有人访问未绑定域名直接看出来是用的宝塔面板关闭活动推荐与在线客服，去除首页企业版广告去除自动校验文件与上报信息定时任务去除面板日志与网站绑定域名上报二、版本来源优化版：latest --> https://github.com/gettionhub/baota专业版：pro --> https://bt.sy/bbs/thread-2-1-1.html企业版：ltd --> https://bt.sy/bbs/thread-3-1-1.html建议使用 latest 版本镜像，手动分离数据库外置，比如搭配adminer+mariadb+postgres的docker镜像，将宝塔面板容器和数据库容器连接使用，以防止意外发生导致数据库丢失或泄露。三、如何部署面板默认信息登录地址：http://{{面板ip地址}}:8888/baota用户名：baotao密码：baota端口：8888安全入口：/baotaSSH端口：22SSH root用户密码：baota注意：部署后务必先修改如上信息，以防被利用！部署方式1. 通过 docker run 运行docker run -itd \ --name baota \ --network=host \ --privileged=true \ --restart=unless-stopped \ -v ~/www/wwwroot:/www/wwwroot \ -v ~/www/vhost:/www/server/panel/vhost \ gettionhub/baota:latest2. 通过 docker-compose 运行git clone https://github.com/gettionhub/baota.git cd baota docker pull gettionhub/baota:latest COMPOSE_HTTP_TIMEOUT=1200 docker-compose --verbose up -d3. 通过 docker-compose 配置version: '3.3' services: baota: image: gettionhub/baota:latest #优化版 #image: gettionhub/baota:pro #专业版 #image: gettionhub/baota:ltd #企业版 container_name: baota #容器名 network_mode: bridge #网络模式 privileged: true #root权限 restart: unless-stopped ports: - 8880:80 - 8443:443 - 8888:8888 - 888:888 volumes: - ./web:/www/wwwroot #网站数据目录 - ./data:/www/server/data #MySQL数据目录 - ./vhost:/www/server/panel/vhost #vhost文件路径四、常用命令获取宝塔面板默认信息docker exec -it baota /etc/init.d/bt default重启nginxdocker exec -it baota /etc/init.d/nginx restart重启PHPdocker exec -it baota /etc/init.d/php-fpm-80 restart重启mysqldocker exec -it baota /etc/init.d/mysqld restart进入宝塔容器docker exec -it baota /bin/sh五、破解教程（仅供学习交流）请注意，任何破解行为都可能违反软件许可协议，并且存在法律风险，因此下面提供的教程仅供技术学习和交流，不建议在实际环境中使用。1. 解除面板时间限制使用文件管理器进入 /www/server/panel/data/ 目录，找到 plugin.json 文件。编辑 plugin.json 文件。使用编辑器查找 "endtime": -1 并将其替换为 "endtime": 999999999999。保存更改。2. 解除面板版本授权继续在 plugin.json 文件中操作。查找 is_user_status，并找到 "ltd": -1 和 "pro": -1，将 -1 替换为 0。保存更改。3. 授权文件进行保护使用以下命令保护 plugin.json 文件：chattr +i /www/server/panel/data/plugin.json若要解除保护，使用以下命令：chattr -i /www/server/panel/data/plugin.json
一、nginx.conf配置fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 256k; fastcgi_intercept_errors on; gzip on; gzip_min_length 1k; gzip_buffers 4 16k; gzip_http_version 1.1; gzip_comp_level 2; gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml; gzip_vary on; gzip_proxied expired no-cache no-store private auth; gzip_disable "MSIE [1-6]\.";二、编译配置./configure宝塔面板所有编译配置./configure \ --user=www \ --group=www \ --prefix=/www/server/nginx \ --add-module=srclib/ngx_devel_kit \ --add-module=srclib/lua_nginx_module \ --add-module=srclib/ngx_cache_purge \ --add-module=srclib/nginx-sticky-module \ --with-openssl=srclib/openssl \ --with-pcre=srclib/pcre-8.43 \ --with-http_v2_module \ --with-stream \ --with-stream_ssl_module \ --with-stream_ssl_preread_module \ --with-http_stub_status_module \ --with-http_ssl_module \ --with-http_image_filter_module \ --with-http_gzip_static_module \ --with-http_gunzip_module \ --with-ipv6 \ --with-http_sub_module \ --with-http_flv_module \ --with-http_addition_module \ --with-http_realip_module \ --with-http_mp4_module \ --with-ld-opt=-Wl,-E \ --with-cc-opt=-Wno-error \ --with-http_dav_module \ --add-module=srclib/nginx-dav-ext-module普通安装下需要的常用编译配置./configure \ --with-http_v2_module \ --with-stream \ --with-stream_ssl_module \ --with-stream_ssl_preread_module \ --with-http_stub_status_module \ --with-http_ssl_module \ --with-http_gzip_static_module \ --with-http_gunzip_module \ --with-http_sub_module \ --with-http_flv_module \ --with-http_addition_module \ --with-http_realip_module \ --with-http_mp4_module \ --with-ld-opt=-Wl,-E \ --with-cc-opt=-Wno-error \ --with-http_dav_module三、server配置server { listen 80; listen 443 ssl http2; server_name www.starguar.com; index index.php index.html index.htm default.php default.htm default.html; root /home/ecs-user/programs/digipay/front/web-official; location ~ \.php$ { fastcgi_pass unix:/run/php/php7.4-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi.conf; } #SSL-START SSL相关配置，请勿删除或修改下一行带注释的404规则 #error_page 404/404.html; #HTTP_TO_HTTPS_START if ($server_port !~ 443){ rewrite ^(/.*)$ https://$host$1 permanent; } #HTTP_TO_HTTPS_END ssl_certificate cert/www.starguar.com/fullchain.pem; ssl_certificate_key cert/www.starguar.com/privkey.pem; ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; add_header Strict-Transport-Security "max-age=31536000"; error_page 497 https://$host$request_uri; #SSL-END access_log logs/web-official.log; error_log logs/web-official-error.log; }
#!/bin/bash # chkconfig: 2345 55 25 # description: bt Cloud Service ### BEGIN INIT INFO # Provides: bt # Required-Start: $all # Required-Stop: $all # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: starts bt # Description: starts the bt ### END INIT INFO panel_init(){ panel_path=/www/server/panel pidfile=$panel_path/logs/panel.pid cd $panel_path env_path=$panel_path/pyenv/bin/activate if [ -f $env_path ];then source $env_path pythonV=$panel_path/pyenv/bin/python chmod -R 700 $panel_path/pyenv/bin else pythonV=/usr/bin/python fi reg="^#\!$pythonV\$" is_sed=$(cat $panel_path/BT-Panel|head -n 1|grep -E $reg) if [ "${is_sed}" = "" ];then sed -i "s@^#!.*@#!$pythonV@" $panel_path/BT-Panel fi is_sed=$(cat $panel_path/BT-Task|head -n 1|grep -E $reg) if [ "${is_sed}" = "" ];then sed -i "s@^#!.*@#!$pythonV@" $panel_path/BT-Task fi chmod 700 $panel_path/BT-Panel chmod 700 $panel_path/BT-Task log_file=$panel_path/logs/error.log task_log_file=$panel_path/logs/task.log if [ -f $panel_path/data/ssl.pl ];then log_file=/dev/null fi port=$(cat $panel_path/data/port.pl) } panel_init get_panel_pids(){ isStart=$(ps aux|grep -E '(runserver|BT-Panel)'|grep -v grep|awk '{print $2}'|xargs) pids=$isStart arr=$isStart } get_task_pids(){ isStart=$(ps aux|grep -E '(task.py|BT-Task)'|grep -v grep|awk '{print $2}'|xargs) pids=$isStart arr=$isStart } panel_start() { isStart=`ps aux|grep 'runserver:app'|grep -v grep|awk '{print $2}'` if [ "$isStart" != '' ];then kill -9 $isStart fi get_panel_pids if [ "$isStart" == '' ];then rm -f $pidfile panel_port_check echo -e "Starting Bt-Panel...\c" nohup $panel_path/BT-Panel >> $log_file 2>&1 & isStart="" n=0 while "$isStart" == "" ; do echo -e ".\c" sleep 0.5 get_panel_pids let n+=1 if [ $n -gt 8 ];then break; fi done if [ "$isStart" == '' ];then echo -e "\033[31mfailed\033[0m" echo '------------------------------------------------------' tail -n 20 $log_file echo '------------------------------------------------------' echo -e "\033[31mError: BT-Panel service startup failed.\033[0m" fi echo -e " \033[32mdone\033[0m" else echo "Starting Bt-Panel... Bt-Panel (pid $(echo $isStart)) already running" fi get_task_pids if [ "$isStart" == '' ];then echo -e "Starting Bt-Tasks... \c" nohup $panel_path/BT-Task >> $task_log_file 2>&1 & sleep 0.2 get_task_pids if [ "$isStart" == '' ];then echo -e "\033[31mfailed\033[0m" echo '------------------------------------------------------' tail -n 20 $task_log_file echo '------------------------------------------------------' echo -e "\033[31mError: BT-Task service startup failed.\033[0m" return; fi echo -e " \033[32mdone\033[0m" else echo "Starting Bt-Tasks... Bt-Tasks (pid $isStart) already running" fi } panel_port_check() { is_process=$(lsof -n -P -i:$port|grep LISTEN|grep -v grep|awk '{print $1}'|sort|uniq|xargs) for pn in ${is_process[@]} do if [ "$pn" = "nginx" ];then /etc/init.d/nginx restart fi if [ "$pn" = "httpd" ];then /etc/init.d/httpd restart fi if [ "$pn" = "mysqld" ];then /etc/init.d/mysqld restart fi if [ "$pn" = "superviso" ];then pkill -9 superviso sleep 0.2 supervisord -c /etc/supervisor/supervisord.conf fi if [ "$pn" = "pure-ftpd" ];then /etc/init.d/pure-ftpd restart fi if [ "$pn" = "memcached" ];then /etc/init.d/memcached restart fi if [ "$pn" = "sudo" ];then if [ -f /etc/init.d/redis ];then /etc/init.d/redis restart fi fi if [ "$pn" = "php-fpm" ];then php_v=(52 53 54 55 56 70 71 72 73 74); for pv in ${php_v[@]}; do if [ -f /etc/init.d/php-fpm-${pv} ];then if [ -f /www/server/php/%{pv}/sbin/php-fpm ];then if [ -f /tmp/php-cgi-${pv}.sock ];then /etc/init.d/php-fpm-${pv} start fi /etc/init.d/php-fpm-${pv} restart fi fi done fi done is_ports=$(lsof -n -P -i:$port|grep LISTEN|grep -v grep|awk '{print $2}'|xargs) if [ "$is_ports" != '' ];then kill -9 $is_ports sleep 1 fi } panel_stop() { echo -e "Stopping Bt-Tasks...\c"; get_task_pids arr=($pids) for p in ${arr[@]} do kill -9 $p done echo -e " \033[32mdone\033[0m" echo -e "Stopping Bt-Panel...\c"; get_panel_pids for p in ${arr[@]} do kill -9 $p &>/dev/null done if [ -f $pidfile ];then rm -f $pidfile fi echo -e " \033[32mdone\033[0m" } panel_status() { port=$(cat $panel_path/data/port.pl) get_panel_pids if [ "$isStart" != '' ];then echo -e "\033[32mBt-Panel (pid $(echo $isStart)) already running\033[0m" else echo -e "\033[31mBt-Panel not running\033[0m" fi get_task_pids if [ "$isStart" != '' ];then echo -e "\033[32mBt-Task (pid $isStart) already running\033[0m" else echo -e "\033[31mBt-Task not running\033[0m" fi } panel_reload() { isStart=$(ps aux|grep 'runserver:app'|grep -v grep|awk '{print $2}') if [ "$isStart" != '' ];then kill -9 $isStart sleep 0.5 fi get_panel_pids if [ "$isStart" != '' ];then get_panel_pids for p in ${arr[@]} do kill -9 $p done rm -f $pidfile panel_port_check echo -e "Reload Bt-Panel.\c"; nohup $panel_path/BT-Panel >> $log_file 2>&1 & isStart="" n=0 while "$isStart" == "" ; do echo -e ".\c" sleep 0.5 get_panel_pids let n+=1 if [ $n -gt 8 ];then break; fi done if [ "$isStart" == '' ];then echo -e "\033[31mfailed\033[0m" echo '------------------------------------------------------' tail -n 20 $log_file echo '------------------------------------------------------' echo -e "\033[31mError: BT-Panel service startup failed.\033[0m" return; fi echo -e " \033[32mdone\033[0m" else echo -e "\033[31mBt-Panel not running\033[0m" panel_start fi } install_used() { if [ ! -f $panel_path/aliyun.pl ];then return; fi password=$(cat /dev/urandom | head -n 16 | md5sum | head -c 12) username=$($pythonV $panel_path/tools.py panel $password) safe_path=$(cat /dev/urandom | head -n 16 | md5sum | head -c 8) echo "$safe_path" > $panel_path/admin_path.pl echo "$password" > $panel_path/default.pl rm -f $panel_path/aliyun.pl } error_logs() { tail -n 100 $log_file } case "$1" in 'start') install_used panel_start ;; 'stop') panel_stop ;; 'restart') panel_stop sleep 1 panel_start ;; 'reload') panel_reload ;; 'status') panel_status ;; 'logs') error_logs ;; 'panel') $pythonV $panel_path/tools.py cli $2 ;; 'default') LOCAL_IP=$(ip addr | grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -E -v "^127\.|^255\.|^0\." | head -n 1) port=$(cat $panel_path/data/port.pl) password=$(cat $panel_path/default.pl) if [ -f $panel_path/data/domain.conf ];then address=$(cat $panel_path/data/domain.conf) fi if [ -f $panel_path/data/admin_path.pl ];then auth_path=$(cat $panel_path/data/admin_path.pl) fi if [ "$address" = "" ];then address=$(curl -sS --connect-timeout 10 -m 60 https://www.bt.cn/Api/getIpAddress) fi pool=http if [ -f $panel_path/data/ssl.pl ];then pool=https fi echo -e "==================================================================" echo -e "\033[32mBT-Panel default info!\033[0m" echo -e "==================================================================" echo "外网面板地址: $pool://$address:$port$auth_path" echo "内网面板地址: http://${LOCAL_IP}:$port$auth_path" echo -e "\033[33m*以下仅为初始默认账户密码，若无法登录请执行bt命令重置账户/密码登录\033[0m" echo -e `$pythonV $panel_path/tools.py username` echo -e "password: $password" echo -e "\033[33mIf you cannot access the panel,\033[0m" echo -e "\033[33mrelease the following panel port [${port}] in the security group\033[0m" echo -e "\033[33m若无法访问面板，请检查防火墙/安全组是否有放行面板[${port}]端口\033[0m" echo -e "==================================================================" ;; *) $pythonV $panel_path/tools.py cli $1 ;; esac
#!/bin/bash PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin export PATH echo " +---------------------------------------------------------------------- | Bt-WebPanel 3.0 FOR CentOS beta +---------------------------------------------------------------------- | Copyright (c) 2015-2017 BT-SOFT(http://www.bt.cn) All rights reserved. +---------------------------------------------------------------------- | Python2.6/2.7 successful the http://SERVER_IP:8888 is WebPanel +---------------------------------------------------------------------- " download_Url='http://download.bt.cn' setup_patn=/www while [ "$go" != 'y' ] && [ "$go" != 'n' ] do read -p "Now do you want to install Bt-Panel to the $setup_patn directory?(y/n): " go; done if [ "$go" == 'n' ];then exit; fi yum -y install ntp \cp -a -r /usr/share/zoneinfo/Asia/Shanghai /etc/localtime echo 'Synchronizing system time..' ntpdate 0.asia.pool.ntp.org hwclock -w startTime=`date +%s` rm -f /var/run/yum.pid paces="wget python-devel python-imaging zip unzip openssl openssl-devel gcc libxml2 libxml2-dev libxslt* zlib zlib-devel libjpeg-devel libpng-devel libwebp libwebp-devel freetype freetype-devel lsof pcre pcre-devel vixie-cron crontabs" yum -y install $paces if [ ! -f '/usr/bin/mysql_config' ];then yum install mysql-devel -y fi tmp=`python -V 2>&1|awk '{print $2}'` pVersion=${tmp:0:3} if [ ! -f "/usr/lib/python${pVersion}/site-packages/setuptools-33.1.1-py${pVersion}.egg" ];then wget $download_Url/install/src/setuptools-33.1.1.zip -T 10 unzip setuptools-33.1.1.zip rm -f setuptools-33.1.1.zip cd setuptools-33.1.1 python setup.py install cd .. rm -rf setuptools-33.1.1 fi if [ ! -f "/usr/lib64/python${pVersion}/site-packages/Pillow-3.2.0-py${pVersion}-linux-x86_64.egg" ] && [ ! -f "/usr/lib/python${pVersion}/site-packages/Pillow-3.2.0-py${pVersion}-linux-x86_64.egg" ];then wget $download_Url/install/src/Pillow-3.2.0.zip -T 10 unzip Pillow-3.2.0.zip rm -f Pillow-3.2.0.zip cd Pillow-3.2.0 python setup.py install cd .. rm -rf Pillow-3.2.0 fi if [ ! -d "/usr/lib/python${pVersion}/site-packages/psutil-5.1.3-py${pVersion}-linux-x86_64.egg" ] && [ ! -d "/usr/lib64/python${pVersion}/site-packages/psutil-5.1.3-py${pVersion}-linux-x86_64.egg" ];then wget $download_Url/install/src/psutil-5.1.3.tar.gz -T 10 tar xvf psutil-5.1.3.tar.gz rm -f psutil-5.1.3.tar.gz cd psutil-5.1.3 python setup.py install cd .. rm -rf psutil-5.1.3 fi if [ ! -f "/usr/lib64/python${pVersion}/site-packages/MySQL_python-1.2.5-py${pVersion}-linux-x86_64.egg" ] && [ ! -f "/usr/lib/python${pVersion}/site-packages/MySQL_python-1.2.5-py${pVersion}-linux-x86_64.egg" ];then wget $download_Url/install/src/MySQL-python-1.2.5.zip -T 10 unzip MySQL-python-1.2.5.zip rm -f MySQL-python-1.2.5.zip cd MySQL-python-1.2.5 python setup.py install cd .. rm -rf MySQL-python-1.2.5 fi if [ ! -f "/usr/lib/python${pVersion}/site-packages/chardet-2.3.0-py${pVersion}.egg" ];then wget $download_Url/install/src/chardet-2.3.0.tar.gz -T 10 tar xvf chardet-2.3.0.tar.gz rm -f chardet-2.3.0.tar.gz cd chardet-2.3.0 python setup.py install cd .. rm -rf chardet-2.3.0 fi if [ ! -f "/usr/lib/python${pVersion}/site-packages/web.py-0.38-py${pVersion}.egg-info" ];then wget $download_Url/install/src/web.py-0.38.tar.gz -T 10 tar xvf web.py-0.38.tar.gz rm -f web.py-0.38.tar.gz cd web.py-0.38 python setup.py install cd .. rm -rf web.py-0.38 fi mkdir -p $setup_patn/server/panel/logs wget https://dl.eff.org/certbot-auto --no-check-certificate -O $setup_patn/server/panel/certbot-auto chmod +x $setup_patn/server/panel/certbot-auto isCron=`cat /var/spool/cron/root|grep certbot.log` if [ "${isCron}" == "" ];then echo "30 2 * * * $setup_patn/server/panel/certbot-auto renew >> $setup_patn/server/panel/logs/certbot.log" >> /var/spool/cron/root chown 600 /var/spool/cron/root fi if [ -f '/etc/init.d/bt' ];then service bt stop fi mkdir -p /www/server mkdir -p /www/wwwroot mkdir -p /www/wwwlogs mkdir -p /www/backup/database mkdir -p /www/backup/site wget -O panel.zip $download_Url/install/src/panel.zip -T 10 wget -O /etc/init.d/bt $download_Url/install/src/bt.init -T 10 if [ -f "$setup_patn/server/panel/data/default.db" ];then if [ -d "/$setup_patn/server/panel/old_data" ];then rm -rf /$setup_patn/server/panel/old_data fi mv $setup_patn/server/panel/data /$setup_patn/server/panel/old_data fi unzip -o panel.zip -d $setup_patn/server/ > /dev/null if [ -d "$setup_patn/server/panel/old_data" ];then if [ -d "/$setup_patn/server/panel/data" ];then rm -rf /$setup_patn/server/panel/data fi mv /$setup_patn/server/panel/old_data $setup_patn/server/panel/data fi rm -f panel.zip rm -f $setup_patn/server/panel/class/*.pyc rm -f $setup_patn/server/panel/*.pyc python -m compileall $setup_patn/server/panel rm -f $setup_patn/server/panel/class/*.py rm -f $setup_patn/server/panel/*.py chmod +x /etc/init.d/bt chkconfig --add bt chkconfig --level 2345 bt on echo '8888' > $setup_patn/server/panel/data/port.pl chmod -R 600 $setup_patn/server/panel chmod +x $setup_patn/server/panel/certbot-auto chmod -R +x $setup_patn/server/panel/script service bt start password=`cat /dev/urandom | head -n 16 | md5sum | head -c 8` cd $setup_patn/server/panel/ python tools.pyc panel $password cd ~ echo "$password" > $setup_patn/server/panel/default.pl chmod 600 $setup_patn/server/panel/default.pl if [ -f "/etc/init.d/iptables" ];then iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 20 -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 21 -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 8888 -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 30000:40000 -j ACCEPT service iptables save iptables_status=`service iptables status | grep 'not running'` if [ "${iptables_status}" == '' ];then service iptables restart fi fi if [ "${isVersion}" == '' ];then if [ ! -f "/etc/init.d/iptables" ];then yum install firewalld -y systemctl enable firewalld systemctl start firewalld firewall-cmd --permanent --zone=public --add-port=20/tcp firewall-cmd --permanent --zone=public --add-port=21/tcp firewall-cmd --permanent --zone=public --add-port=22/tcp firewall-cmd --permanent --zone=public --add-port=80/tcp firewall-cmd --permanent --zone=public --add-port=8888/tcp firewall-cmd --permanent --zone=public --add-port=30000-40000/tcp firewall-cmd --reload fi fi yum -y install epel-release country=`curl -sS --connect-timeout 10 -m 60 http://ip.vpser.net/country` if [ "${country}" = "CN" ]; then mkdir ~/.pip cat > ~/.pip/pip.conf <<EOF [global] index-url = https://pypi.doubanio.com/simple/ [install] trusted-host=pypi.doubanio.com EOF fi nohup $setup_patn/server/panel/certbot-auto -n > /tmp/certbot-auto.log 2>&1 & address="" n=0 while [ "$address" == '' ] do address=`curl -s http://city.ip138.com/ip2city.asp|grep -Eo '([0-9]+\.){3}[0-9]+'` let n++ sleep 0.1 if [ $n -gt 5 ];then address="SERVER_IP" fi done curl http://www.bt.cn/Api/SetupCount?type=Linux echo "=====================================" echo -e "\033[32mThe install successful!\033[0m" echo -e "=====================================" echo -e "Bt-Panel: http://$address:8888" echo -e "username: admin" echo -e "password: $password" echo -e "=====================================" endTime=`date +%s` ((outTime=($endTime-$startTime)/60)) echo -e "Time consuming:\033[32m $outTime \033[0mMinute!" rm -f install.sh 2022-11-30版本：#!/bin/bash PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin export PATH LANG=en_US.UTF-8 CURL_CHECK=$(which curl) if [ "$?" == "0" ];then curl -sS --connect-timeout 10 -m 10 https://www.bt.cn/api/wpanel/SetupCount > /dev/null 2>&1 else wget -O /dev/null -o /dev/null -T 5 https://www.bt.cn/api/wpanel/SetupCount fi if [ $(whoami) != "root" ];then echo "请使用root权限执行宝塔安装命令！" exit 1; fi is64bit=$(getconf LONG_BIT) if [ "${is64bit}" != '64' ];then Red_Error "抱歉, 当前面板版本不支持32位系统, 请使用64位系统或安装宝塔5.9!"; fi Centos6Check=$(cat /etc/redhat-release | grep ' 6.' | grep -iE 'centos|Red Hat') if [ "${Centos6Check}" ];then echo "Centos6不支持安装宝塔面板，请更换Centos7/8安装宝塔面板" exit 1 fi UbuntuCheck=$(cat /etc/issue|grep Ubuntu|awk '{print $2}'|cut -f 1 -d '.') if [ "${UbuntuCheck}" ] && [ "${UbuntuCheck}" -lt "16" ];then echo "Ubuntu ${UbuntuCheck}不支持安装宝塔面板，建议更换Ubuntu18/20安装宝塔面板" exit 1 fi cd ~ setup_path="/www" python_bin=$setup_path/server/panel/pyenv/bin/python cpu_cpunt=$(cat /proc/cpuinfo|grep processor|wc -l) if [ "$1" ];then IDC_CODE=$1 fi GetSysInfo(){ if [ -s "/etc/redhat-release" ];then SYS_VERSION=$(cat /etc/redhat-release) elif [ -s "/etc/issue" ]; then SYS_VERSION=$(cat /etc/issue) fi SYS_INFO=$(uname -a) SYS_BIT=$(getconf LONG_BIT) MEM_TOTAL=$(free -m|grep Mem|awk '{print $2}') CPU_INFO=$(getconf _NPROCESSORS_ONLN) echo -e ${SYS_VERSION} echo -e Bit:${SYS_BIT} Mem:${MEM_TOTAL}M Core:${CPU_INFO} echo -e ${SYS_INFO} if [ -z "${os_version}" ];then echo -e "============================================" echo -e "检测到为非常用系统安装,建议更换至Centos-7或Debian-10+或Ubuntu-20+系统安装宝塔面板" echo -e "详情请查看系统兼容表：https://docs.qq.com/sheet/DUm54VUtyTVNlc21H?tab=BB08J2" echo -e "特殊情况可通过以下联系方式寻求安装协助情况" fi is64bit=$(getconf LONG_BIT) if [ "${is64bit}" == '32' ];then echo -e "宝塔面板不支持32位系统进行安装，请使用64位系统/服务器架构进行安装宝塔" exit 1 fi S390X_CHECK=$(uname -a|grep s390x) if [ "${S390X_CHECK}" ];then echo -e "宝塔面板不支持s390x架构进行安装，请使用64位系统/服务器架构进行安装宝塔" exit 1 fi echo -e "============================================" echo -e "请截图以上报错信息发帖至论坛www.bt.cn/bbs求助" echo -e "============================================" if [ -f "/usr/bin/qrencode" ];then echo -e "或微信扫码联系企业微信技术求助" echo -e "============================================" qrencode -t ANSIUTF8 "https://work.weixin.qq.com/kfid/kfc9072f0e29a53bd52" echo -e "============================================" else echo -e "或手机访问以下链接、扫码联系企业微信技术求助" echo -e "============================================" echo -e "联系链接:https://work.weixin.qq.com/kfid/kfc9072f0e29a53bd52" echo -e "============================================" fi } Red_Error(){ echo '================================================='; printf '\033[1;31;40m%b\033[0m\n' "$@"; GetSysInfo exit 1; } Lock_Clear(){ if [ -f "/etc/bt_crack.pl" ];then chattr -R -ia /www chattr -ia /etc/init.d/bt \cp -rpa /www/backup/panel/vhost/* /www/server/panel/vhost/ mv /www/server/panel/BTPanel/__init__.bak /www/server/panel/BTPanel/__init__.py rm -f /etc/bt_crack.pl fi } Install_Check(){ if [ "${INSTALL_FORCE}" ];then return fi echo -e "----------------------------------------------------" echo -e "检查已有其他Web/mysql环境，安装宝塔可能影响现有站点及数据" echo -e "Web/mysql service is alreday installed,Can't install panel" echo -e "----------------------------------------------------" echo -e "已知风险/Enter yes to force installation" read -p "输入yes强制安装: " yes; if [ "$yes" != "yes" ];then echo -e "------------" echo "取消安装" exit; fi INSTALL_FORCE="true" } System_Check(){ MYSQLD_CHECK=$(ps -ef |grep mysqld|grep -v grep|grep -v /www/server/mysql) PHP_CHECK=$(ps -ef|grep php-fpm|grep master|grep -v /www/server/php) NGINX_CHECK=$(ps -ef|grep nginx|grep master|grep -v /www/server/nginx) HTTPD_CHECK=$(ps -ef |grep -E 'httpd|apache'|grep -v /www/server/apache|grep -v grep) if [ "${PHP_CHECK}" ] || [ "${MYSQLD_CHECK}" ] || [ "${NGINX_CHECK}" ] || [ "${HTTPD_CHECK}" ];then Install_Check fi } Get_Pack_Manager(){ if [ -f "/usr/bin/yum" ] && [ -d "/etc/yum.repos.d" ]; then PM="yum" elif [ -f "/usr/bin/apt-get" ] && [ -f "/usr/bin/dpkg" ]; then PM="apt-get" fi } Auto_Swap() { swap=$(free |grep Swap|awk '{print $2}') if [ "${swap}" -gt 1 ];then echo "Swap total sizse: $swap"; return; fi if [ ! -d /www ];then mkdir /www fi swapFile="/www/swap" dd if=/dev/zero of=$swapFile bs=1M count=1025 mkswap -f $swapFile swapon $swapFile echo "$swapFile swap swap defaults 0 0" >> /etc/fstab swap=`free |grep Swap|awk '{print $2}'` if [ $swap -gt 1 ];then echo "Swap total sizse: $swap"; return; fi sed -i "/\/www\/swap/d" /etc/fstab rm -f $swapFile } Service_Add(){ if [ "${PM}" == "yum" ] || [ "${PM}" == "dnf" ]; then chkconfig --add bt chkconfig --level 2345 bt on Centos9Check=$(cat /etc/redhat-release |grep ' 9') if [ "${Centos9Check}" ];then wget -O /usr/lib/systemd/system/btpanel.service ${download_Url}/init/systemd/btpanel.service systemctl enable btpanel fi elif [ "${PM}" == "apt-get" ]; then update-rc.d bt defaults fi } Set_Centos_Repo(){ HUAWEI_CHECK=$(cat /etc/motd |grep "Huawei Cloud") if [ "${HUAWEI_CHECK}" ] && [ "${is64bit}" == "64" ];then \cp -rpa /etc/yum.repos.d/ /etc/yumBak sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*.repo sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.epel.cloud|g' /etc/yum.repos.d/CentOS-*.repo rm -f /etc/yum.repos.d/epel.repo rm -f /etc/yum.repos.d/epel-* fi ALIYUN_CHECK=$(cat /etc/motd|grep "Alibaba Cloud ") if [ "${ALIYUN_CHECK}" ] && [ "${is64bit}" == "64" ] && [ ! -f "/etc/yum.repos.d/Centos-vault-8.5.2111.repo" ];then rename '.repo' '.repo.bak' /etc/yum.repos.d/*.repo wget https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo -O /etc/yum.repos.d/Centos-vault-8.5.2111.repo wget https://mirrors.aliyun.com/repo/epel-archive-8.repo -O /etc/yum.repos.d/epel-archive-8.repo sed -i 's/mirrors.cloud.aliyuncs.com/url_tmp/g' /etc/yum.repos.d/Centos-vault-8.5.2111.repo && sed -i 's/mirrors.aliyun.com/mirrors.cloud.aliyuncs.com/g' /etc/yum.repos.d/Centos-vault-8.5.2111.repo && sed -i 's/url_tmp/mirrors.aliyun.com/g' /etc/yum.repos.d/Centos-vault-8.5.2111.repo sed -i 's/mirrors.aliyun.com/mirrors.cloud.aliyuncs.com/g' /etc/yum.repos.d/epel-archive-8.repo fi MIRROR_CHECK=$(cat /etc/yum.repos.d/CentOS-Linux-AppStream.repo |grep "[^#]mirror.centos.org") if [ "${MIRROR_CHECK}" ] && [ "${is64bit}" == "64" ];then \cp -rpa /etc/yum.repos.d/ /etc/yumBak sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*.repo sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.epel.cloud|g' /etc/yum.repos.d/CentOS-*.repo fi } get_node_url(){ if [ ! -f /bin/curl ];then if [ "${PM}" = "yum" ]; then yum install curl -y elif [ "${PM}" = "apt-get" ]; then apt-get install curl -y fi fi if [ -f "/www/node.pl" ];then download_Url=$(cat /www/node.pl) echo "Download node: $download_Url"; echo '---------------------------------------------'; return fi echo '---------------------------------------------'; echo "Selected download node..."; nodes=(http://dg2.bt.cn http://dg1.bt.cn http://download.bt.cn http://125.90.93.52:5880 http://36.133.1.8:5880 http://123.129.198.197 http://103.179.243.14:5880 http://128.1.164.196); if [ "$1" ];then nodes=($(echo ${nodes[*]}|sed "s#${1}##")) fi tmp_file1=/dev/shm/net_test1.pl tmp_file2=/dev/shm/net_test2.pl [ -f "${tmp_file1}" ] && rm -f ${tmp_file1} [ -f "${tmp_file2}" ] && rm -f ${tmp_file2} touch $tmp_file1 touch $tmp_file2 for node in ${nodes[@]}; do NODE_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${node}/net_test|xargs) RES=$(echo ${NODE_CHECK}|awk '{print $1}') NODE_STATUS=$(echo ${NODE_CHECK}|awk '{print $2}') TIME_TOTAL=$(echo ${NODE_CHECK}|awk '{print $3 * 1000 - 500 }'|cut -d '.' -f 1) if [ "${NODE_STATUS}" == "200" ];then if [ $TIME_TOTAL -lt 100 ];then if [ $RES -ge 1500 ];then echo "$RES $node" >> $tmp_file1 fi else if [ $RES -ge 1500 ];then echo "$TIME_TOTAL $node" >> $tmp_file2 fi fi i=$(($i+1)) if [ $TIME_TOTAL -lt 100 ];then if [ $RES -ge 3000 ];then break; fi fi fi done NODE_URL=$(cat $tmp_file1|sort -r -g -t " " -k 1|head -n 1|awk '{print $2}') if [ -z "$NODE_URL" ];then NODE_URL=$(cat $tmp_file2|sort -g -t " " -k 1|head -n 1|awk '{print $2}') if [ -z "$NODE_URL" ];then NODE_URL='http://download.bt.cn'; fi fi rm -f $tmp_file1 rm -f $tmp_file2 download_Url=$NODE_URL echo "Download node: $download_Url"; echo '---------------------------------------------'; } Remove_Package(){ local PackageNmae=$1 if [ "${PM}" == "yum" ];then isPackage=$(rpm -q ${PackageNmae}|grep "not installed") if [ -z "${isPackage}" ];then yum remove ${PackageNmae} -y fi elif [ "${PM}" == "apt-get" ];then isPackage=$(dpkg -l|grep ${PackageNmae}) if [ "${PackageNmae}" ];then apt-get remove ${PackageNmae} -y fi fi } Install_RPM_Pack(){ yumPath=/etc/yum.conf Centos8Check=$(cat /etc/redhat-release | grep ' 8.' | grep -iE 'centos|Red Hat') if [ "${Centos8Check}" ];then Set_Centos_Repo fi isExc=$(cat $yumPath|grep httpd) if [ "$isExc" = "" ];then echo "exclude=httpd nginx php mysql mairadb python-psutil python2-psutil" >> $yumPath fi #SYS_TYPE=$(uname -a|grep x86_64) #yumBaseUrl=$(cat /etc/yum.repos.d/CentOS-Base.repo|grep baseurl=http|cut -d '=' -f 2|cut -d '$' -f 1|head -n 1) #[ "${yumBaseUrl}" ] && checkYumRepo=$(curl --connect-timeout 5 --head -s -o /dev/null -w %{http_code} ${yumBaseUrl}) #if [ "${checkYumRepo}" != "200" ] && [ "${SYS_TYPE}" ];then # curl -Ss --connect-timeout 3 -m 60 http://download.bt.cn/install/yumRepo_select.sh|bash #fi #尝试同步时间(从bt.cn) echo 'Synchronizing system time...' getBtTime=$(curl -sS --connect-timeout 3 -m 60 http://www.bt.cn/api/index/get_time) if [ "${getBtTime}" ];then date -s "$(date -d @$getBtTime +"%Y-%m-%d %H:%M:%S")" fi if [ -z "${Centos8Check}" ]; then yum install ntp -y rm -rf /etc/localtime ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime #尝试同步国际时间(从ntp服务器) ntpdate 0.asia.pool.ntp.org setenforce 0 fi startTime=`date +%s` sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config #yum remove -y python-requests python3-requests python-greenlet python3-greenlet yumPacks="libcurl-devel wget tar gcc make zip unzip openssl openssl-devel gcc libxml2 libxml2-devel libxslt* zlib zlib-devel libjpeg-devel libpng-devel libwebp libwebp-devel freetype freetype-devel lsof pcre pcre-devel vixie-cron crontabs icu libicu-devel c-ares libffi-devel bzip2-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel qrencode" yum install -y ${yumPacks} for yumPack in ${yumPacks} do rpmPack=$(rpm -q ${yumPack}) packCheck=$(echo ${rpmPack}|grep not) if [ "${packCheck}" ]; then yum install ${yumPack} -y fi done if [ -f "/usr/bin/dnf" ]; then dnf install -y redhat-rpm-config fi ALI_OS=$(cat /etc/redhat-release |grep "Alibaba Cloud Linux release 3") if [ -z "${ALI_OS}" ];then yum install epel-release -y fi } Install_Deb_Pack(){ ln -sf bash /bin/sh UBUNTU_22=$(cat /etc/issue|grep "Ubuntu 22") if [ "${UBUNTU_22}" ];then apt-get remove needrestart -y fi ALIYUN_CHECK=$(cat /etc/motd|grep "Alibaba Cloud ") if [ "${ALIYUN_CHECK}" ] && [ "${UBUNTU_22}" ];then apt-get remove libicu70 -y fi apt-get update -y apt-get install bash -y if [ -f "/usr/bin/bash" ];then ln -sf /usr/bin/bash /bin/sh fi apt-get install ruby -y apt-get install lsb-release -y #apt-get install ntp ntpdate -y #/etc/init.d/ntp stop #update-rc.d ntp remove #cat >>~/.profile<<EOF #TZ='Asia/Shanghai'; export TZ #EOF #rm -rf /etc/localtime #cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime #echo 'Synchronizing system time...' #ntpdate 0.asia.pool.ntp.org #apt-get upgrade -y LIBCURL_VER=$(dpkg -l|grep libcurl4|awk '{print $3}') if [ "${LIBCURL_VER}" == "7.68.0-1ubuntu2.8" ];then apt-get remove libcurl4 -y apt-get install curl -y fi debPacks="wget curl libcurl4-openssl-dev gcc make zip unzip tar openssl libssl-dev gcc libxml2 libxml2-dev zlib1g zlib1g-dev libjpeg-dev libpng-dev lsof libpcre3 libpcre3-dev cron net-tools swig build-essential libffi-dev libbz2-dev libncurses-dev libsqlite3-dev libreadline-dev tk-dev libgdbm-dev libdb-dev libdb++-dev libpcap-dev xz-utils git qrencode"; apt-get install -y $debPacks --force-yes for debPack in ${debPacks} do packCheck=$(dpkg -l|grep ${debPack}) if [ "$?" -ne "0" ] ;then apt-get install -y $debPack fi done if [ ! -d '/etc/letsencrypt' ];then mkdir -p /etc/letsencryp mkdir -p /var/spool/cron if [ ! -f '/var/spool/cron/crontabs/root' ];then echo '' > /var/spool/cron/crontabs/root chmod 600 /var/spool/cron/crontabs/root fi fi } Get_Versions(){ redhat_version_file="/etc/redhat-release" deb_version_file="/etc/issue" if [ -f $redhat_version_file ];then os_type='el' is_aliyunos=$(cat $redhat_version_file|grep Aliyun) if [ "$is_aliyunos" != "" ];then return fi os_version=$(cat $redhat_version_file|grep CentOS|grep -Eo '([0-9]+\.)+[0-9]+'|grep -Eo '^[0-9]') if [ "${os_version}" = "5" ];then os_version="" fi if [ -z "${os_version}" ];then os_version=$(cat /etc/redhat-release |grep Stream|grep -oE 8) fi else os_type='ubuntu' os_version=$(cat $deb_version_file|grep Ubuntu|grep -Eo '([0-9]+\.)+[0-9]+'|grep -Eo '^[0-9]+') if [ "${os_version}" = "" ];then os_type='debian' os_version=$(cat $deb_version_file|grep Debian|grep -Eo '([0-9]+\.)+[0-9]+'|grep -Eo '[0-9]+') if [ "${os_version}" = "" ];then os_version=$(cat $deb_version_file|grep Debian|grep -Eo '[0-9]+') fi if [ "${os_version}" = "8" ];then os_version="" fi if [ "${is64bit}" = '32' ];then os_version="" fi else if [ "$os_version" = "14" ];then os_version="" fi if [ "$os_version" = "12" ];then os_version="" fi if [ "$os_version" = "19" ];then os_version="" fi if [ "$os_version" = "21" ];then os_version="" fi if [ "$os_version" = "20" ];then os_version2004=$(cat /etc/issue|grep 20.04) if [ -z "${os_version2004}" ];then os_version="" fi fi fi fi } Install_Python_Lib(){ curl -Ss --connect-timeout 3 -m 60 $download_Url/install/pip_select.sh|bash pyenv_path="/www/server/panel" if [ -f $pyenv_path/pyenv/bin/python ];then is_ssl=$($python_bin -c "import ssl" 2>&1|grep cannot) $pyenv_path/pyenv/bin/python3.7 -V if [ $? -eq 0 ] && [ -z "${is_ssl}" ];then chmod -R 700 $pyenv_path/pyenv/bin is_package=$($python_bin -m psutil 2>&1|grep package) if [ "$is_package" = "" ];then wget -O $pyenv_path/pyenv/pip.txt $download_Url/install/pyenv/pip.txt -T 5 $pyenv_path/pyenv/bin/pip install -U pip $pyenv_path/pyenv/bin/pip install -U setuptools==65.5.0 $pyenv_path/pyenv/bin/pip install -r $pyenv_path/pyenv/pip.txt fi source $pyenv_path/pyenv/bin/activate chmod -R 700 $pyenv_path/pyenv/bin return else rm -rf $pyenv_path/pyenv fi fi is_loongarch64=$(uname -a|grep loongarch64) if [ "$is_loongarch64" != "" ] && [ -f "/usr/bin/yum" ];then yumPacks="python3-devel python3-pip python3-psutil python3-gevent python3-pyOpenSSL python3-paramiko python3-flask python3-rsa python3-requests python3-six python3-websocket-client" yum install -y ${yumPacks} for yumPack in ${yumPacks} do rpmPack=$(rpm -q ${yumPack}) packCheck=$(echo ${rpmPack}|grep not) if [ "${packCheck}" ]; then yum install ${yumPack} -y fi done pip3 install -U pip pip3 install Pillow psutil pyinotify pycryptodome upyun oss2 pymysql qrcode qiniu redis pymongo Cython configparser cos-python-sdk-v5 supervisor gevent-websocket pyopenssl pip3 install flask==1.1.4 pip3 install Pillow -U pyenv_bin=/www/server/panel/pyenv/bin mkdir -p $pyenv_bin ln -sf /usr/local/bin/pip3 $pyenv_bin/pip ln -sf /usr/local/bin/pip3 $pyenv_bin/pip3 ln -sf /usr/local/bin/pip3 $pyenv_bin/pip3.7 if [ -f "/usr/bin/python3.7" ];then ln -sf /usr/bin/python3.7 $pyenv_bin/python ln -sf /usr/bin/python3.7 $pyenv_bin/python3 ln -sf /usr/bin/python3.7 $pyenv_bin/python3.7 elif [ -f "/usr/bin/python3.6" ]; then ln -sf /usr/bin/python3.6 $pyenv_bin/python ln -sf /usr/bin/python3.6 $pyenv_bin/python3 ln -sf /usr/bin/python3.6 $pyenv_bin/python3.7 fi echo > $pyenv_bin/activate return fi py_version="3.7.8" mkdir -p $pyenv_path echo "True" > /www/disk.pl if [ ! -w /www/disk.pl ];then Red_Error "ERROR: Install python env fielded." "ERROR: /www目录无法写入，请检查目录/用户/磁盘权限！" fi os_type='el' os_version='7' is_export_openssl=0 Get_Versions echo "OS: $os_type - $os_version" is_aarch64=$(uname -a|grep aarch64) if [ "$is_aarch64" != "" ];then is64bit="aarch64" fi if [ -f "/www/server/panel/pymake.pl" ];then os_version="" rm -f /www/server/panel/pymake.pl fi if [ "${os_version}" != "" ];then pyenv_file="/www/pyenv.tar.gz" wget -O $pyenv_file $download_Url/install/pyenv/pyenv-${os_type}${os_version}-x${is64bit}.tar.gz -T 10 if [ "$?" != "0" ];then get_node_url $download_Url wget -O $pyenv_file $download_Url/install/pyenv/pyenv-${os_type}${os_version}-x${is64bit}.tar.gz -T 10 fi tmp_size=$(du -b $pyenv_file|awk '{print $1}') if [ $tmp_size -lt 703460 ];then rm -f $pyenv_file echo "ERROR: Download python env fielded." else echo "Install python env..." tar zxvf $pyenv_file -C $pyenv_path/ > /dev/null chmod -R 700 $pyenv_path/pyenv/bin if [ ! -f $pyenv_path/pyenv/bin/python ];then rm -f $pyenv_file Red_Error "ERROR: Install python env fielded." "ERROR: 下载宝塔运行环境失败，请尝试重新安装！" fi $pyenv_path/pyenv/bin/python3.7 -V if [ $? -eq 0 ];then rm -f $pyenv_file ln -sf $pyenv_path/pyenv/bin/pip3.7 /usr/bin/btpip ln -sf $pyenv_path/pyenv/bin/python3.7 /usr/bin/btpython source $pyenv_path/pyenv/bin/activate return else rm -f $pyenv_file rm -rf $pyenv_path/pyenv fi fi fi cd /www python_src='/www/python_src.tar.xz' python_src_path="/www/Python-${py_version}" wget -O $python_src $download_Url/src/Python-${py_version}.tar.xz -T 5 tmp_size=$(du -b $python_src|awk '{print $1}') if [ $tmp_size -lt 10703460 ];then rm -f $python_src Red_Error "ERROR: Download python source code fielded." "ERROR: 下载宝塔运行环境失败，请尝试重新安装！" fi tar xvf $python_src rm -f $python_src cd $python_src_path ./configure --prefix=$pyenv_path/pyenv make -j$cpu_cpunt make install if [ ! -f $pyenv_path/pyenv/bin/python3.7 ];then rm -rf $python_src_path Red_Error "ERROR: Make python env fielded." "ERROR: 编译宝塔运行环境失败！" fi cd ~ rm -rf $python_src_path wget -O $pyenv_path/pyenv/bin/activate $download_Url/install/pyenv/activate.panel -T 5 wget -O $pyenv_path/pyenv/pip.txt $download_Url/install/pyenv/pip-3.7.8.txt -T 5 ln -sf $pyenv_path/pyenv/bin/pip3.7 $pyenv_path/pyenv/bin/pip ln -sf $pyenv_path/pyenv/bin/python3.7 $pyenv_path/pyenv/bin/python ln -sf $pyenv_path/pyenv/bin/pip3.7 /usr/bin/btpip ln -sf $pyenv_path/pyenv/bin/python3.7 /usr/bin/btpython chmod -R 700 $pyenv_path/pyenv/bin $pyenv_path/pyenv/bin/pip install -U pip $pyenv_path/pyenv/bin/pip install -U setuptools==65.5.0 $pyenv_path/pyenv/bin/pip install -U wheel==0.34.2 $pyenv_path/pyenv/bin/pip install -r $pyenv_path/pyenv/pip.txt source $pyenv_path/pyenv/bin/activate is_gevent=$($python_bin -m gevent 2>&1|grep -oE package) is_psutil=$($python_bin -m psutil 2>&1|grep -oE package) if [ "${is_gevent}" != "${is_psutil}" ];then Red_Error "ERROR: psutil/gevent install failed!" fi } Install_Bt(){ panelPort="8888" if [ -f ${setup_path}/server/panel/data/port.pl ];then panelPort=$(cat ${setup_path}/server/panel/data/port.pl) else RE_NUM=$(expr $RANDOM % 3) if [ "${RE_NUM}" == "1" ];then panelPort=$(expr $RANDOM % 55535 + 10000) fi fi mkdir -p ${setup_path}/server/panel/logs mkdir -p ${setup_path}/server/panel/vhost/apache mkdir -p ${setup_path}/server/panel/vhost/nginx mkdir -p ${setup_path}/server/panel/vhost/rewrite mkdir -p ${setup_path}/server/panel/install mkdir -p /www/server mkdir -p /www/wwwroot mkdir -p /www/wwwlogs mkdir -p /www/backup/database mkdir -p /www/backup/site if [ ! -d "/etc/init.d" ];then mkdir -p /etc/init.d fi if [ -f "/etc/init.d/bt" ]; then /etc/init.d/bt stop sleep 1 fi wget -O /etc/init.d/bt ${download_Url}/install/src/bt6.init -T 10 wget -O /www/server/panel/install/public.sh ${download_Url}/install/public.sh -T 10 wget -O panel.zip ${download_Url}/install/src/panel6.zip -T 10 if [ -f "${setup_path}/server/panel/data/default.db" ];then if [ -d "/${setup_path}/server/panel/old_data" ];then rm -rf ${setup_path}/server/panel/old_data fi mkdir -p ${setup_path}/server/panel/old_data d_format=$(date +"%Y%m%d_%H%M%S") \cp -arf ${setup_path}/server/panel/data/default.db ${setup_path}/server/panel/data/default_backup_${d_format}.db mv -f ${setup_path}/server/panel/data/default.db ${setup_path}/server/panel/old_data/default.db mv -f ${setup_path}/server/panel/data/system.db ${setup_path}/server/panel/old_data/system.db mv -f ${setup_path}/server/panel/data/port.pl ${setup_path}/server/panel/old_data/port.pl mv -f ${setup_path}/server/panel/data/admin_path.pl ${setup_path}/server/panel/old_data/admin_path.pl fi if [ ! -f "/usr/bin/unzip" ]; then if [ "${PM}" = "yum" ]; then yum install unzip -y elif [ "${PM}" = "apt-get" ]; then apt-get update apt-get install unzip -y fi fi unzip -o panel.zip -d ${setup_path}/server/ > /dev/null if [ -d "${setup_path}/server/panel/old_data" ];then mv -f ${setup_path}/server/panel/old_data/default.db ${setup_path}/server/panel/data/default.db mv -f ${setup_path}/server/panel/old_data/system.db ${setup_path}/server/panel/data/system.db mv -f ${setup_path}/server/panel/old_data/port.pl ${setup_path}/server/panel/data/port.pl mv -f ${setup_path}/server/panel/old_data/admin_path.pl ${setup_path}/server/panel/data/admin_path.pl if [ -d "/${setup_path}/server/panel/old_data" ];then rm -rf ${setup_path}/server/panel/old_data fi fi if [ ! -f ${setup_path}/server/panel/tools.py ] || [ ! -f ${setup_path}/server/panel/BT-Panel ];then ls -lh panel.zip Red_Error "ERROR: Failed to download, please try install again!" "ERROR: 下载宝塔失败，请尝试重新安装！" fi rm -f panel.zip rm -f ${setup_path}/server/panel/class/*.pyc rm -f ${setup_path}/server/panel/*.pyc chmod +x /etc/init.d/bt chmod -R 600 ${setup_path}/server/panel chmod -R +x ${setup_path}/server/panel/script ln -sf /etc/init.d/bt /usr/bin/bt echo "${panelPort}" > ${setup_path}/server/panel/data/port.pl wget -O /etc/init.d/bt ${download_Url}/install/src/bt7.init -T 10 wget -O /www/server/panel/init.sh ${download_Url}/install/src/bt7.init -T 10 wget -O /www/server/panel/data/softList.conf ${download_Url}/install/conf/softList.conf } Set_Bt_Panel(){ Run_User="www" wwwUser=$(cat /etc/passwd|cut -d ":" -f 1|grep ^www$) if [ "${wwwUser}" != "www" ];then groupadd ${Run_User} useradd -s /sbin/nologin -g ${Run_User} ${Run_User} fi password=$(cat /dev/urandom | head -n 16 | md5sum | head -c 8) sleep 1 admin_auth="/www/server/panel/data/admin_path.pl" if [ ! -f ${admin_auth} ];then auth_path=$(cat /dev/urandom | head -n 16 | md5sum | head -c 8) echo "/${auth_path}" > ${admin_auth} fi chmod -R 700 $pyenv_path/pyenv/bin /www/server/panel/pyenv/bin/pip3 install pymongo /www/server/panel/pyenv/bin/pip3 install psycopg2-binary /www/server/panel/pyenv/bin/pip3 install flask -U /www/server/panel/pyenv/bin/pip3 install flask-sock auth_path=$(cat ${admin_auth}) cd ${setup_path}/server/panel/ /etc/init.d/bt start $python_bin -m py_compile tools.py $python_bin tools.py username username=$($python_bin tools.py panel ${password}) cd ~ echo "${password}" > ${setup_path}/server/panel/default.pl chmod 600 ${setup_path}/server/panel/default.pl sleep 3 /etc/init.d/bt restart sleep 3 isStart=$(ps aux |grep 'BT-Panel'|grep -v grep|awk '{print $2}') LOCAL_CURL=$(curl 127.0.0.1:8888/login 2>&1 |grep -i html) if [ -z "${isStart}" ] && [ -z "${LOCAL_CURL}" ];then /etc/init.d/bt 22 cd /www/server/panel/pyenv/bin touch t.pl ls -al python3.7 python lsattr python3.7 python Red_Error "ERROR: The BT-Panel service startup failed." "ERROR: 宝塔启动失败" fi wget -O oneav_bt.sh http://download.bt.cn/install/plugin/oneav/install.sh > /dev/null 2>&1 bash oneav_bt.sh install > /www/server/panel/install//btinstall.log 2>&1 rm -f oneav_bt.sh } Set_Firewall(){ sshPort=$(cat /etc/ssh/sshd_config | grep 'Port '|awk '{print $2}') if [ "${PM}" = "apt-get" ]; then apt-get install -y ufw if [ -f "/usr/sbin/ufw" ];then ufw allow 20/tcp ufw allow 21/tcp ufw allow 22/tcp ufw allow 80/tcp ufw allow 443/tcp ufw allow 888/tcp ufw allow ${panelPort}/tcp ufw allow ${sshPort}/tcp ufw allow 39000:40000/tcp ufw_status=`ufw status` echo y|ufw enable ufw default deny ufw reload fi else if [ -f "/etc/init.d/iptables" ];then iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 20 -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 21 -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ${panelPort} -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ${sshPort} -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 39000:40000 -j ACCEPT #iptables -I INPUT -p tcp -m state --state NEW -m udp --dport 39000:40000 -j ACCEPT iptables -A INPUT -p icmp --icmp-type any -j ACCEPT iptables -A INPUT -s localhost -d localhost -j ACCEPT iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -P INPUT DROP service iptables save sed -i "s#IPTABLES_MODULES=\"\"#IPTABLES_MODULES=\"ip_conntrack_netbios_ns ip_conntrack_ftp ip_nat_ftp\"#" /etc/sysconfig/iptables-config iptables_status=$(service iptables status | grep 'not running') if [ "${iptables_status}" == '' ];then service iptables restart fi else AliyunCheck=$(cat /etc/redhat-release|grep "Aliyun Linux") [ "${AliyunCheck}" ] && return yum install firewalld -y [ "${Centos8Check}" ] && yum reinstall python3-six -y systemctl enable firewalld systemctl start firewalld firewall-cmd --set-default-zone=public > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=20/tcp > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=21/tcp > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=22/tcp > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=80/tcp > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=443/tcp > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=${panelPort}/tcp > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=${sshPort}/tcp > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=39000-40000/tcp > /dev/null 2>&1 #firewall-cmd --permanent --zone=public --add-port=39000-40000/udp > /dev/null 2>&1 firewall-cmd --reload fi fi } Get_Ip_Address(){ getIpAddress="" getIpAddress=$(curl -sS --connect-timeout 10 -m 60 https://www.bt.cn/Api/getIpAddress) if [ -z "${getIpAddress}" ] || [ "${getIpAddress}" = "0.0.0.0" ]; then isHosts=$(cat /etc/hosts|grep 'www.bt.cn') if [ -z "${isHosts}" ];then echo "" >> /etc/hosts echo "116.213.43.206 www.bt.cn" >> /etc/hosts getIpAddress=$(curl -sS --connect-timeout 10 -m 60 https://www.bt.cn/Api/getIpAddress) if [ -z "${getIpAddress}" ];then sed -i "/bt.cn/d" /etc/hosts fi fi fi ipv4Check=$($python_bin -c "import re; print(re.match('^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$','${getIpAddress}'))") if [ "${ipv4Check}" == "None" ];then ipv6Address=$(echo ${getIpAddress}|tr -d "[]") ipv6Check=$($python_bin -c "import re; print(re.match('^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$','${ipv6Address}'))") if [ "${ipv6Check}" == "None" ]; then getIpAddress="SERVER_IP" else echo "True" > ${setup_path}/server/panel/data/ipv6.pl sleep 1 /etc/init.d/bt restart fi fi if [ "${getIpAddress}" != "SERVER_IP" ];then echo "${getIpAddress}" > ${setup_path}/server/panel/data/iplist.txt fi LOCAL_IP=$(ip addr | grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -E -v "^127\.|^255\.|^0\." | head -n 1) } Setup_Count(){ curl -sS --connect-timeout 10 -m 60 https://www.bt.cn/Api/SetupCount?type=Linux\&o=$1 > /dev/null 2>&1 if [ "$1" != "" ];then echo $1 > /www/server/panel/data/o.pl cd /www/server/panel $python_bin tools.py o fi echo /www > /var/bt_setupPath.conf } Install_Main(){ startTime=`date +%s` Lock_Clear System_Check Get_Pack_Manager get_node_url MEM_TOTAL=$(free -g|grep Mem|awk '{print $2}') if [ "${MEM_TOTAL}" -le "1" ];then Auto_Swap fi if [ "${PM}" = "yum" ]; then Install_RPM_Pack elif [ "${PM}" = "apt-get" ]; then Install_Deb_Pack fi Install_Python_Lib Install_Bt Set_Bt_Panel Service_Add Set_Firewall Get_Ip_Address Setup_Count ${IDC_CODE} } echo " +---------------------------------------------------------------------- | Bt-WebPanel FOR CentOS/Ubuntu/Debian +---------------------------------------------------------------------- | Copyright © 2015-2099 BT-SOFT(http://www.bt.cn) All rights reserved. +---------------------------------------------------------------------- | The WebPanel URL will be http://SERVER_IP:8888 when installed. +---------------------------------------------------------------------- | 为了您的正常使用，请确保使用全新或纯净的系统安装宝塔面板，不支持已部署项目/环境的系统安装 +---------------------------------------------------------------------- " while [ "$go" != 'y' ] && [ "$go" != 'n' ] do read -p "Do you want to install Bt-Panel to the $setup_path directory now?(y/n): " go; done if [ "$go" == 'n' ];then exit; fi ARCH_LINUX=$(cat /etc/os-release |grep "Arch Linux") if [ "${ARCH_LINUX}" ] && [ -f "/usr/bin/pacman" ];then pacman -Sy pacman -S curl wget unzip firewalld openssl pkg-config make gcc cmake libxml2 libxslt libvpx gd libsodium oniguruma sqlite libzip autoconf inetutils sudo --noconfirm fi Install_Main echo > /www/server/panel/data/bind.pl echo -e "==================================================================" echo -e "\033[32mCongratulations! Installed successfully!\033[0m" echo -e "==================================================================" echo "外网面板地址: http://${getIpAddress}:${panelPort}${auth_path}" echo "内网面板地址: http://${LOCAL_IP}:${panelPort}${auth_path}" echo -e "username: $username" echo -e "password: $password" echo -e "\033[33mIf you cannot access the panel,\033[0m" echo -e "\033[33mrelease the following panel port [${panelPort}] in the security group\033[0m" echo -e "\033[33m若无法访问面板，请检查防火墙/安全组是否有放行面板[${panelPort}]端口\033[0m" echo -e "==================================================================" endTime=`date +%s` ((outTime=($endTime-$startTime)/60)) echo -e "Time consumed:\033[32m $outTime \033[0mMinute!"
#!/bin/bash PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin export PATH LANG=en_US.UTF-8 if [ $(whoami) != "root" ];then echo "请使用root权限执行宝塔安装命令！" exit 1; fi is64bit=$(getconf LONG_BIT) if [ "${is64bit}" != '64' ];then Red_Error "抱歉, 当前面板版本不支持32位系统, 请使用64位系统或安装宝塔5.9!"; fi Centos6Check=$(cat /etc/redhat-release | grep ' 6.' | grep -iE 'centos|Red Hat') if [ "${Centos6Check}" ];then echo "Centos6不支持安装宝塔面板，请更换Centos7/8安装宝塔面板" exit 1 fi UbuntuCheck=$(cat /etc/issue|grep Ubuntu|awk '{print $2}'|cut -f 1 -d '.') if [ "${UbuntuCheck}" -lt "16" ];then echo "Ubuntu ${UbuntuCheck}不支持安装宝塔面板，建议更换Ubuntu18/20安装宝塔面板" exit 1 fi cd ~ setup_path="/www" python_bin=$setup_path/server/panel/pyenv/bin/python cpu_cpunt=$(cat /proc/cpuinfo|grep processor|wc -l) if [ "$1" ];then IDC_CODE=$1 fi GetSysInfo(){ if [ -s "/etc/redhat-release" ];then SYS_VERSION=$(cat /etc/redhat-release) elif [ -s "/etc/issue" ]; then SYS_VERSION=$(cat /etc/issue) fi SYS_INFO=$(uname -a) SYS_BIT=$(getconf LONG_BIT) MEM_TOTAL=$(free -m|grep Mem|awk '{print $2}') CPU_INFO=$(getconf _NPROCESSORS_ONLN) echo -e ${SYS_VERSION} echo -e Bit:${SYS_BIT} Mem:${MEM_TOTAL}M Core:${CPU_INFO} echo -e ${SYS_INFO} echo -e "请截图以上报错信息发帖至论坛www.bt.cn/bbs求助" } Red_Error(){ echo '================================================='; printf '\033[1;31;40m%b\033[0m\n' "$@"; GetSysInfo exit 1; } Lock_Clear(){ if [ -f "/etc/bt_crack.pl" ];then chattr -R -ia /www chattr -ia /etc/init.d/bt \cp -rpa /www/backup/panel/vhost/* /www/server/panel/vhost/ mv /www/server/panel/BTPanel/__init__.bak /www/server/panel/BTPanel/__init__.py rm -f /etc/bt_crack.pl fi } Install_Check(){ if [ "${INSTALL_FORCE}" ];then return fi echo -e "----------------------------------------------------" echo -e "检查已有其他Web/mysql环境，安装宝塔可能影响现有站点及数据" echo -e "Web/mysql service is alreday installed,Can't install panel" echo -e "----------------------------------------------------" echo -e "已知风险/Enter yes to force installation" read -p "输入yes强制安装: " yes; if [ "$yes" != "yes" ];then echo -e "------------" echo "取消安装" exit; fi INSTALL_FORCE="true" } System_Check(){ MYSQLD_CHECK=$(ps -ef |grep mysqld|grep -v grep|grep -v /www/server/mysql) PHP_CHECK=$(ps -ef|grep php-fpm|grep master|grep -v /www/server/php) NGINX_CHECK=$(ps -ef|grep nginx|grep master|grep -v /www/server/nginx) HTTPD_CHECK=$(ps -ef |grep -E 'httpd|apache'|grep -v /www/server/apache|grep -v grep) if [ "${PHP_CHECK}" ] || [ "${MYSQLD_CHECK}" ] || [ "${NGINX_CHECK}" ] || [ "${HTTPD_CHECK}" ];then Install_Check fi } Get_Pack_Manager(){ if [ -f "/usr/bin/yum" ] && [ -d "/etc/yum.repos.d" ]; then PM="yum" elif [ -f "/usr/bin/apt-get" ] && [ -f "/usr/bin/dpkg" ]; then PM="apt-get" fi } Auto_Swap() { swap=$(free |grep Swap|awk '{print $2}') if [ "${swap}" -gt 1 ];then echo "Swap total sizse: $swap"; return; fi if [ ! -d /www ];then mkdir /www fi swapFile="/www/swap" dd if=/dev/zero of=$swapFile bs=1M count=1025 mkswap -f $swapFile swapon $swapFile echo "$swapFile swap swap defaults 0 0" >> /etc/fstab swap=`free |grep Swap|awk '{print $2}'` if [ $swap -gt 1 ];then echo "Swap total sizse: $swap"; return; fi sed -i "/\/www\/swap/d" /etc/fstab rm -f $swapFile } Service_Add(){ if [ "${PM}" == "yum" ] || [ "${PM}" == "dnf" ]; then chkconfig --add bt chkconfig --level 2345 bt on elif [ "${PM}" == "apt-get" ]; then update-rc.d bt defaults fi } get_node_url(){ if [ ! -f /bin/curl ];then if [ "${PM}" = "yum" ]; then yum install curl -y elif [ "${PM}" = "apt-get" ]; then apt-get install curl -y fi fi if [ -f "/www/node.pl" ];then download_Url=$(cat /www/node.pl) echo "Download node: $download_Url"; echo '---------------------------------------------'; return fi echo '---------------------------------------------'; echo "Selected download node..."; nodes=(http://dg2.bt.cn http://dg1.bt.cn http://125.90.93.52:5880 http://36.133.1.8:5880 http://123.129.198.197 http://38.34.185.130 http://116.213.43.206:5880 http://128.1.164.196); tmp_file1=/dev/shm/net_test1.pl tmp_file2=/dev/shm/net_test2.pl [ -f "${tmp_file1}" ] && rm -f ${tmp_file1} [ -f "${tmp_file2}" ] && rm -f ${tmp_file2} touch $tmp_file1 touch $tmp_file2 for node in ${nodes[@]}; do NODE_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${node}/net_test|xargs) RES=$(echo ${NODE_CHECK}|awk '{print $1}') NODE_STATUS=$(echo ${NODE_CHECK}|awk '{print $2}') TIME_TOTAL=$(echo ${NODE_CHECK}|awk '{print $3 * 1000 - 500 }'|cut -d '.' -f 1) if [ "${NODE_STATUS}" == "200" ];then if [ $TIME_TOTAL -lt 100 ];then if [ $RES -ge 1500 ];then echo "$RES $node" >> $tmp_file1 fi else if [ $RES -ge 1500 ];then echo "$TIME_TOTAL $node" >> $tmp_file2 fi fi i=$(($i+1)) if [ $TIME_TOTAL -lt 100 ];then if [ $RES -ge 3000 ];then break; fi fi fi done NODE_URL=$(cat $tmp_file1|sort -r -g -t " " -k 1|head -n 1|awk '{print $2}') if [ -z "$NODE_URL" ];then NODE_URL=$(cat $tmp_file2|sort -g -t " " -k 1|head -n 1|awk '{print $2}') if [ -z "$NODE_URL" ];then NODE_URL='http://download.bt.cn'; fi fi rm -f $tmp_file1 rm -f $tmp_file2 download_Url=$NODE_URL echo "Download node: $download_Url"; echo '---------------------------------------------'; } Remove_Package(){ local PackageNmae=$1 if [ "${PM}" == "yum" ];then isPackage=$(rpm -q ${PackageNmae}|grep "not installed") if [ -z "${isPackage}" ];then yum remove ${PackageNmae} -y fi elif [ "${PM}" == "apt-get" ];then isPackage=$(dpkg -l|grep ${PackageNmae}) if [ "${PackageNmae}" ];then apt-get remove ${PackageNmae} -y fi fi } Install_RPM_Pack(){ yumPath=/etc/yum.conf Centos8Check=$(cat /etc/redhat-release | grep ' 8.' | grep -iE 'centos|Red Hat') isExc=$(cat $yumPath|grep httpd) if [ "$isExc" = "" ];then echo "exclude=httpd nginx php mysql mairadb python-psutil python2-psutil" >> $yumPath fi #SYS_TYPE=$(uname -a|grep x86_64) #yumBaseUrl=$(cat /etc/yum.repos.d/CentOS-Base.repo|grep baseurl=http|cut -d '=' -f 2|cut -d '$' -f 1|head -n 1) #[ "${yumBaseUrl}" ] && checkYumRepo=$(curl --connect-timeout 5 --head -s -o /dev/null -w %{http_code} ${yumBaseUrl}) #if [ "${checkYumRepo}" != "200" ] && [ "${SYS_TYPE}" ];then # curl -Ss --connect-timeout 3 -m 60 http://download.bt.cn/install/yumRepo_select.sh|bash #fi #尝试同步时间(从bt.cn) echo 'Synchronizing system time...' getBtTime=$(curl -sS --connect-timeout 3 -m 60 http://www.bt.cn/api/index/get_time) if [ "${getBtTime}" ];then date -s "$(date -d @$getBtTime +"%Y-%m-%d %H:%M:%S")" fi if [ -z "${Centos8Check}" ]; then yum install ntp -y rm -rf /etc/localtime ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime #尝试同步国际时间(从ntp服务器) ntpdate 0.asia.pool.ntp.org setenforce 0 fi startTime=`date +%s` sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config #yum remove -y python-requests python3-requests python-greenlet python3-greenlet yumPacks="libcurl-devel wget tar gcc make zip unzip openssl openssl-devel gcc libxml2 libxml2-devel libxslt* zlib zlib-devel libjpeg-devel libpng-devel libwebp libwebp-devel freetype freetype-devel lsof pcre pcre-devel vixie-cron crontabs icu libicu-devel c-ares libffi-devel bzip2-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel" yum install -y ${yumPacks} for yumPack in ${yumPacks} do rpmPack=$(rpm -q ${yumPack}) packCheck=$(echo ${rpmPack}|grep not) if [ "${packCheck}" ]; then yum install ${yumPack} -y fi done if [ -f "/usr/bin/dnf" ]; then dnf install -y redhat-rpm-config fi ALI_OS=$(cat /etc/redhat-release |grep "Alibaba Cloud Linux release 3") if [ -z "${ALI_OS}" ];then yum install epel-release -y fi } Install_Deb_Pack(){ ln -sf bash /bin/sh apt-get update -y apt-get install ruby -y apt-get install lsb-release -y #apt-get install ntp ntpdate -y #/etc/init.d/ntp stop #update-rc.d ntp remove #cat >>~/.profile<<EOF #TZ='Asia/Shanghai'; export TZ #EOF #rm -rf /etc/localtime #cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime #echo 'Synchronizing system time...' #ntpdate 0.asia.pool.ntp.org #apt-get upgrade -y debPacks="wget curl libcurl4-openssl-dev gcc make zip unzip tar openssl libssl-dev gcc libxml2 libxml2-dev zlib1g zlib1g-dev libjpeg-dev libpng-dev lsof libpcre3 libpcre3-dev cron net-tools swig build-essential libffi-dev libbz2-dev libncurses-dev libsqlite3-dev libreadline-dev tk-dev libgdbm-dev libdb-dev libdb++-dev libpcap-dev xz-utils git"; apt-get install -y $debPacks --force-yes for debPack in ${debPacks} do packCheck=$(dpkg -l ${debPack}) if [ "$?" -ne "0" ] ;then apt-get install -y $debPack fi done if [ ! -d '/etc/letsencrypt' ];then mkdir -p /etc/letsencryp mkdir -p /var/spool/cron if [ ! -f '/var/spool/cron/crontabs/root' ];then echo '' > /var/spool/cron/crontabs/root chmod 600 /var/spool/cron/crontabs/root fi fi } Get_Versions(){ redhat_version_file="/etc/redhat-release" deb_version_file="/etc/issue" if [ -f $redhat_version_file ];then os_type='el' is_aliyunos=$(cat $redhat_version_file|grep Aliyun) if [ "$is_aliyunos" != "" ];then return fi os_version=$(cat $redhat_version_file|grep CentOS|grep -Eo '([0-9]+\.)+[0-9]+'|grep -Eo '^[0-9]') if [ "${os_version}" = "5" ];then os_version="" fi if [ -z "${os_version}" ];then os_version=$(cat /etc/redhat-release |grep Stream|grep -oE 8) fi else os_type='ubuntu' os_version=$(cat $deb_version_file|grep Ubuntu|grep -Eo '([0-9]+\.)+[0-9]+'|grep -Eo '^[0-9]+') if [ "${os_version}" = "" ];then os_type='debian' os_version=$(cat $deb_version_file|grep Debian|grep -Eo '([0-9]+\.)+[0-9]+'|grep -Eo '[0-9]+') if [ "${os_version}" = "" ];then os_version=$(cat $deb_version_file|grep Debian|grep -Eo '[0-9]+') fi if [ "${os_version}" = "8" ];then os_version="" fi if [ "${is64bit}" = '32' ];then os_version="" fi else if [ "$os_version" = "14" ];then os_version="" fi if [ "$os_version" = "12" ];then os_version="" fi if [ "$os_version" = "19" ];then os_version="" fi if [ "$os_version" = "21" ];then os_version="" fi if [ "$os_version" = "20" ];then os_version2004=$(cat /etc/issue|grep 20.04) if [ -z "${os_version2004}" ];then os_version="" fi fi fi fi } Install_Python_Lib(){ curl -Ss --connect-timeout 3 -m 60 $download_Url/install/pip_select.sh|bash pyenv_path="/www/server/panel" if [ -f $pyenv_path/pyenv/bin/python ];then is_ssl=$($python_bin -c "import ssl" 2>&1|grep cannot) $pyenv_path/pyenv/bin/python3.7 -V if [ $? -eq 0 ] && [ -z "${is_ssl}" ];then chmod -R 700 $pyenv_path/pyenv/bin is_package=$($python_bin -m psutil 2>&1|grep package) if [ "$is_package" = "" ];then wget -O $pyenv_path/pyenv/pip.txt $download_Url/install/pyenv/pip.txt -T 5 $pyenv_path/pyenv/bin/pip install -U pip $pyenv_path/pyenv/bin/pip install -U setuptools $pyenv_path/pyenv/bin/pip install -r $pyenv_path/pyenv/pip.txt fi source $pyenv_path/pyenv/bin/activate return else rm -rf $pyenv_path/pyenv fi fi is_loongarch64=$(uname -a|grep loongarch64) if [ "$is_loongarch64" != "" ] && [ -f "/usr/bin/yum" ];then yumPacks="python3-devel python3-pip python3-psutil python3-gevent python3-pyOpenSSL python3-paramiko python3-flask python3-rsa python3-requests python3-six python3-websocket-client" yum install -y ${yumPacks} for yumPack in ${yumPacks} do rpmPack=$(rpm -q ${yumPack}) packCheck=$(echo ${rpmPack}|grep not) if [ "${packCheck}" ]; then yum install ${yumPack} -y fi done pip3 install -U pip pip3 install Pillow psutil pyinotify pycryptodome upyun oss2 pymysql qrcode qiniu redis pymongo Cython configparser cos-python-sdk-v5 supervisor gevent-websocket pyopenssl pip3 install flask==1.1.4 pip3 install Pillow -U pyenv_bin=/www/server/panel/pyenv/bin mkdir -p $pyenv_bin ln -sf /usr/local/bin/pip3 $pyenv_bin/pip ln -sf /usr/local/bin/pip3 $pyenv_bin/pip3 ln -sf /usr/local/bin/pip3 $pyenv_bin/pip3.7 if [ -f "/usr/bin/python3.7" ];then ln -sf /usr/bin/python3.7 $pyenv_bin/python ln -sf /usr/bin/python3.7 $pyenv_bin/python3 ln -sf /usr/bin/python3.7 $pyenv_bin/python3.7 elif [ -f "/usr/bin/python3.6" ]; then ln -sf /usr/bin/python3.6 $pyenv_bin/python ln -sf /usr/bin/python3.6 $pyenv_bin/python3 ln -sf /usr/bin/python3.6 $pyenv_bin/python3.7 fi echo > $pyenv_bin/activate return fi py_version="3.7.8" mkdir -p $pyenv_path echo "True" > /www/disk.pl if [ ! -w /www/disk.pl ];then Red_Error "ERROR: Install python env fielded." "ERROR: /www目录无法写入，请检查目录/用户/磁盘权限！" fi os_type='el' os_version='7' is_export_openssl=0 Get_Versions echo "OS: $os_type - $os_version" is_aarch64=$(uname -a|grep aarch64) if [ "$is_aarch64" != "" ];then is64bit="aarch64" fi if [ -f "/www/server/panel/pymake.pl" ];then os_version="" rm -f /www/server/panel/pymake.pl fi if [ "${os_version}" != "" ];then pyenv_file="/www/pyenv.tar.gz" wget -O $pyenv_file $download_Url/install/pyenv/pyenv-${os_type}${os_version}-x${is64bit}.tar.gz -T 10 tmp_size=$(du -b $pyenv_file|awk '{print $1}') if [ $tmp_size -lt 703460 ];then rm -f $pyenv_file echo "ERROR: Download python env fielded." else echo "Install python env..." tar zxvf $pyenv_file -C $pyenv_path/ > /dev/null chmod -R 700 $pyenv_path/pyenv/bin if [ ! -f $pyenv_path/pyenv/bin/python ];then rm -f $pyenv_file Red_Error "ERROR: Install python env fielded." "ERROR: 下载宝塔运行环境失败，请尝试重新安装！" fi $pyenv_path/pyenv/bin/python3.7 -V if [ $? -eq 0 ];then rm -f $pyenv_file ln -sf $pyenv_path/pyenv/bin/pip3.7 /usr/bin/btpip ln -sf $pyenv_path/pyenv/bin/python3.7 /usr/bin/btpython source $pyenv_path/pyenv/bin/activate return else rm -f $pyenv_file rm -rf $pyenv_path/pyenv fi fi fi cd /www python_src='/www/python_src.tar.xz' python_src_path="/www/Python-${py_version}" wget -O $python_src $download_Url/src/Python-${py_version}.tar.xz -T 5 tmp_size=$(du -b $python_src|awk '{print $1}') if [ $tmp_size -lt 10703460 ];then rm -f $python_src Red_Error "ERROR: Download python source code fielded." "ERROR: 下载宝塔运行环境失败，请尝试重新安装！" fi tar xvf $python_src rm -f $python_src cd $python_src_path ./configure --prefix=$pyenv_path/pyenv make -j$cpu_cpunt make install if [ ! -f $pyenv_path/pyenv/bin/python3.7 ];then rm -rf $python_src_path Red_Error "ERROR: Make python env fielded." "ERROR: 编译宝塔运行环境失败！" fi cd ~ rm -rf $python_src_path wget -O $pyenv_path/pyenv/bin/activate $download_Url/install/pyenv/activate.panel -T 5 wget -O $pyenv_path/pyenv/pip.txt $download_Url/install/pyenv/pip-3.7.8.txt -T 5 ln -sf $pyenv_path/pyenv/bin/pip3.7 $pyenv_path/pyenv/bin/pip ln -sf $pyenv_path/pyenv/bin/python3.7 $pyenv_path/pyenv/bin/python ln -sf $pyenv_path/pyenv/bin/pip3.7 /usr/bin/btpip ln -sf $pyenv_path/pyenv/bin/python3.7 /usr/bin/btpython chmod -R 700 $pyenv_path/pyenv/bin $pyenv_path/pyenv/bin/pip install -U pip $pyenv_path/pyenv/bin/pip install -U setuptools $pyenv_path/pyenv/bin/pip install -U wheel==0.34.2 $pyenv_path/pyenv/bin/pip install -r $pyenv_path/pyenv/pip.txt source $pyenv_path/pyenv/bin/activate is_gevent=$($python_bin -m gevent 2>&1|grep -oE package) is_psutil=$($python_bin -m psutil 2>&1|grep -oE package) if [ "${is_gevent}" != "${is_psutil}" ];then Red_Error "ERROR: psutil/gevent install failed!" fi } Install_Bt(){ panelPort="8888" if [ -f ${setup_path}/server/panel/data/port.pl ];then panelPort=$(cat ${setup_path}/server/panel/data/port.pl) fi mkdir -p ${setup_path}/server/panel/logs mkdir -p ${setup_path}/server/panel/vhost/apache mkdir -p ${setup_path}/server/panel/vhost/nginx mkdir -p ${setup_path}/server/panel/vhost/rewrite mkdir -p ${setup_path}/server/panel/install mkdir -p /www/server mkdir -p /www/wwwroot mkdir -p /www/wwwlogs mkdir -p /www/backup/database mkdir -p /www/backup/site if [ -f "/etc/init.d/bt" ]; then /etc/init.d/bt stop sleep 1 fi wget -O /etc/init.d/bt ${download_Url}/install/src/bt6.init -T 10 wget -O /www/server/panel/install/public.sh ${download_Url}/install/public.sh -T 10 wget -O panel.zip ${download_Url}/install/src/panel6.zip -T 10 if [ -f "${setup_path}/server/panel/data/default.db" ];then if [ -d "/${setup_path}/server/panel/old_data" ];then rm -rf ${setup_path}/server/panel/old_data fi mkdir -p ${setup_path}/server/panel/old_data d_format=$(date +"%Y%m%d_%H%M%S") \cp -arf ${setup_path}/server/panel/data/default.db ${setup_path}/server/panel/data/default_backup_${d_format}.db mv -f ${setup_path}/server/panel/data/default.db ${setup_path}/server/panel/old_data/default.db mv -f ${setup_path}/server/panel/data/system.db ${setup_path}/server/panel/old_data/system.db mv -f ${setup_path}/server/panel/data/port.pl ${setup_path}/server/panel/old_data/port.pl mv -f ${setup_path}/server/panel/data/admin_path.pl ${setup_path}/server/panel/old_data/admin_path.pl fi if [ ! -f "/usr/bin/unzip" ]; then if [ "${PM}" = "yum" ]; then yum install unzip -y elif [ "${PM}" = "apt-get" ]; then apt-get update apt-get install unzip -y fi fi unzip -o panel.zip -d ${setup_path}/server/ > /dev/null if [ -d "${setup_path}/server/panel/old_data" ];then mv -f ${setup_path}/server/panel/old_data/default.db ${setup_path}/server/panel/data/default.db mv -f ${setup_path}/server/panel/old_data/system.db ${setup_path}/server/panel/data/system.db mv -f ${setup_path}/server/panel/old_data/port.pl ${setup_path}/server/panel/data/port.pl mv -f ${setup_path}/server/panel/old_data/admin_path.pl ${setup_path}/server/panel/data/admin_path.pl if [ -d "/${setup_path}/server/panel/old_data" ];then rm -rf ${setup_path}/server/panel/old_data fi fi if [ ! -f ${setup_path}/server/panel/tools.py ] || [ ! -f ${setup_path}/server/panel/BT-Panel ];then ls -lh panel.zip Red_Error "ERROR: Failed to download, please try install again!" "ERROR: 下载宝塔失败，请尝试重新安装！" fi rm -f panel.zip rm -f ${setup_path}/server/panel/class/*.pyc rm -f ${setup_path}/server/panel/*.pyc chmod +x /etc/init.d/bt chmod -R 600 ${setup_path}/server/panel chmod -R +x ${setup_path}/server/panel/script ln -sf /etc/init.d/bt /usr/bin/bt echo "${panelPort}" > ${setup_path}/server/panel/data/port.pl wget -O /etc/init.d/bt ${download_Url}/install/src/bt7.init -T 10 wget -O /www/server/panel/init.sh ${download_Url}/install/src/bt7.init -T 10 wget -O /www/server/panel/data/softList.conf ${download_Url}/install/conf/softList.conf } Set_Bt_Panel(){ Run_User="www" wwwUser=$(cat /etc/passwd|grep www) if [ "${wwwUser}" == "" ];then groupadd ${Run_User} useradd -s /sbin/nologin -g ${Run_User} ${Run_User} fi password=$(cat /dev/urandom | head -n 16 | md5sum | head -c 8) sleep 1 admin_auth="/www/server/panel/data/admin_path.pl" if [ ! -f ${admin_auth} ];then auth_path=$(cat /dev/urandom | head -n 16 | md5sum | head -c 8) echo "/${auth_path}" > ${admin_auth} fi auth_path=$(cat ${admin_auth}) cd ${setup_path}/server/panel/ /etc/init.d/bt start $python_bin -m py_compile tools.py $python_bin tools.py username username=$($python_bin tools.py panel ${password}) cd ~ echo "${password}" > ${setup_path}/server/panel/default.pl chmod 600 ${setup_path}/server/panel/default.pl sleep 3 /etc/init.d/bt restart sleep 3 isStart=$(ps aux |grep 'BT-Panel'|grep -v grep|awk '{print $2}') LOCAL_CURL=$(curl 127.0.0.1:8888/login 2>&1 |grep -i html) if [ -z "${isStart}" ] && [ -z "${LOCAL_CURL}" ];then /etc/init.d/bt 22 cd /www/server/panel/pyenv/bin touch t.pl ls -al python3.7 python lsattr python3.7 python Red_Error "ERROR: The BT-Panel service startup failed." "ERROR: 宝塔启动失败" fi } Set_Firewall(){ sshPort=$(cat /etc/ssh/sshd_config | grep 'Port '|awk '{print $2}') if [ "${PM}" = "apt-get" ]; then apt-get install -y ufw if [ -f "/usr/sbin/ufw" ];then ufw allow 20/tcp ufw allow 21/tcp ufw allow 22/tcp ufw allow 80/tcp ufw allow 888/tcp ufw allow ${panelPort}/tcp ufw allow ${sshPort}/tcp ufw allow 39000:40000/tcp ufw_status=`ufw status` echo y|ufw enable ufw default deny ufw reload fi else if [ -f "/etc/init.d/iptables" ];then iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 20 -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 21 -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ${panelPort} -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ${sshPort} -j ACCEPT iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 39000:40000 -j ACCEPT #iptables -I INPUT -p tcp -m state --state NEW -m udp --dport 39000:40000 -j ACCEPT iptables -A INPUT -p icmp --icmp-type any -j ACCEPT iptables -A INPUT -s localhost -d localhost -j ACCEPT iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -P INPUT DROP service iptables save sed -i "s#IPTABLES_MODULES=\"\"#IPTABLES_MODULES=\"ip_conntrack_netbios_ns ip_conntrack_ftp ip_nat_ftp\"#" /etc/sysconfig/iptables-config iptables_status=$(service iptables status | grep 'not running') if [ "${iptables_status}" == '' ];then service iptables restart fi else AliyunCheck=$(cat /etc/redhat-release|grep "Aliyun Linux") [ "${AliyunCheck}" ] && return yum install firewalld -y [ "${Centos8Check}" ] && yum reinstall python3-six -y systemctl enable firewalld systemctl start firewalld firewall-cmd --set-default-zone=public > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=20/tcp > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=21/tcp > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=22/tcp > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=80/tcp > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=${panelPort}/tcp > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=${sshPort}/tcp > /dev/null 2>&1 firewall-cmd --permanent --zone=public --add-port=39000-40000/tcp > /dev/null 2>&1 #firewall-cmd --permanent --zone=public --add-port=39000-40000/udp > /dev/null 2>&1 firewall-cmd --reload fi fi } Get_Ip_Address(){ getIpAddress="" getIpAddress=$(curl -sS --connect-timeout 10 -m 60 https://www.bt.cn/Api/getIpAddress) if [ -z "${getIpAddress}" ] || [ "${getIpAddress}" = "0.0.0.0" ]; then isHosts=$(cat /etc/hosts|grep 'www.bt.cn') if [ -z "${isHosts}" ];then echo "" >> /etc/hosts echo "116.213.43.206 www.bt.cn" >> /etc/hosts getIpAddress=$(curl -sS --connect-timeout 10 -m 60 https://www.bt.cn/Api/getIpAddress) if [ -z "${getIpAddress}" ];then sed -i "/bt.cn/d" /etc/hosts fi fi fi ipv4Check=$($python_bin -c "import re; print(re.match('^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$','${getIpAddress}'))") if [ "${ipv4Check}" == "None" ];then ipv6Address=$(echo ${getIpAddress}|tr -d "[]") ipv6Check=$($python_bin -c "import re; print(re.match('^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$','${ipv6Address}'))") if [ "${ipv6Check}" == "None" ]; then getIpAddress="SERVER_IP" else echo "True" > ${setup_path}/server/panel/data/ipv6.pl sleep 1 /etc/init.d/bt restart fi fi if [ "${getIpAddress}" != "SERVER_IP" ];then echo "${getIpAddress}" > ${setup_path}/server/panel/data/iplist.txt fi LOCAL_IP=$(ip addr | grep -E -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -E -v "^127\.|^255\.|^0\." | head -n 1) } Setup_Count(){ curl -sS --connect-timeout 10 -m 60 https://www.bt.cn/Api/SetupCount?type=Linux\&o=$1 > /dev/null 2>&1 if [ "$1" != "" ];then echo $1 > /www/server/panel/data/o.pl cd /www/server/panel $python_bin tools.py o fi echo /www > /var/bt_setupPath.conf } Install_Main(){ startTime=`date +%s` Lock_Clear System_Check Get_Pack_Manager get_node_url MEM_TOTAL=$(free -g|grep Mem|awk '{print $2}') if [ "${MEM_TOTAL}" -le "1" ];then Auto_Swap fi if [ "${PM}" = "yum" ]; then Install_RPM_Pack elif [ "${PM}" = "apt-get" ]; then Install_Deb_Pack fi Install_Python_Lib Install_Bt Set_Bt_Panel Service_Add Set_Firewall Get_Ip_Address Setup_Count ${IDC_CODE} } echo " +---------------------------------------------------------------------- | Bt-WebPanel FOR CentOS/Ubuntu/Debian +---------------------------------------------------------------------- | Copyright © 2015-2099 BT-SOFT(http://www.bt.cn) All rights reserved. +---------------------------------------------------------------------- | The WebPanel URL will be http://SERVER_IP:8888 when installed. +---------------------------------------------------------------------- " while [ "$go" != 'y' ] && [ "$go" != 'n' ] do read -p "Do you want to install Bt-Panel to the $setup_path directory now?(y/n): " go; done if [ "$go" == 'n' ];then exit; fi Install_Main echo > /www/server/panel/data/bind.pl echo -e "==================================================================" echo -e "\033[32mCongratulations! Installed successfully!\033[0m" echo -e "==================================================================" echo "外网面板地址: http://${getIpAddress}:${panelPort}${auth_path}" echo "内网面板地址: http://${LOCAL_IP}:${panelPort}${auth_path}" echo -e "username: $username" echo -e "password: $password" echo -e "\033[33mIf you cannot access the panel,\033[0m" echo -e "\033[33mrelease the following panel port [${panelPort}] in the security group\033[0m" echo -e "\033[33m若无法访问面板，请检查防火墙/安全组是否有放行面板[${panelPort}]端口\033[0m" echo -e "==================================================================" endTime=`date +%s` ((outTime=($endTime-$startTime)/60)) echo -e "Time consumed:\033[32m $outTime \033[0mMinute!"
1.编写启动docker宝塔面板脚本以下终端命令，在docker服务启动后执行，可以启动容器内 宝塔服务 , bt-centos 为含有宝塔的docker 容器名 。这两行命令保存为 starng.sh ，且存放在 /volume1/docker/mx_baota/starng.sh 路径下，在 群晖管理界面 的 File Station 路径为 /docker/mx_baota/starng.shdocker exec bt-centos /etc/init.d/bt start docker exec bt-centos /etc/init.d/nginx start2.添加群晖计划任务控制面板 > 计划任务 > 新增 > 触发的任务 > 用户定义的脚本打开控制面板、计划任务新增计划任务用户账号必须选择 root （否则权限不足），事件选择 开机 新增计划任务勾选并填写邮箱，可以发送运行结果sleep 30 sh /volume1/docker/mx_baota/starng.sh
1.从git上下载nginx-rtmp模块git clone https://github.com/arut/nginx-rtmp-module.git{alert type="error"}注意： 千万不要 先在windows平台下载rtmp模块文件，然后打包迁移到linux系统。否则文件编码格式将会被改变，怎么安装都不会成功。会出现错误提示：unknown directive "rtmp" {/alert}若没有安装git和gcc编译环境apt install -y gcc gcc-c++ autoconf wget apt -y install wget gcc-c++ ncurses ncurses-devel cmake make perl bison openssl openssl-devel gcc* libxml2 libxml2-devel curl-devel libjpeg* libpng* freetype*apt install -y git2.编译安装nginx时添加nginx-rtmp模块从宝塔中安装nginx中安装，选择编译安装，会出现自定义模块界面，点击添加，在弹出的界面输入：{alert type="error"}模块名称： nginx_rtmp_module 描述： nginx rtmp 参数： –add-module=/www/server/nginx-rtmp-module {/alert}验证：看到 --add-module=/allroot/programs/nginx-rtmp-module 另一种安装方式：修改 /www/server/panel/install/nginx.sh 安装命令，需要先用宝塔执行过编译安装命令后才会有该文件/www/server/panel/install然后执行安装命令sh /www/server/panel/install/nginx.sh install 1.203.修改nginx.conf配置rtmp_auto_push on; rtmp { server { listen 1935; #监听端口，记得开放 ping 30s; chunk_size 4000; notify_method get; application hls {#rtmp推流请求路径 live on; hls on; hls_path /www/server/nginx/hls; #视频流暂存地址 hls_sync 100ms; hls_fragment 5s; #切片大小，越小占用资源越高，但是延时越小，默认5s } application live { live on; } # Video on demand #application vod { # play /www/server/nginx/Videos; #} # Video on demand over HTTP #application vod_http { # play http://localhost:8080/vod/; #} } }#rtmp状态 location /stat { rtmp_stat all; rtmp_stat_stylesheet stat.xsl; } location /stat.xsl { #rtmp-module模块安装地址，这个可以通过http看到状态 root /allroot/programs/nginx-rtmp-module; } #http支持hls流播放 location /hls { #Serve HLS config types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; } root /allroot/programs/live/hls; #与视频流暂存地址相同 expires -1; add_header Cache-Control no-cache; } 4.测hi推流ffmpeg -re -i test.flv -vcodec copy -acodec copy -f flv rtmp://10.163.102.157:1936/hls/test点播模型rtmp { server { listen 1935; #//服务端口 chunk_size 4096; #//数据传输块的大小 application video { play /usr/local/data/video; #//视频文件存放位置，访问方式rtmp://localhost:1935/video } } }5.直播回放rtmp { server { listen 1935; chunk_size 4096; application video { play /usr/local/data/video; } application live { live on;#直播模式 hls on; #这个参数把直播服务器改造成实时回放服务器。 wait_key on; #对视频切片进行保护，这样就不会产生马赛克了。 hls_path /usr/local/data/hls; #切片视频文件存放位置。 hls_fragment 10s; #每个视频切片的时长。 hls_playlist_length 60s; #总共可以回看的事件，这里设置的是1分钟。 hls_continuous on; #连续模式。 hls_cleanup on; #对多余的切片进行删除。 hls_nested on; #嵌套模式。 } }
stream { # 添加socket转发的代理 upstream socket_proxy { hash $remote_addr consistent; # 转发的目的地址和端口 server 192.168.1.100:9000 weight=5 max_fails=3 fail_timeout=30s; } # 提供转发的服务，即访问localhost:9001，会跳转至代理socket_proxy指定的转发地址 server { listen 9001; proxy_connect_timeout 1s; proxy_timeout 3s; proxy_pass socket_proxy; } }