ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Linux服务器四件套一键安装:JDK、MySQL、Redis、Nginx

Linux服务器四件套一键安装:JDK、MySQL、Redis、Nginx 简介一份面向Linux运维与后端开发者的自动化部署资源整合JDK、MySQL、Redis、Nginx四大组件的安装、配置与启动脚本。适合需要快速搭建开发或测试环境、希望降低手工编译配置成本的中级运维人员也适合初学者对照脚本理解组件安装流程。资源共27个文件以shell脚本和源码压缩包为主另含conf/cnf配置文件及少量rpm依赖包覆盖环境变量写入、root密码重置、安全初始化、服务守护进程配置等关键环节并内置常见依赖包的安装逻辑。压缩包整体约930.56MB按组件分目录存放方便按需调用目前已有298人学习下载。借助这套资料用户可掌握从源码编译到服务自启动的完整链路直接修改脚本参数即可复用部署逻辑同时通过配置示例还能加深对Nginx站点、MySQL参数调优等运维要点的理解兼顾上手效率与进阶参考。1. Linux 一键安装四件套一次跑通 JDK、MySQL、Redis、Nginx新拿到一台 Linux 服务器从零装好 JDK、MySQL、Redis、Nginx 四件套手动折腾一个下午是常态。下载链接失效、glibc 版本不匹配、MySQL 初始化报错、Redis 编译缺依赖随便一个坑都能卡半小时。这套一键式安装方案的价值就是把四个组件的安装顺序、下载源、目录约定、配置项全部固化成一个可重复执行的流程换一台机器跑一遍就能复用。适合刚接手服务器的新运维、需要批量初始化环境的开发同学以及想把环境部署塞进自动化流水线的人。下面从 JDK 开始逐个拆解每一步为什么这么设计以及哪些参数必须手动确认。2. JDK 先行版本选型、目录约定与环境变量一次说清2.1 为什么把 JDK 放在第一位依赖最少最适合验证脚本框架四件套里 JDK 对系统的依赖最少tar 包解压后直接就是完整运行时不需要编译器和额外系统库最不容易失败。一键脚本先跑 JDK本质是在验证网络、解压、目录写权限这条基础设施链路。如果 JDK 这步都翻车后面 MySQL、Nginx 编译环节的错误只会更难排查。版本选型要按业务现状来存量老项目基本锁死 JDK 8新项目可以直接上 17。两个版本在安装方式上没有区别只是 tar 包名不同。脚本里我会把版本号单独抽成一个变量换版本时只改一行其余逻辑完全不动。另外新机器上很可能预装了系统自带的 OpenJDK先执行java -version确认一下如果版本和目标不一致优先用yum remove卸载旧版本否则新装的 JDK 会被 PATH 里的旧版本抢先占用这就是很多人装完新 JDK 后java -version还是旧版本的原因。2.2 下载与解压镜像站路径先确认再写进脚本目录约定上我习惯在/usr/local/java下放一个带版本号的真实目录再做一个latest软链接。环境变量统一指向latest以后升级 JDK 只需要替换真实目录并重建软链接环境变量文件一次写好就不用动。这个设计在多版本共存运维时非常实用切换版本从改环境变量退化成改一条ln -sf命令。下载这一步常见做法是去 jdk 镜像网站 拿对应版本的 tar 包但每个镜像站的目录结构不完全一样第一次用某个镜像时先在浏览器里手动打开确认路径再写进脚本。网上帖子里的 JDK 下载链接大概率已经过期特别是 8u202 这种老版本路径变动很频繁。下面这段把包名、安装路径全部变量化可以直接抄#!/bin/bash JAVA_VERSION8u202 JAVA_TARBALLjdk-8u202-linux-x64.tar.gz JAVA_HOME_DIR/usr/local/java JAVA_REAL_DIR${JAVA_HOME_DIR}/jdk1.8.0_202 mkdir -p ${JAVA_HOME_DIR} # 解压到指定目录-C 参数先创建目标目录结构 tar -xzf /tmp/${JAVA_TARBALL} -C ${JAVA_HOME_DIR} # latest 软链接永远指向当前使用的 JDK切换版本只动这一个链接 ln -sf ${JAVA_REAL_DIR} ${JAVA_HOME_DIR}/latest # 确认软链接指向正确 ls -ld ${JAVA_HOME_DIR}/latesttar -xzf的-C指定了解压目标目录包内的目录名会原样展开到/usr/local/java下。ln -sf里的-f参数会强制覆盖旧链接同一个脚本执行两遍不会因为链接已存在而中断。如果你下载的包名和实际解压后目录名不一致以解压后的真实目录名为准修改JAVA_REAL_DIR这一步错了环境变量会指向空路径。提示解压完成后务必看一眼ls -ld的输出软链接指向的路径存在且正确再继续后面的环境变量配置。2.3 环境变量写在 /etc/profile.d 而不是 /etc/profile环境变量有两种常见写法直接改/etc/profile或者在/etc/profile.d/下新建一个脚本。我一般用后者因为/etc/profile本身会遍历加载/etc/profile.d/*.sh单独放一个文件的好处是升级、卸载、排查都干净不会把主 profile 改得面目全非。网上搜 jdk环境变量配置失败十有八九是写进了当前用户家目录的.bashrc换一个终端就失效或者往/etc/profile末尾追加内容脚本执行几次就重复追加几次PATH越来越长。写入方式用 cat heredoc注意 here 文档的定界符加引号避免$JAVA_HOME在写入时就被展开成空值# 写入系统级环境变量文件/etc/profile 启动时会自动加载 cat /etc/profile.d/java.sh EOF export JAVA_HOME/usr/local/java/latest export PATH$JAVA_HOME/bin:$PATH export CLASSPATH.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar EOF # 让当前 shell 立即生效重登终端后也会自动加载 source /etc/profile.d/java.sh java -version定界符EOF加上引号是关键不加引号的话$JAVA_HOME在 cat 写入时就被解释成空字符串生成的脚本里这一行就是export JAVA_HOME/usr/local/java/latest普通字符串不报错但也不对。CLASSPATH 在 Java 9 之后已经不需要手动配置了如果你装的是 JDK 8写上无妨。验证时命令行输出openjdk version 1.8.0_202之类的信息说明环境变量已经生效。如果输出的是系统自带 JDK 的版本号回头检查是否漏了卸载旧版本那一部。3. MySQL 初始化与远程访问从二进制包到可连接实例3.1 选型yum 还是官方二进制包MySQL 的安装方式yum 最省事但版本和初始化逻辑都被源控制有些内部 yum 源的版本老到连 JSON 函数都缺。用官方二进制包glibc 版本的好处是版本自主可控且解压后直接可以跑是自动化脚本里的主流选择。版本选择上老业务优先 5.7新业务直接 8.0。8.0 默认认证插件是caching_sha2_password老版本 Navicat 和旧语言驱动都连不上所以自动化脚本里要么选 5.7要么在 8.0 里把 root 认证方式手动改回mysql_native_password。二进制包运行有两个运行时依赖不装会在初始化阶段报error while loading shared libraries之类的错yum install -y libaio numactl这两个包体积很小缺了会在 mysqld 启动时直接抛错先装掉省得后面回头找原因。3.2 初始化--initialize-insecure 让自动化少踩一个坑手动安装 MySQL 时常用--initialize它会把临时密码写进错误日志你还需要去日志里翻出来。自动化脚本里我统一用--initialize-insecureroot 初始密码为空脚本下一步直接执行ALTER USER改成正式密码省掉解析日志这一步。处理流程包括创建专用系统账号、规划数据目录、解压二进制包、初始化和启动#!/bin/bash MYSQL_BASE/usr/local/mysql MYSQL_DATA/usr/local/mysql/data # 创建专用系统账号-r 系统账号-s /sbin/nologin 禁止交互登录 groupadd mysql useradd -r -g mysql -s /sbin/nologin mysql # 解压二进制包并重命名到标准路径 tar -xzf mysql-8.0.36-linux-glibc2.17-x86_64-minimal.tar.xz -C /usr/local mv /usr/local/mysql-8.0.36-linux-glibc2.17-x86_64-minimal ${MYSQL_BASE} # 创建数据目录属主必须是 mysql mkdir -p ${MYSQL_DATA} chown -R mysql:mysql ${MYSQL_BASE} # 初始化--initialize-insecure 生成空密码 root适合自动化接管 mysqld --initialize-insecure \ --basedir${MYSQL_BASE} \ --datadir${MYSQL_DATA} \ --usermysql # 先以手动方式启动确认能跑起来再考虑注册系统服务 mysqld_safe --usermysql --initialize-insecure和--initialize的差别就是 root 初始密码前者是空后者是随机临时密码。自动脚本选前者可以直接接后续的ALTER USER。--basedir和--datadir必须和之前规划的目录完全一致不一致会导致初始化过程找不到系统表。chown -R mysql:mysql这步漏了的话mysqld 以 mysql 用户启动时会因为数据目录不可写而失败错误日志里大概率报Permission denied。3.3 远程授权、开机自启与 sql_mode三个细节一起处理初始化完成后 root 默认只允许从 localhost 登录远程工具连不上。需要显式创建远程账号并授权注意生产环境不建议直接开放 root这里是为了任何时候都能接管才这么处理ALTER USER rootlocalhost IDENTIFIED BY MyPass123; CREATE USER root% IDENTIFIED BY MyPass123; GRANT ALL PRIVILEGES ON *.* TO root% WITH GRANT OPTION; FLUSH PRIVILEGES;FLUSH PRIVILEGES让授权表改动立即生效不执行的话有时候客户端重连仍然报权限不足。远程连接还会遇到防火墙拦截常见做法是放行 3306 端口firewall-cmd --permanent --add-port3306/tcp firewall-cmd --reload。如果服务器同时还在跑别的 MySQL 实例端口冲突时用ss -lntp | grep 3306确认占用情况。还有一个容易中招的细节是 sql_mode。MySQL 5.7 之后默认的sql_mode带着NO_ZERO_DATE和NO_ZERO_IN_DATE业务里如果有“mysql设置默认值为0”这种以0000-00-00作为日期默认值的表结构建表语句会直接报错。解决办法是启动后执行SET GLOBAL sql_modeONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION把两个 NO_ZERO 项去掉同时写入 my.cnf 固化。开机自启方面二进制包不自带 systemd 服务文件需要手动封装一个 unit 文件核心内容就是进程守护和启动用户cat /etc/systemd/system/mysqld.service EOF [Unit] DescriptionMySQL Server Afternetwork.target [Service] Usermysql Groupmysql ExecStart/usr/local/mysql/bin/mysqld_safe --usermysql Restartalways [Install] WantedBymulti-user.target EOF systemctl daemon-reload systemctl enable --now mysqld用 systemd 而不是裸的mysqld_safe 好处是开机自启和崩溃重启都交给 systemd 管服务器断电重启后 MySQL 会自动回来不用手工去拉进程。Restartalways这项保留进程意外退出时系统会自动拉起。4. Redis 与 Nginx 编译安装选对参数才算装完4.1 Redisyum 版本太老源码编译并不难系统 yum 源里的 Redis 版本通常落后好几个大版本且不带 6.x 以后的新特性。源码编译安装 Redis 本身不复杂make一下就好真正花时间的是确定配置参数。如果你更习惯用 docker 做部署docker安装redis主从也很常见原生编译的价值在于能看清配置路径和运行机制容器里的配置也是同一套参数。下载、编译、安装三条命令走完#!/bin/bash REDIS_VERSION7.2.4 mkdir -p /usr/local/src cd /usr/local/src # 下载官方源码包下载地址以 redis 官网 releases 目录为准 wget -c -O redis-${REDIS_VERSION}.tar.gz \ https://download.redis.io/releases/redis-${REDIS_VERSION}.tar.gz tar -xzf redis-${REDIS_VERSION}.tar.gz cd redis-${REDIS_VERSION} # 并行编译nproc 返回当前机器 CPU 核数 make -j$(nproc) # 默认把 redis-server、redis-cli 装到 /usr/local/bin make installwget -c支持断点续传网络不稳时重跑脚本不会从头开始下载。make -j$(nproc)用上了全部 CPU 核四核机器编译 Redis 一般在几秒内完成。如果编译中途报错优先级最高的排查项是 gcc 是否已安装yum install -y gcc之后make clean make重来一次。Redis 的编译依赖比 MySQL 二进制包少得多这也是它适合放在编译安装练手位置的原因。4.2 Redis 配置daemonize、protected-mode、requirepass 缺一不可Redis 装完不是开箱即用默认配置下它在前台运行、只能本机访问、没有密码三个问题一个都不能留。我习惯用 cat 直接覆盖默认配置比 sed 一行行改干净不会因为默认残留配置导致启动行为不可预期mkdir -p /etc/redis /var/lib/redis cat /etc/redis/redis.conf EOF # 后台运行否则终端一关进程就消失 daemonize yes # 监听所有网卡配合密码一起用 bind 0.0.0.0 # 关闭保护模式允许非本机访问前提是必须有密码 protected-mode no # 强制要求密码暴露到局域网等于裸奔 requirepass RedisPass123 # RDB 和 AOF 持久化文件都写到这里 dir /var/lib/redis # 日志文件路径排查问题时看这里 logfile /var/log/redis.log EOF redis-server /etc/redis/redis.conf redis-cli -a RedisPass123 PINGdaemonize yes是后台运行的关键不加的话 redis-server 会占用当前终端CtrlC 或者关掉 SSH 窗口进程就没了。bind 0.0.0.0配合protected-mode no是外部访问的开关组合只设一个会有一半功能不生效。requirepass是安全兜底这三个参数必须一起出现单独拎哪一个出来都是半吊子配置。验证时redis-cli -a 密码 PING返回PONG就是正常也可以用 redis 可视化客户端 连接测试但命令行更直接。Redis 数据类型 只有五种String、Hash、List、Set、ZSet装好后用TYPE key命令可以随时确认某个键属于什么类型这个命令在排查缓存问题时很常用。提示dir指定的目录要提前创建Redis 不会自动创建持久化目录写不进去会直接启动失败。4.3 Nginx 编译参数ssl 与 stream 模块按需裁剪Nginx 用源码编译是最能定制运行行为的方式yum 源里的版本经常落后几个迭代模块也不全。编译参数决定后续功能边界最常见的坑是编译完才发现没有 SSL 模块配置listen 443 ssl直接报错只能重新编译整个 Nginx。所以第一次编译时就把常用模块一次性带上#!/bin/bash NGINX_VERSION1.26.0 NGINX_BASE/usr/local/nginx # 编译依赖一次装齐缺哪个 configure 阶段就会报错 yum install -y gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel # nginx.org 是官方下载源别去第三方站点下 wget -c -O /tmp/nginx-${NGINX_VERSION}.tar.gz \ https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz tar -xzf /tmp/nginx-${NGINX_VERSION}.tar.gz -C /usr/local/src cd /usr/local/src/nginx-${NGINX_VERSION} # 编译核心参数prefix 定安装目录模块按需裁剪 ./configure \ --prefix${NGINX_BASE} \ --with-http_ssl_module \ --with-http_gzip_static_module \ --with-stream make -j$(nproc) make install--prefix决定 Nginx 安装目录默认是/usr/local/nginx所有配置和二进制都在这个目录下卸载时删目录即可。--with-http_ssl_module是 HTTPS 的命门没有它 443 端口配置全部失效。--with-stream是四层转发模块后面做数据库负载均衡或者非 HTTP 协议代理时必须有而且这个模块编译期不加上运行期想补只能重新编译。--with-http_gzip_static_module负责静态文件预压缩纯静态站点开启后效果立竿见影。编译完成后确认安装信息/usr/local/nginx/sbin/nginx -V输出里会列出所有编译参数核对一下--with-http_ssl_module是否在列表里。装完 Nginx 后大多数人第一件事是配 nginx反向代理把后端 Java 服务的请求转发到 80 或 443 端口这些配置写在/usr/local/nginx/conf/nginx.conf的server块里改完记得nginx -t先验证语法再 reload避免改挂线上服务。5. 常见安装问题避坑五条踩坑记录与排查思路5.1 JDK 环境变量不生效终端一换就“找不到jdk”现象source /etc/profile之后java -version正常输出关掉终端重新 SSH 登录java命令直接command not found。原因环境变量写进了当前用户家目录的.bashrc只对当前用户和当前终端会话生效。还有一种更隐蔽的情况脚本是从 Windows 编辑后传上来的文件带 CRLF 换行/etc/profile解析到一半中断后面的环境变量根本没加载。解决统一把环境变量写到/etc/profile.d/java.sh用vim或sed -i s/\r$//确认文件是 LF 换行然后重新登录一次终端执行echo $JAVA_HOME看是否输出路径。从那以后我每次装 JDK 都会强制走一遍这个检查。5.2 MySQL 远程登录被拒Host not allowed现象本机mysql -uroot -p正常用 Navicat 或从应用服务器连接时报Host xxx is not allowed to connect to this MySQL server。原因初始化之后的 root 只有localhost权限授权表里没有远程主机的记录连接请求到达 MySQL 后直接拒绝。解决按照 3.3 节的 SQL 创建root%远程账号并执行FLUSH PRIVILEGES。如果为了找回密码用过skip-grant-tables务必在修复后从 my.cnf 移除该参数并重启 MySQL否则整个实例一直处于免鉴权状态风险极大。5.3 Redis 进程启动后消失ping 得通但 ps 找不到现象redis-cli ping能返回PONG但ps -ef | grep redis看不到进程关闭当前 SSH 终端后再连接Redis 已经不可用了。原因daemonize没有设为yesRedis 在前台运行终端关闭时收到 SIGHUP 信号直接退出。redis-cli ping在进程退出前发出的所以看起来短暂正常。解决把daemonize yes写进/etc/redis/redis.conf重启redis-server /etc/redis/redis.conf。为了验证配置是否真的固化用redis-cli shutdown做一次干净退出然后重新启动再ps -ef | grep redis确认进程在后台驻留。5.4 Nginx 80 端口被占用bind() failed现象nginx -t提示syntax is ok但启动时 error log 显示bind() to 0.0.0.0:80 failed (98: Address already in use)。原因已经有服务占用了 80 端口最常见的是 httpd也可能是上一次 Nginx 意外退出留下的监听 socket。解决用 Linux 常用命令 里的端口排查技巧ss -lntp | grep :80找到占用进程的 PID确认不是系统关键服务后kill再启动 Nginx。如果业务端口不能动就改 Nginx 监听端口同时同步修改防火墙放行规则这里是两个配置项不是只改一个就能连通。5.5 脚本重复执行导致环境混乱装了两遍之后找不到北现象同一台机器上把一键脚本跑了两遍JDK 目录下堆了多个版本、MySQL 初始化报data directory already exists、Nginx 二次编译直接覆盖了安装目录。原因脚本没有做幂等处理安装前不检查目标是否已存在导致所有组件都被重新安装了一遍。解决每个组件安装前加存在性判断。JDK 检查/usr/local/java/latest是否已经是有效软链接是就跳过MySQL 检查${MYSQL_DATA}/mysql系统表目录是否存在存在就跳过初始化Nginx 检查/usr/local/nginx/sbin/nginx是否已存在。加入判断后脚本从头到尾执行两遍的结果是一样的这是生产环境脚本的基本素养。6. 收尾验证一张清单加一个 check.sh6.1 一张验证清单走完四件套装完之后不要急着下班先按下面这张清单把四个组件全部验证一遍。这个顺序也是我每次收尾的固定习惯从上到下执行完基本能确认整套环境是可用的组件验证命令预期结果JDKjava -versionopenjdk version 1.8.0_202MySQLmysql -uroot -p -e SELECT VERSION();8.0.36Redisredis-cli -a RedisPass123 PINGPONGNginxcurl -I http://127.0.0.1HTTP/1.1 200 OK注意 MySQL 和 Redis 的验证命令里都带了密码shell 历史记录里会留下明文测试环境无所谓生产环境建议把密码改成从环境变量读取或者用.my.cnf配置文件的[client]段来避免密码出现在命令行参数中。6.2 check.sh一键脚本的最后一公里手动执行四条命令很简单但换一台新机器、新环境或者隔了很久重新部署时脑子里的记忆会模糊。我把验证逻辑收集成一个check.sh放到和安装脚本同一个目录下执行一次就能看到四项服务的健康状态#!/bin/bash MYSQL_PASSMyPass123 REDIS_PASSRedisPass123 check_jdk() { java -version 21 | head -n1 } check_mysql() { mysql -uroot -p${MYSQL_PASS} -e SELECT VERSION(); 2/dev/null } check_redis() { redis-cli -a ${REDIS_PASS} PING 2/dev/null } check_nginx() { curl -sI http://127.0.0.1 | head -n1 } echo JDK: $(check_jdk) echo MySQL: $(check_mysql) echo Redis: $(check_redis) echo Nginx: $(check_nginx)脚本里的四个函数各自独立任何一项失败都不会阻塞其他项的检查。2/dev/null把密码相关的警告和连接报错吞掉输出更干净。如果某项输出异常直接去对应组件的日志目录查MySQL 看$MYSQL_DATA/*.errRedis 看/var/log/redis.logNginx 看/usr/local/nginx/logs/error.log日志路径在设计阶段固定下来排查时就不用到处找。这套流程我最初在一台低配虚拟机上跑通后来换到物理服务器和云主机也都复用差别只在依赖包的包名和初始化参数的小版本差异。从那以后我每次装完环境都强制自己先跑安装脚本、再跑一遍 check.sh任何一项红了就在现场处理绝不含糊上线。这个习惯帮我避掉了至少三次基础设施层面的隐患希望帮到你。本文还有配套的精品资源点击获取
返回列表