资讯动态

Linux服务器一键安装JDK、MySQL、Redis、Nginx的最佳实践

发布时间:2026/10/21 22:10:40 来源:尧图企业网站定制
简介Linux服务器环境搭建中JDK、MySQL、Redis、Nginx是Web服务常用基础组件但手动安装配置繁琐。这份资源面向Linux运维与后端开发者提供一键式自动化部署方案通过shell脚本串联下载、解压、配置、启动快速完成整套环境初始化。压缩包共27个文件约930.56MB以sh安装脚本、gz/tar软件源码包、cnf/conf配置文件及rpm依赖包为主覆盖JDK 8u201、MySQL 8.0.30、Redis 6.2.4、Nginx 1.20.1并附带gcc、perl、zlib、openssl、pcre等编译依赖以及密码重置、安全初始化等实用脚本。整个部署过程涉及环境变量设置、MySQL安全优化、Redis访问控制、Nginx配置校验等关键细节并给出systemd单元文件便于服务管理和开机自启资源目录按组件拆分便于按需检索与复用。适合希望减少重复劳动、快速获得可运行环境的用户已有298人学习下载脚本化部署思路与配置细节值得参考。1. 为什么我不再手动装这四个组件给一台新的 Linux 服务器做基础环境JDK、MySQL、Redis、Nginx 这四个组件基本是绕不开的。手动装我也干过最快也要两个小时慢的时候光在 JDK 下载页里挑版本、找对应系统架构就能耗掉半小时。后来我把流程简化成一条一键式安装脚本跑完一遍JDK、MySQL、Redis、Nginx 全部就位并且该有的自启动和密码策略都给你配好。这篇笔记适合两类人一类是刚拿到云服务器、项目又急着联调的开发者另一类是反复交付环境、不想每次都重新踩坑的运维。我不会告诉你所有参数都是一种答案只会把我在真实环境里验证过的那套选择逻辑、安装顺序和报错处理写出来。脚本会保留日志跑挂了能看出死在哪一步。2. 环境准备先定版本再动手这四个组件怎么选一键安装脚本不能无脑执行第一步要先看清服务器的底子。我的习惯是装任何组件之前先把操作系统版本和 CPU 架构写进安装清单里后面下载软件包、选 yum 源就不会张冠李戴。2.1 先确认操作系统和 CPU 架构打开终端先执行这么两条命令cat /etc/os-release uname -m第一行会输出发行版的信息比如 CentOS、Rocky Linux、AlmaLinux、Ubuntu第二行输出 CPU 架构x86_64代表 Intel/AMD 64 位aarch64代表 ARM 64 位。后面所有软件包的下载地址都依赖这两个结果选错的话要么直接运行报错要么装完java -version显示 Illegal instruction。如果你的环境是 Ubuntu我的脚本里所有yum都要换成aptMySQL 和 Nginx 的仓库配置方式也不同。下面的安装流程以 CentOS/Rocky 体系为主Ubuntu 用户对照着改包管理器就行。提示云服务器尤其是 ARM 实例MySQL 和 Redis 的源码包通常需要自己编译yum 源里不一定有现成的 aarch64 包。2.2 JDK 版本默认 OpenJDK 8给 11 和 17 留好开关选 JDK 版本天天打架的问题其实是“项目跑在哪个版本上”。如果是维护老项目Spring Boot 2.x、绝大多数大数据组件都依赖 Java 8如果是全新项目上 Spring Boot 3那就直接上 JDK 17。最怕的是生产环境一半 8、一半 17一键脚本里不做版本区分的话后面改起来很痛苦。我给的脚本默认安装 OpenJDK 8原因很简单Java 8 的兼容面最广Tomcat、Hadoop、Zookeeper 这些老家伙都认它。需要升级时把脚本里的版本变量改成11或17其余逻辑基本不用动。参考选型表场景推荐 JDK说明Spring Boot 2.x / Hadoop / 老项目OpenJDK 8资源占用低生态兼容最好新业务 Modulith / JDK 新特性OpenJDK 11中间过渡版本Spring Boot 3.x / GraalVMOpenJDK 17LTS长期维护不要同时往一个系统里塞多个 JDK 版本除非你愿意处理alternatives的麻烦。后面第 3 章的脚本会有专门的awk解析路径避免用户装完发现JAVA_HOME指向空目录。2.3 MySQL用官方 yum 源别用系统自带的 MariaDB很多 Linux 发行版默认装了 MariaDB它和 MySQL 命令兼容但初始化方式、密码插件都不一样。一键脚本里我会先卸载 MariaDB再装 MySQL 官方 yum 源。MySQL 8.0 是目前的主流5.7 已经进入生命末期新环境我建议直接上 8.0。版本适用情况初始密码机制MySQL 8.0新项目、新架构安装后自动生成临时密码必须解密再改MySQL 5.7老系统兼容安装后自动生成临时密码机制类似MariaDB极简环境、已有数据一般不产生临时密码脚本里选择 MySQL 8.0 还有一个原因官方 yum 源会自动带上libaio、net-tools这些依赖源码装的话这些坑要自己一个一个踩。2.4 Redis 和 NginxRedis 选编译Nginx 选 yumRedis 用发行版自带的包管理安装版本通常会落后主版本一两年而且/etc/redis.conf的默认配置改得比较保守。我会选择源码编译 Redis 7.x耗时不超过三分钟关键是编译参数可控制比如路径、TLS 支持。Nginx 则不必源码编译除非你需要http_realip_module、kafka模块这些自定义能力普通反向代理、静态资源服务用官方 yum 源安装即可。我常用的组合是组件安装方式理由配置文件Redis 7.0源码 make install版本可控systemd 托管不依赖发行版服务/etc/redis/6379.confNginx 1.24官方 yum 源稳定、有动态模块目录/etc/nginx/nginx.conf这套组合在我的测试环境里跑了大半年升级维护都不费劲。接下来第 3 章就按这个选型写安装脚本。3. 一键安装脚本JDK、MySQL、Redis、Nginx 的顺序不能乱我见过最“暴力”的一键脚本就是拿一堆yum install平铺出来一旦中途失败后面继续跑最后你根本不知道哪个装上了。真正的运维脚本要有日志、有错误退出、有关键步骤的回显顺序也要讲究。3.1 脚本骨架先定义日志和错误终止我习惯在脚本开头放四个关键变量和两个函数所有后续函数都依赖它们#!/bin/bash set -e BASE_DIR/opt/install LOG_FILE/var/log/env_install.log MYSQL_ROOT_PWDMysql2024 REDIS_PWDRedis2024 export JAVA_HOME exec 2${LOG_FILE} info() { echo [INFO] $(date %F %T) $*; } err() { echo [ERROR] $(date %F %T) $*; exit 1; }set -e表示遇到任何非零退出码直接终止脚本这样不会出现“MySQL 装挂了 Nginx 还在配”的假成功exec 2把标准错误全部追加到日志文件排错时不用重新拷终端。MYSQL_ROOT_PWD和REDIS_PWD是两个需要你提前手改的变量我会在配置阶段用到它们。注意set -e也有副作用。比如某个服务 stop 后再 startStop 返回非零就会中断所以关键命令执行后要顺手接|| true或者判断退出码。3.2 JDK 安装函数yum 方式加 profile.d 配置JDK 的安装函数我这么写install_jdk() { local jdk_version$1 if command -v java /dev/null 21; then info JDK already installed: $(java -version 21 | head -1) return fi yum install -y java-${jdk_version}-openjdk-devel JAVA_HOME$(readlink -f $(command -v javac) | sed s#/bin/javac##) cat /etc/profile.d/jdk.sh EOF export JAVA_HOME${JAVA_HOME} export PATH\$JAVA_HOME/bin:\$PATH EOF source /etc/profile.d/jdk.sh java -version || err JDK install failed }函数接受一个参数8、11或17。command -v java判断是否已经装过避免重复安装readlink -f把javac的软链解析成真实路径因为 CentOS 里 OpenJDK 的JAVA_HOME藏在/usr/lib/jvm/java-1.8.0-openjdk-...下。sed去掉末尾的/bin/javac剩下的就是干净的JAVA_HOME。写到/etc/profile.d/jdk.sh的好处是登录即生效不用去手工 source/etc/profile。最后java -version验证失败直接退出。3.3 MySQL 安装函数先卸干净再装官方源我在脚本里把 MySQL 的安装拆成三个动作清理旧包、配置官方源、初始化密码。install_mysql() { yum remove -y mariadb* 2/dev/null || true rpm -Uvh https://repo.mysql.com/mysql80-community-release-el${RELEASE_VER}-3.noarch.rpm yum install -y mysql-community-server systemctl enable --now mysqld INIT_PWD$(grep temporary password /var/log/mysqld.log | awk {print $NF}) mysql -uroot -p${INIT_PWD} --connect-expired-password -e \ ALTER USER rootlocalhost IDENTIFIED BY ${MYSQL_ROOT_PWD}; info MySQL root password changed }注意RELEASE_VER变量要提前根据/etc/os-release设置CentOS 7 填7Rocky 8 填8。卸载 MariaDB 时用|| true因为有些镜像根本没装 MariaDB返回非零不该中断整个脚本。rpm -Uvh装的是 MySQL 官方 yum 源之后yum install会从官方源拉包。MySQL 启动后默认会在/var/log/mysqld.log里生成临时 root 密码我用awk {print $NF}取最后一列。密码里可能包含特殊字符所以-p和密码之间不加空格并且用双引号包裹。--connect-expired-password很重要不加上它会直接报You must reset your password。3.4 Redis 安装函数编译到指定目录不污染 binRedis 用源码编译函数如下install_redis() { if [ ! -f /usr/local/redis/bin/redis-server ]; then yum install -y gcc make tcl cd /usr/local/src tar xzf redis-7.0.12.tar.gz cd redis-7.0.12 make -j$(nproc) make install PREFIX/usr/local/redis fi useradd -r -s /sbin/nologin redis 2/dev/null || true mkdir -p /etc/redis /var/lib/redis chown redis:redis /var/lib/redis cp redis.conf /etc/redis/6379.conf sed -i s/^# requirepass foobared/requirepass ${REDIS_PWD}/ /etc/redis/6379.conf sed -i s/^dir .*/dir \/var\/lib\/redis/ /etc/redis/6379.conf sed -i s/^appendonly no/appendonly yes/ /etc/redis/6379.conf sed -i s/^daemonize yes/daemonize no/ /etc/redis/6379.conf cat /etc/systemd/system/redis.service EOF [Unit] DescriptionRedis 7.0.12 server Afternetwork.target [Service] Userredis Groupredis ExecStart/usr/local/redis/bin/redis-server /etc/redis/6379.conf ExecStop/usr/local/redis/bin/redis-cli -a Redis2024 shutdown Restartalways RestartSec5 [Install] WantedBymulti-user.target EOF systemctl daemon-reload systemctl enable --now redis }这里说四个最容易被忽略的参数daemonize no是为 systemd 准备的如果保持yessystemd 会认为主进程退出直接给你标记为 faileddir /var/lib/redis修改 RDB 持久化文件落盘目录默认/root会造成 Redis 进程跑在 redis 用户下时没有写权限appendonly yes开启 AOF生产环境必备Userredis改用普通用户运行防止 Redis 被注入攻击后直接拿到 root 权限。3.5 Nginx 安装函数官方 yum 源最省心Nginx 不走编译我用官方 yum 源install_nginx() { cat /etc/yum.repos.d/nginx.repo EOF [nginx-stable] namenginx stable repo baseurlhttp://nginx.org/packages/centos/\$releasever/\$basearch/ gpgcheck1 enabled1 gpgkeyhttps://nginx.org/keys/nginx_signing.key EOF yum install -y nginx systemctl enable --now nginx }heredoc 里我故意保留了\$releasever和\$basearch目的是让 yum 在运行时自己去展开而不是在写文件时就被替换成空字符串。gpgcheck1开启签名检查防止源被篡改。如果你需要编译安装 Nginx那就在./configure时把--prefix/usr/local/nginx--with-http_ssl_module都带上并把make install后的二进制链接进/usr/local/bin否则 systemd ExecStart 路径要自己改。四个组件按这个顺序执行JDK 在最前面因为 Redis 编译依赖 gcc、Java 项目联调也依赖 JDKMySQL 其次初始化需要等待Redis 与 Nginx 放后面它们不依赖前面两个。如果你有数据库备份恢复需求MySQL 要放在最后再恢复数据第一步最好先初始化密码。4. 配置调优四个服务装完别急着交出去装完只是第一步真正让你“看起来懂运维”的是配置细节。这一章我会把四个服务串起来至少要能让 Java 应用连上 MySQL、通过 Redis 缓存、再被 Nginx 反向代理。4.1 MySQL改 root 密码后立刻处理远程访问默认 MySQL 只监听127.0.0.1远程客户端连不上。我现在习惯把bind-address改成0.0.0.0但你得知道这意味着什么防火墙和账号权限必须同时收紧。[mysqld] bind-address0.0.0.0 port3306 character-set-serverutf8mb4 collation-serverutf8mb4_general_ci default-authentication-pluginmysql_native_passworddefault-authentication-plugin这行值得说。MySQL 8.0 默认的caching_sha2_password很多老版本客户端不支持如果你的 Java 驱动是 5.x会出现 Authentication plugin 报错Java 8 以上驱动没问题但运维环境里尽量兼容我会在测试时确认驱动再决定要不要这一行。远程账号必须在 MySQL 里单独创建不要直接用 root 开放远程CREATE USER app% IDENTIFIED BY App2024; GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.* TO app%; FLUSH PRIVILEGES;%表示任意主机当然这只是测试环境写法。生产上应该写成能访问的应用服务器 IP比如app192.168.1.%。授权粒度也不需要给ALL PRIVILEGES哪怕要备份也建议单独建一个备份账号只授SELECT和LOCK TABLES。4.2 Redis密码、持久化、内存上限一次配完我给出的 Redis 配置在/etc/redis/6379.conf上做三处调整requirepass Redis2024 appendonly yes maxmemory 2gb maxmemory-policy allkeys-lrurequirepass是访问密码不配的话任何人连上 6379 就能flushall。maxmemory要结合服务器物理内存来定我给的是 2GB 示例maxmemory-policy allkeys-lru是内存满了以后自动淘汰最久没用的 key适合缓存场景。如果你把 Redis 当消息队列用这条要改noeviction否则消息会悄悄丢。AOF 开启后记得在日志里观察aof_last_bgrewrite_status。老版本 Redis 的 AOF 重写偶尔会因为内存不足失败现象是磁盘文件越来越大重启后恢复特别慢。解决方案除了加大maxmemory还要给系统留出rewrite时 fork 子进程的内存余量。4.3 Nginx用最精简的配置把 Java 应用代理出来Nginx 最常见的用法就是反代后面的 Java 进程server { listen 80; server_name demo.example.com; 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_connect_timeout 5s; } location /static/ { alias /data/www/static/; expires 7d; } }proxy_pass后面可以是 IP:端口也可以是一个 upstream 组名配了 upstream 后这里填http://backend_server。Host头必须透传否则后端拿不到真实域名很多 Java 框架里用request.getServerName()会出错。alias和root是有区别的alias会把/static/映射到/data/www/static/root则会拼接成/data/www/static/static/这个坑我在交付时撞过不止一次。改完nginx.conf先执行nginx -t检查输出syntax is ok之后再systemctl reload nginx。千万别直接restart生产环境 reload 平滑切换restart 会瞬间断掉所有连接。4.4 开机自启和防火墙最后一步决定稳定性用 systemd 的机器四个服务都要 enablefor svc in mysqld redis nginx; do systemctl enable $svc doneJDK 不需要 systemd 服务它是基础环境。然后是防火墙CentOS 7 以上默认firewalld有名你要放行这三个端口firewall-cmd --permanent --add-port80/tcp firewall-cmd --permanent --add-port3306/tcp firewall-cmd --permanent --add-port6379/tcp firewall-cmd --reloadRedis 和 MySQL 端口如果只给内网调用建议只对网段放行不要对全世界开。SELinux 开启的状态下Nginx 反代会出现 502因为httpd_can_network_connect策略默认关闭。可以用setsebool -P httpd_can_network_connect1持久化放行别一上来就setenforce 0那等于把安全策略全关了。5. 常见问题与避坑排查装完跑不起来的五个真实场景部署最怕的就是按教程装完结果服务一个都起不来。下面五条都是我实际踩过的坑每一条都会先写现象再分析原因最后给解决方式。5.1 Nginx 启动报 Address already in use现象systemctl start nginx提示bind() to 0.0.0.0:80 failed (98: Address already in use)然后服务进入 failed 状态。原因80 端口被别的进程占用了。常见元凶是系统自带的 Apachehttpd或者你已经用nginx -c手动启动过一个实例systemd 再拉一个就撞车。解决先找到占用方ss -lntp | grep :80看到 PID 后ps -p PID -o cmd确认是哪个进程。如果是httpd直接systemctl stop httpd systemctl disable httpd如果是你自己手动启的 nginxnginx -s stop停掉再让 systemd 接管。排查完重新systemctl start nginx。5.2 java -version 显示的版本和装的不一样现象脚本里明明装了 OpenJDK 8重启终端后输入java -version却显示 1.7 或 1.6。原因/etc/profile.d里的 JDK 配置没生效或者系统里存在alternatives默认指向的旧版本。CentOS/RHEL 的alternatives框架会把java、javac软链到/usr/bin优先级高的旧版本占了位置。解决强制切换 alternative 指向alternatives --set java /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.282.b08-1.el7_9.x86_64/bin/java alternatives --set javac /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.282.b08-1.el7_9.x86_64/bin/javac source /etc/profile.d/jdk.sh java -version路径要以实际readlink -f $(which javac)结果为准别照抄。如果你是新开的终端还是老版本看一下/etc/profile.d/jdk.sh里JAVA_HOME的路径是否存在很多老教程把路径写死成/usr/lib/jvm/java-1.8.0但实际目录名称带.x86_64后缀导致 PATH 变量设成了一个不存在的位置。5.3 MySQL 初始化失败mysqld.log 里没有临时密码现象systemctl start mysqld后/var/log/mysqld.log中找不到temporary password那一行mysql -uroot -p怎么试都登录不了。原因两种常见可能一是datadir指向目录权限不对MySQL 初始化根本没跑完二是/var/lib/mysql之前已被 MariaDB 或老 MySQL 初始化过新的 mysqld 检测到数据目录已存在就不会再次初始化。解决先看错误日志tail -80 /var/log/mysqld.log如果看见[ERROR] failed to set datadir to /var/lib/mysql或者Permission denied执行chown -R mysql:mysql /var/lib/mysql如果日志显示mysqld: File ./mysql-ibd文件已存在说明是个半残的旧数据目录。确认里面没有你要保留的数据库之后把目录备份一下再重新初始化mv /var/lib/mysql /var/lib/mysql.bak_$(date %F) mkdir /var/lib/mysql chown mysql:mysql /var/lib/mysql mysqld --initialize-insecure --usermysql--initialize-insecure会生成一个无需密码的 root 账号启动后立刻mysql -uroot进去改密码。这种处理只适合全新环境已有业务数据的库千万别这么干。5.4 Redis 启动后立刻退出systemd 状态一直是 failed现象systemctl start redis执行后没有任何报错但systemctl status redis显示active (running)几秒后又变 failedredis-cli ping失败。原因最常见是daemonize yes和 systemd 的冲突。Redis 在 daemon 模式下会 fork 一个子进程然后父进程主动退出systemd 根据 PID 判断主进程已经退出就把服务标记为失败并执行停止。另一个高频原因是vm.overcommit_memory0Redis 在启动时申请内存失败。解决确认配置文件里的daemonize必须为no。再执行sysctl vm.overcommit_memory1 echo vm.overcommit_memory1 /etc/sysctl.conf systemctl restart redisovercommit_memory1允许内核在没有足够物理内存时也接受 Redis 的申请对 Redis 这种按需分配内存的场景是常见配置调优。改完 sysctl 要持久化不然重启又打回原形。5.5 Nginx 返回 403 Forbidden但配置文件看起来没问题现象Nginx 已启动curl http://127.0.0.1输出 403error.log里出现directory index of /data/www/ is forbidden。原因Nginx 的 worker 进程以nginx用户运行而/data/www目录的权限是 750 且 owner 是 root。nginx用户没有x权限进入不了目录自然读不到 index.html。这也是很多新手在 VPS 上遇到 403 的真凶。解决调整目录权限chown -R nginx:nginx /data/www chmod 755 /data/www如果根目录定位需求并不想给nginx用户全部权限也可以给目录设置ox。另外还要看index配置是否包含需要的文件location / {}里没有index index.html;而目录下只有index.htm同样会 403。这些坑有个共同点服务启动成功的表象背后权限、端口、systemd 语义只要有一处对不上就翻车。每改一个参数都要用第 6 章的验证方式再跑一遍不要攒到凌晨再一起排查。6. 验证四件套是否跑通一条命令看懂全部状态我做完环境交付之前一定会跑一遍检测脚本而不是单纯systemctl status。因为 status 显示的 active 只能说明进程在不能说明端口通、密码可用。6.1 最省事的四合一验证命令把下面这段存成env_check.sh放到任意目录执行#!/bin/bash MYSQL_PWD${MYSQL_ROOT_PWD:-Mysql2024} REDIS_PWD${REDIS_PWD:-Redis2024} echo JDK java -version 21 | head -1 echo MySQL mysql -uroot -p${MYSQL_PWD} -e SELECT VERSION(); 2/dev/null || echo MySQL login failed echo Redis redis-cli -a ${REDIS_PWD} ping 2/dev/null || echo Redis ping failed echo Nginx curl -sI http://127.0.0.1 | head -1 echo Ports ss -lntp | grep -E :(3306|6379|80)\b脚本里的密码从环境变量读避免硬编码泄露。MySQL 验证走真实 SQL 查询Redis 走pingNginx 走 HTTP 响应头JDK 走java -version。四个输出全部正常基本可以放心交付。6.2 功能级验证让数据真正写一遍进程检查不放心我会再做一次业务级的冒烟测试。MySQL 里建一张临时表插入再删除CREATE DATABASE IF NOT EXISTS smoke_test; USE smoke_test; CREATE TABLE t_hello(id INT PRIMARY KEY auto_increment, msg VARCHAR(32)); INSERT INTO t_hello(msg) VALUES (ok); SELECT msg FROM t_hello WHERE id1; DROP DATABASE smoke_test;Redis 侧就是最经典的 set/getredis-cli -a ${REDIS_PWD} set smoke_key ok /dev/null redis-cli -a ${REDIS_PWD} get smoke_key redis-cli -a ${REDIS_PWD} del smoke_keyNginx 用一个后端代理测试先起一个能响应 8080 端口的简单 Java 进程然后curl http://127.0.0.1/health看返回内容是不是来自 8080 那个进程。这一步能同时验证 Nginx 配置和 JDK 环境是最划算的一步测试。从那以后我每次交付新环境都会把这套检查脚本放进部署流水线的前置环节十分钟跑完四件套的版本、端口、登录态全部留痕。尤其是ss -lntp的输出会单独存档哪天线上端口被占翻历史记录就能快速定位。装环境这事看着玄学真把验证步骤固化下来稳定性就出来了。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑