Redis 是国内外广泛使用的高性能键值数据库,在软件开发、缓存和消息队列等场景避免不了 Redis 的身影。为了方便快速部署,有时我们需要编写自动化脚本,来实现 Redis 的一键安装和一键卸载。本文基于 Redis 3.2.12 版本,结合 CentOS 及类似系统,分享我实现的Redis安装与卸载自动化shell脚本,以及遇到的一些细节和解决方案。
一、脚本功能与结构
1.1 安装脚本主要功能
- 自动安装 Redis 必要依赖(gcc make jemalloc-devel tcl wget firewalld)
- 下载指定版本的 Redis 源码包(支持本地压缩包路径)
- 编译安装 Redis 到指定目录
- 创建
redis
系统用户,并配置相应目录权限 - 交互式设置访问密码、端口、绑定地址、持久化、日志路径等多项配置
- 生成 systemd 服务脚本,实现 Redis 服务化管理
- 配置 firewall(firewalld)防火墙端口开放与关闭
- 启动 Redis 并辅助打印运行状态
1.2 卸载脚本主要功能
- 停止 Redis 服务,禁止开机自启
- 删除 systemd 服务文件并刷新 systemd 配置
- 删除 Redis 安装目录(包括可执行文件、配置文件、日志和数据)
- 删除 Redis 用户(基于安全和风险考虑,操作前请确认)
- 关闭防火墙中Redis端口开放
二、运行卸载脚本日志示例
[root@localhost script]# ./uninstall-redis.sh
=== Redis 卸载流程 ===
[INFO] 停止 Redis 服务...
[INFO] 禁用 Redis 服务开机自启...
Removed symlink /etc/systemd/system/multi-user.target.wants/redis.service.
[INFO] 删除 systemd 服务文件...
[INFO] 删除 Redis 安装目录:/home/environment/redis
[INFO] 删除 redis 用户...
userdel: redis 邮件池 (/var/spool/mail/redis) 未找到
userdel:未找到 redis 的主目录“/home/redis”
[INFO] 关闭 firewalld 上 Redis 端口 6379
success
success
[INFO] Redis 卸载完成!
小提示:
userdel
提示「邮件池未找到」「主目录未找到」并不影响用户删除操作,且是正常信息,因为安装时并未创建 /home/redis
目录也没有邮箱文件。
三、使用这些脚本
-
准备环境
确保你的系统为 CentOS/RHEL,且有网络连接和 root 权限。 -
安装 Redis
chmod +x install-redis.sh ./install-redis.sh
根据提示输入相应配置。
-
卸载 Redis
chmod +x uninstall-redis.sh ./uninstall-redis.sh
脚本会自动清理服务、文件和用户。
四、总结
- 通过自定义 shell 脚本自动部署 Redis 节省时间,降低人为配置错误风险
- 支持交互式定制和默认参数,灵活方便
- 配合使用卸载脚本,有效避免“残留”,实现完整的安装-卸载闭环
- 部署前请备份重要数据,尤其是配置文件和持久化文件
- 根据实际需求针对防火墙、用户权限等可做进一步增强
希望这套Redis一键安装和卸载脚本能帮你快速搭建高可用的缓存环境,也欢迎关注、留言交流!
附录:脚本获取
- 安装脚本
#!/bin/bash
REDIS_VERSION="3.2.12"
# 安装目录
INSTALL_DIR="/home/environment/redis"
# 安装包路径,优先使用,可不写
LOCAL_TARBALL=""
DOWNLOAD_BASE_URL="http://download.redis.io/releases"
# 可更改端口号
REDIS_PORT=6379
# 预设 Redis 密码,留空则安装时交互询问
REDIS_PASSWORD=""
install_dependencies() {
echo "[INFO] 安装依赖包..."
yum install -y gcc make jemalloc-devel tcl wget firewalld || {
echo "[ERROR] 安装依赖包失败,请检查网络及yum源配置"
exit 1
}
}
fetch_redis_source() {
if [[ -n "$LOCAL_TARBALL" && -f "$LOCAL_TARBALL" ]]; then
echo "[INFO] 使用用户指定本地压缩包:$LOCAL_TARBALL"
SRC_TAR="$LOCAL_TARBALL"
else
SRC_TAR="redis-$REDIS_VERSION.tar.gz"
DOWNLOAD_URL="$DOWNLOAD_BASE_URL/$SRC_TAR"
echo "[INFO] 本地压缩包未指定或不存在,尝试从互联网下载:$DOWNLOAD_URL"
if ! wget -c "$DOWNLOAD_URL" -O "$SRC_TAR"; then
echo "[ERROR] 下载 Redis 源码包失败,请检查网络及版本号"
exit 1
fi
SRC_TAR="$SRC_TAR"
fi
}
compile_install_redis() {
echo "[INFO] 解压源码包..."
tar xzf "$SRC_TAR" || {
echo "[ERROR] 解压失败"
exit 1
}
cd "redis-$REDIS_VERSION" || {
echo "[ERROR] 目录 redis-$REDIS_VERSION 不存在"
exit 1
}
echo "[INFO] 编译 Redis..."
make -j$(nproc) || {
echo "[ERROR] make 编译失败"
exit 1
}
make install PREFIX="$INSTALL_DIR" || {
echo "[ERROR] make install 失败"
exit 1
}
cd ..
}
setup_user_and_dirs() {
id redis &>/dev/null || useradd -r -s /sbin/nologin redis
mkdir -p "$INSTALL_DIR/etc" "$INSTALL_DIR/var" "$INSTALL_DIR/log"
chown -R redis:redis "$INSTALL_DIR"
}
prompt_user_input() {
# 如果 REDIS_PASSWORD 为空,则交互询问是否设置密码以及输入密码
if [[ -z "$REDIS_PASSWORD" ]]; then
read -p "是否设置 Redis 访问密码?(y/N): " set_pass
set_pass=${set_pass,,}
if [[ "$set_pass" == "y" ]]; then
while true; do
read -s -p "请输入 Redis 密码: " redis_pass1
echo
read -s -p "请再次输入密码确认: " redis_pass2
echo
if [[ "$redis_pass1" == "$redis_pass2" && -n "$redis_pass1" ]]; then
REDIS_PASSWORD="$redis_pass1"
break
else
echo "[WARN] 两次输入不一致或为空,请重试"
fi
done
fi
else
# 如果预设变量有值,提示并选择是否继续使用
while true; do
read -p "检测到脚本头部预设 Redis 密码,是否使用该密码?(Y/n): " use_pre_pass
use_pre_pass=${use_pre_pass,,}
if [[ "$use_pre_pass" == "y" || -z "$use_pre_pass" ]]; then
echo "将使用预设 Redis 密码。"
break
elif [[ "$use_pre_pass" == "n" ]]; then
REDIS_PASSWORD=""
# 递归调用进入交互模式输入密码
prompt_user_input
return
else
echo "请输入 y 或 n。"
fi
done
fi
read -p "是否允许外部工具连接 Redis (监听所有IP 0.0.0.0)?(y/N): " allow_external
allow_external=${allow_external,,}
if [[ "$allow_external" == "y" ]]; then
BIND_ADDR="0.0.0.0"
else
BIND_ADDR="127.0.0.1"
fi
read -p "是否允许防火墙开放 Redis 端口 $REDIS_PORT?(y/N): " open_firewall
open_firewall=${open_firewall,,}
read -p "是否启用 RDB 持久化(默认启用)?(Y/n): " enable_rdb
enable_rdb=${enable_rdb,,}
[[ "$enable_rdb" == "n" ]] && RDB_ENABLED="no" || RDB_ENABLED="yes"
read -p "是否启用 AOF 持久化(默认禁用)?(y/N): " enable_aof
enable_aof=${enable_aof,,}
[[ "$enable_aof" == "y" ]] && AOF_ENABLED="yes" || AOF_ENABLED="no"
read -p "是否调整最大客户端连接数(默认 10000)?(y/N): " change_max_clients
change_max_clients=${change_max_clients,,}
if [[ "$change_max_clients" == "y" ]]; then
while true; do
read -p "请输入最大客户端连接数(建议不小于 1000): " max_clients_input
if [[ "$max_clients_input" =~ ^[0-9]+$ && $max_clients_input -ge 100 ]]; then
MAX_CLIENTS=$max_clients_input
break
else
echo "请输入有效的数字且不小于100"
fi
done
else
MAX_CLIENTS=10000
fi
read -p "是否自定义日志文件路径(默认$INSTALL_DIR/var/redis.log)?(y/N): " custom_log
custom_log=${custom_log,,}
if [[ "$custom_log" == "y" ]]; then
while true; do
read -p "请输入日志文件完整路径: " log_path_input
if [[ -n "$log_path_input" ]]; then
LOG_FILE="$log_path_input"
break
else
echo "路径不能为空"
fi
done
else
LOG_FILE="$INSTALL_DIR/var/redis.log"
fi
}
# 复制默认配置文件,做增量修改
copy_and_modify_conf() {
SRC_CONF="redis-$REDIS_VERSION/redis.conf"
CONF_PATH="$INSTALL_DIR/etc/redis.conf"
echo "[INFO] 复制示例配置文件到安装目录"
cp "$SRC_CONF" "$CONF_PATH" || {
echo "[ERROR] 复制配置文件失败"
exit 1
}
echo "[INFO] 修改配置文件"
# 修改 bind 地址
sed -i "s/^bind .*/bind $BIND_ADDR/" "$CONF_PATH"
# 如果选择了设置密码
if [[ -n "$REDIS_PASSWORD" ]]; then
# 注释掉原有 requirepass(以防多个)
sed -i "s/^\(requirepass.*\)/# \1/" "$CONF_PATH"
# 添加新密码配置到文件末尾
echo "requirepass $REDIS_PASSWORD" >> "$CONF_PATH"
else
# 注释掉所有 requirepass,避免密码限制
sed -i "s/^\(requirepass.*\)/# \1/" "$CONF_PATH"
fi
# 设置日志文件
sed -i "s@^logfile .*@logfile \"$LOG_FILE\"@" "$CONF_PATH"
# 设置工作目录
sed -i "s@^dir .*@dir $INSTALL_DIR/var@" "$CONF_PATH"
# maxclients
sed -i "s/^maxclients .*/maxclients $MAX_CLIENTS/" "$CONF_PATH"
# 配置持久化:RDB
if [[ "$RDB_ENABLED" == "no" ]]; then
# 注释掉所有save规则禁用RDB持久化
sed -i "s/^save/# save/" "$CONF_PATH"
else
# 使用默认或保留原有save配置即可,不做处理
# 如果想自定义 save 规则可在此添加
# 这里以默认配置为例,就不修改了
:
fi
# 配置持久化:AOF
if [[ "$AOF_ENABLED" == "yes" ]]; then
sed -i "s/^appendonly no/appendonly yes/" "$CONF_PATH"
else
sed -i "s/^appendonly yes/appendonly no/" "$CONF_PATH"
fi
}
create_systemd_service() {
SERVICE_FILE="/etc/systemd/system/redis.service"
cat > "$SERVICE_FILE" <<EOF
[Unit]
Description=Redis In-Memory Data Store
After=network.target
[Service]
User=redis
Group=redis
ExecStart=$INSTALL_DIR/bin/redis-server $INSTALL_DIR/etc/redis.conf
ExecStop=$INSTALL_DIR/bin/redis-cli -p $REDIS_PORT shutdown
Restart=always
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable redis
}
start_redis() {
systemctl start redis
sleep 2
if systemctl status redis | grep -q running; then
echo "[INFO] Redis 服务启动成功,运行端口 $REDIS_PORT"
else
echo "[ERROR] Redis 服务启动失败,请检查日志"
journalctl -u redis -n 50 --no-pager
exit 1
fi
}
configure_firewall() {
# 检查 firewalld 是否安装
if ! command -v firewall-cmd &>/dev/null; then
echo "[WARN] firewalld 未安装,尝试安装中..."
yum install -y firewalld || {
echo "[ERROR] firewalld 安装失败,请手动安装防火墙"
return
}
fi
# 检查 firewalld 是否正在运行,未运行则尝试启动并设置开机自启
systemctl is-active --quiet firewalld
if [[ $? -ne 0 ]]; then
echo "[WARN] firewalld 未启动,尝试启动并设置开机自启..."
systemctl start firewalld || {
echo "[ERROR] firewalld 启动失败,请检查系统日志"
return
}
systemctl enable firewalld
fi
# 根据用户选择开放或关闭对应端口
if [[ "$open_firewall" == "y" ]]; then
echo "[INFO] 配置 firewalld 开放端口 $REDIS_PORT/tcp"
firewall-cmd --permanent --add-port=${REDIS_PORT}/tcp
firewall-cmd --reload
else
echo "[INFO] 配置 firewalld 关闭端口 $REDIS_PORT/tcp"
firewall-cmd --permanent --remove-port=${REDIS_PORT}/tcp &>/dev/null
firewall-cmd --reload
fi
}
main() {
echo "=== Redis 安装脚本 ==="
read -p "请输入 Redis 源码压缩包本地路径(有则输入完整路径,无则直接回车): " user_tarball
if [[ -n "$user_tarball" ]]; then
if [[ -f "$user_tarball" ]]; then
LOCAL_TARBALL="$user_tarball"
else
echo "[ERROR] 指定的压缩包路径不存在,请检查后重试"
exit 1
fi
fi
install_dependencies
fetch_redis_source
compile_install_redis
setup_user_and_dirs
prompt_user_input
copy_and_modify_conf
create_systemd_service
configure_firewall
start_redis
echo "Redis 安装完成!"
echo "配置文件: $INSTALL_DIR/etc/redis.conf"
echo "日志文件: $LOG_FILE"
echo "默认使用 systemctl 管理服务:"
echo " - 启动: systemctl start redis"
echo " - 停止: systemctl stop redis"
echo " - 重启: systemctl restart redis"
echo " - 查看状态: systemctl status redis"
}
main "$@"
- 搭配一键卸载脚本
#!/bin/bash
# Redis 卸载脚本示例
# 以下变量需和安装脚本保持一致
REDIS_PORT=6379
INSTALL_DIR="/home/environment/redis"
SERVICE_FILE="/etc/systemd/system/redis.service"
REDIS_USER="redis"
echo "=== Redis 卸载流程 ==="
# 1. 停止 Redis 服务并禁用开机自启
if systemctl is-active --quiet redis; then
echo "[INFO] 停止 Redis 服务..."
systemctl stop redis
fi
if systemctl is-enabled --quiet redis; then
echo "[INFO] 禁用 Redis 服务开机自启..."
systemctl disable redis
fi
# 2. 删除 systemd 服务文件并刷新 systemd 配置
if [[ -f "$SERVICE_FILE" ]]; then
echo "[INFO] 删除 systemd 服务文件..."
rm -f "$SERVICE_FILE"
systemctl daemon-reload
fi
# 3. 删除安装目录(包含二进制、配置、数据、日志)
if [[ -d "$INSTALL_DIR" ]]; then
echo "[INFO] 删除 Redis 安装目录:$INSTALL_DIR"
rm -rf "$INSTALL_DIR"
fi
# 4. 删除 redis 用户(可选,谨慎操作)
if id "$REDIS_USER" &>/dev/null; then
echo "[INFO] 删除 redis 用户..."
userdel -r "$REDIS_USER"
fi
# 5. 关闭防火墙 Redis 端口(仅当 firewalld 存在并运行)
if command -v firewall-cmd &>/dev/null && systemctl is-active --quiet firewalld; then
echo "[INFO] 关闭 firewalld 上 Redis 端口 $REDIS_PORT"
firewall-cmd --permanent --remove-port=${REDIS_PORT}/tcp
firewall-cmd --reload
fi
# 6. 依赖包可选择不卸载,视环境决定
#echo "[INFO] 依赖包卸载 请手动确认"
#yum remove -y gcc make jemalloc-devel tcl wget firewalld
echo "[INFO] Redis 卸载完成!"
版权声明
本文原创,欢迎共享,转载请注明出处。