Yum源服务器_运维手册_日常篇
Yum 源服务器 运维手册(日常运维篇)
1. 系统简介
Yum 源服务器为企业内网 Linux 服务器提供 RPM 包分发服务,部署在 Linux 服务器上(通常使用 CentOS/Rocky/AlmaLinux),通过 HTTP/HTTPS 对外提供仓库访问。支持多发行版多版本仓库托管、增量同步上游镜像、GPG 签名验证。是企业 Linux 标准化运维的基础设施组件。
2. 账号维护
2.1 系统账号管理
# 创建运维专用账号
useradd -m -s /bin/bash repo_admin
passwd repo_admin
# 授予 sudo 权限(限定特定命令)
echo "repo_admin ALL=(ALL) NOPASSWD: /usr/bin/createrepo, /usr/bin/reposync, /usr/bin/rsync, /bin/systemctl restart httpd" > /etc/sudoers.d/repo_admin
# 检查账号
id repo_admin
sudo -l -U repo_admin2.2 SSH 密钥管理
# 生成部署用密钥对(在管理端执行)
ssh-keygen -t ed25519 -f ~/.ssh/repo_deploy_key -C "repo-deploy@domain"
# 将公钥添加到 Yum 源服务器
ssh-copy-id -i ~/.ssh/repo_deploy_key.pub repo_admin@yum-server
# 禁用密码登录(安全加固)
sed -i 's/^PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart sshd2.3 SELinux 管理
# 查看 SELinux 状态
getenforce
# 【推荐】保持 Enforcing,为仓库目录设置正确上下文
# 查看当前上下文
ls -Z /var/www/html/repo/
# 设置正确的 SELinux 上下文(HTTP 可读)
semanage fcontext -a -t httpd_sys_content_t "/var/www/html/repo(/.*)?"
restorecon -Rv /var/www/html/repo/
# 如果使用自定义端口,还需配置 SELinux 策略
semanage port -a -t http_port_t -p tcp 80802.4 防火墙规则管理
# HTTP 仓库(使用 firewalld)
firewall-cmd --permanent --add-service=http
firewall-cmd --reload
# HTTPS 仓库
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
# 自定义端口
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --reload
# 验证防火墙规则
firewall-cmd --list-all2.5 账号审计
# 查看所有系统用户
cat /etc/passwd | grep -E "home|bash"
# 查看 sudo 授权用户
cat /etc/sudoers /etc/sudoers.d/*
# 查看 SSH 登录记录
lastlog
last | head -30
# 查看最近登录失败的 IP
lastb | head -20- 每季度审核一次系统账号
- 离职人员立即禁用或删除账号:
usermod -L 用户名
3. 日常配置调整
3.1 仓库添加/删除/修改
创建新仓库
# 1. 创建目录结构
mkdir -p /var/www/html/repo/centos/7/os/x86_64
mkdir -p /var/www/html/repo/centos/7/updates/x86_64
# 2. 下载或复制 RPM 包到目录
# (详见 3.2 同步源配置)
# 3. 创建元数据(核心步骤)
createrepo --database /var/www/html/repo/centos/7/os/x86_64
# 4. 更新元数据(增量添加新包后)
createrepo --update /var/www/html/repo/centos/7/os/x86_64
# 5. 验证元数据
ls -la /var/www/html/repo/centos/7/os/x86_64/repodata/删除仓库
# 直接删除目录
rm -rf /var/www/html/repo/centos/7/os
# 或在 nginx/apache 配置中注释掉对应 location修改仓库配置(repomd.xml)
# repomd.xml 由 createrepo 自动生成,通常不需要手动修改
# 如需修改仓库描述显示
createrepo --update --pretty --simple-md-filenames /path/to/repo
# 查看 repomd.xml 内容
cat /var/www/html/repo/centos/7/os/x86_64/repodata/repomd.xml | head -203.2 同步源配置(上游 Mirror)
使用 reposync 同步
# 安装必要工具
yum install -y yum-utils createrepo
# 同步 CentOS 7 Base 仓库到本地
reposync --repoid=base --newest-only --download-metadata --download_path=/var/www/html/repo/centos/7/
# 同步只保留最新包(推荐,节省空间)
reposync --repoid=base --newest-only --download-metadata --download_path=/var/www/html/repo/centos/7/
# 同步后必须重新生成元数据
createrepo --update /var/www/html/repo/centos/7/os/x86_64/使用 rsync 同步(更快,适合大型仓库)
# 从阿里云镜像站 rsync 同步 CentOS 7
rsync -avz --delete --exclude="i386" --exclude="debug" \
rsync://mirrors.aliyun.com/centos/7/os/x86_64/ \
/var/www/html/repo/centos/7/os/x86_64/
# 同步 EPEL 仓库
rsync -avz --delete --exclude="i386" --exclude="debug" \
rsync://mirrors.aliyun.com/epel/7/x86_64/ \
/var/www/html/repo/epel/7/x86_64/3.3 同步频率配置(crontab)
配置定时同步任务
# 编辑 crontab
crontab -e -u repo_admin
# 添加同步任务(推荐每天凌晨同步)
# 每天凌晨 3:00 同步 Base 仓库
0 3 * * * /usr/local/bin/sync_repo.sh base > /var/log/repo_sync/base.log 2>&1
# 每天凌晨 4:00 同步 Updates 仓库
0 4 * * * /usr/local/bin/sync_repo.sh updates > /var/log/repo_sync/updates.log 2>&1
# 每周日凌晨 5:00 同步 EPEL 仓库
0 5 * * 0 /usr/local/bin/sync_repo.sh epel > /var/log/repo_sync/epel.log 2>&1同步脚本示例(/usr/local/bin/sync_repo.sh)
#!/bin/bash
# sync_repo.sh - Yum 仓库同步脚本
REPO_NAME=$1
REPO_BASE="/var/www/html/repo"
LOG_FILE="/var/log/repo_sync/${REPO_NAME}.log"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting sync for $REPO_NAME" >> $LOG_FILE
case $REPO_NAME in
base)
reposync --repoid=base --newest-only --download-metadata \
--download_path=${REPO_BASE}/centos/7/ >> $LOG_FILE 2>&1
createrepo --update ${REPO_BASE}/centos/7/os/x86_64/ >> $LOG_FILE 2>&1
;;
updates)
reposync --repoid=updates --newest-only --download-metadata \
--download_path=${REPO_BASE}/centos/7/ >> $LOG_FILE 2>&1
createrepo --update ${REPO_BASE}/centos/7/updates/x86_64/ >> $LOG_FILE 2>&1
;;
epel)
rsync -avz --delete --exclude="i386" --exclude="debug" \
rsync://mirrors.aliyun.com/epel/7/x86_64/ \
${REPO_BASE}/epel/7/x86_64/ >> $LOG_FILE 2>&1
createrepo --update ${REPO_BASE}/epel/7/x86_64/ >> $LOG_FILE 2>&1
;;
*)
echo "Usage: $0 {base|updates|epel}" >> $LOG_FILE
exit 1
;;
esac
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Sync completed for $REPO_NAME" >> $LOG_FILE3.4 GPG 密钥管理
# 导入上游 GPG 密钥
rpm --import https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
# 查看已导入的 GPG 密钥
rpm -qa gpg-pubkey*
# 导出 GPG 密钥供客户端使用
gpg --export -a "CentOS-7" > /var/www/html/repo/centos/RPM-GPG-KEY-CentOS-7
# 为本地仓库创建签名(可选,企业私有仓库需要)
gpg --gen-key # 生成签名密钥
rpmsign --addsign --key-id=YOUR_KEY_ID /var/www/html/repo/local/*.rpm3.5 客户端 repo 文件模板
# 保存到 /var/www/html/repo/client-templates/centos7.repo
# 供客户端使用的 repo 模板文件
[local-base]
name=CentOS-$releasever - Base (Local)
baseurl=http://yum-server.domain.com/centos/$releasever/os/$basearch/
gpgcheck=1
enabled=1
gpgkey=http://yum-server.domain.com/centos/RPM-GPG-KEY-CentOS-$releasever
[local-updates]
name=CentOS-$releasever - Updates (Local)
baseurl=http://yum-server.domain.com/centos/$releasever/updates/$basearch/
gpgcheck=1
enabled=1
gpgkey=http://yum-server.domain.com/centos/RPM-GPG-KEY-CentOS-$releasever
[local-epel]
name=EPEL for CentOS-$releasever (Local)
baseurl=http://yum-server.domain.com/epel/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=http://yum-server.domain.com/epel/RPM-GPG-KEY-EPEL-$releasever3.6 Nginx/Apache 虚拟主机配置
Nginx 配置(推荐)
# /etc/nginx/conf.d/yum-repo.conf
server {
listen 80;
server_name yum-server.domain.com;
root /var/www/html/repo;
# 日志配置
access_log /var/log/nginx/yum-repo-access.log main;
error_log /var/log/nginx/yum-repo-error.log;
# 启用目录列表
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
# 禁掉 debug 目录(不需要同步给客户端)
location ~ /debug/ {
deny all;
}
# 大文件下载优化
location ~* \.(rpm)$ {
sendfile on;
tcp_nopush on;
}
}Apache 配置(备选)
# /etc/httpd/conf.d/yum-repo.conf
<VirtualHost *:80>
ServerName yum-server.domain.com
DocumentRoot /var/www/html/repo
<Directory /var/www/html/repo>
Options +Indexes +FollowSymLinks
IndexOptions FancyIndexing NameWidth=* VersionSort
Require all granted
</Directory>
# 访问日志
CustomLog /var/log/httpd/yum-repo-access.log combined
ErrorLog /var/log/httpd/yum-repo-error.log
</VirtualHost>3.7 目录权限管理
# 设置目录拥有者
chown -R repo_admin:repo_admin /var/www/html/repo/
# 设置目录权限(755:目录可读可执行,文件644)
find /var/www/html/repo -type d -exec chmod 755 {} \;
find /var/www/html/repo -type f -exec chmod 644 {} \;
# 给 createrepo 写的数据库特殊权限
chmod 644 /var/www/html/repo/*/repodata/*3.8 带宽限制(rsync --bwlimit)
# 同步时限制带宽,避免占满出口(限速 10MB/s = 10240 KB/s)
rsync -avz --delete --bwlimit=10240 \
rsync://mirrors.aliyun.com/centos/7/os/x86_64/ \
/var/www/html/repo/centos/7/os/x86_64/
# reposync 本身不支持带宽限制,可通过 rsync 替代3.9 配置备份
backup_date=$(date +%Y%m%d)
mkdir -p /root/repo_backup/$backup_date
# 备份 Nginx/Apache 配置
cp /etc/nginx/conf.d/yum-repo.conf /root/repo_backup/$backup_date/
# 或
# cp /etc/httpd/conf.d/yum-repo.conf /root/repo_backup/$backup_date/
# 备份同步脚本
cp /usr/local/bin/sync_repo.sh /root/repo_backup/$backup_date/
# 备份 crontab
crontab -l > /root/repo_backup/$backup_date/crontab.txt
# 备份 GPG 密钥
gpg --export -a "密钥名" > /root/repo_backup/$backup_date/gpg-public.key
gpg --export-secret-keys -a "密钥名" > /root/repo_backup/$backup_date/gpg-private.key
# 备份客户端 repo 模板
cp /var/www/html/repo/client-templates/*.repo /root/repo_backup/$backup_date/3.10 配置生效
- Nginx 配置修改后重载:
nginx -t && systemctl reload nginx - Apache 配置修改后重载:
httpd -t && systemctl reload httpd - 仓库元数据更新(createrepo)后立即生效,无需重启服务
- crontab 编辑后立即生效
4. 日常巡检 Checklist
| 检查项 | 检查方法 | 正常状态 | 频率 | |
|---|---|---|---|---|
| Web 服务状态 | systemctl status nginx 或 systemctl status httpd | active (running) | 每日 | |
| 仓库总磁盘空间 | df -h /var/www/html/repo | 使用率 < 80% | 每日 | |
| 最近同步时间 | tail -3 /var/log/repo_sync/base.log | 最近24小时内有成功记录 | 每日 | |
| 仓库元数据完整性 | ls -la /var/www/html/repo/centos/7/os/x86_64/repodata/repomd.xml | 文件存在且最近修改时间与同步一致 | 每日 | |
| 客户端访问测试 | 找一台客户端执行 yum repolist | 显示本地仓库且计数正确 | 每日 | |
| HTTP 响应正常 | curl -s -o /dev/null -w "%{http_code}" http://localhost/repo/ | 200 或 301 | 每日 | |
| 目录列表可访问 | `curl -s http://localhost/repo/centos/7/os/x86_64/ \ | grep "repodata"` | 返回目录列表 | 每日 |
| Nginx/Apache 错误日志 | tail -20 /var/log/nginx/yum-repo-error.log | 无大量 4xx/5xx 错误 | 每日 | |
| repo 文件语法检查 | createrepo --check /var/www/html/repo/centos/7/os/x86_64/ | 无错误输出 | 每周 | |
| 同步日志无报错 | `grep -i "error\ | fail" /var/log/repo_sync/*.log` | 无匹配 | 每日 |
| SELinux 状态 | getenforce | Enforcing(推荐) | 每周 | |
| 防火墙规则 | firewall-cmd --list-all | http/https 服务已允许 | 每周 | |
| 存储空间预测 | `du -sh /var/www/html/repo/*/ \ | sort -rh` | 监控增长趋势 | 每周 |
5. 系统启停操作
5.1 正常启动
# Nginx
systemctl start nginx
systemctl status nginx
# Apache
systemctl start httpd
systemctl status httpd5.2 正常停止
# 先确认是否正在进行同步任务
ps aux | grep -E "rsync|reposync|createrepo"
# 停止 Web 服务
systemctl stop nginx
# 或
systemctl stop httpd5.3 服务状态检查
# Web 服务
systemctl status nginx --no-pager
# 端口监听
ss -tlnp | grep -E ":80|:443"
# 仓库可访问性
curl -I http://localhost/repo/5.4 异常处理
- 端口冲突:
ss -tlnp | grep :80查看 80 端口占用 - 进程卡住:
killall -9 reposync强制终止同步进程 - 磁盘满了时先清理最早的仓库备份
6. 日志查看与分析
6.1 日志路径
# Web 服务日志
/var/log/nginx/yum-repo-access.log # Nginx 访问日志
/var/log/nginx/yum-repo-error.log # Nginx 错误日志
/var/log/httpd/yum-repo-access.log # Apache 访问日志
/var/log/httpd/yum-repo-error.log # Apache 错误日志
# 同步日志
/var/log/repo_sync/base.log # Base 仓库同步日志
/var/log/repo_sync/updates.log # Updates 同步日志
/var/log/repo_sync/epel.log # EPEL 同步日志
# 系统日志
/var/log/messages # 系统消息
/var/log/cron # crontab 执行日志6.2 关键日志关键字
| 日志/关键字 | 含义 | 处理 |
|---|---|---|
| "error: Cannot retrieve repository metadata" | 仓库元数据损坏 | 重新运行 createrepo |
| "No such file or directory: repodata" | 缺少元数据 | 运行 createrepo |
| "Disk quota exceeded" / "No space left on device" | 磁盘空间满 | 清理旧包或扩容 |
| rsync error: timeout | 同步超时 | 检查上游镜像可达性 |
| "Permission denied" / 403 | 权限错误 | 检查目录权限和 SELinux |
| "404 Not Found" | 文件不存在 | 检查仓库同步是否完整 |
| "Connection refused" | Web 服务未启动 | 启动 nginx/httpd |
| "gpgkey retrieval failed" | GPG 密钥下载失败 | 检查 GPG 文件路径 |
| "Delta RPMs disabled" | 增量 RPM 下载失败 | 可忽略,自动回退下载完整包 |
6.3 日志轮转/清理
# 配置 logrotate 管理同步日志
cat > /etc/logrotate.d/repo-sync << 'EOF'
/var/log/repo_sync/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 644 repo_admin repo_admin
}
EOF
# 立即测试
logrotate -d /etc/logrotate.d/repo-sync7. 常见故障处理
7.1 客户端 yum repolist 失败
现象:客户端执行 yum repolist 报错,显示仓库不可用
解决:
# 在客户端上排查
# 1. 测试仓库 URL 可访问
curl -I http://yum-server.domain.com/repo/centos/7/os/x86_64/
# 2. 检查 repodata 是否存在
curl -s http://yum-server.domain.com/repo/centos/7/os/x86_64/repodata/repomd.xml | head -5
# 3. 检查客户端 DNS 解析
nslookup yum-server.domain.com
# 4. 如果 curl 正常但 yum 失败,检查 repo 文件
cat /etc/yum.repos.d/local.repo
# 确认 baseurl 路径正确,no proxy 设置不被代理拦截
# 5. 在服务器端检查访问日志
tail -20 /var/log/nginx/yum-repo-access.log | grep 客户端IP7.2 同步失败(上游不可达)
现象:同步脚本报错,上游镜像无法连接
解决:
# 1. 测试上游镜像连通性
curl -I rsync://mirrors.aliyun.com/
curl -I https://mirrors.aliyun.com/
# 2. 检查 DNS
nslookup mirrors.aliyun.com
# 3. 切换备用上游镜像
# 阿里云:rsync://mirrors.aliyun.com/
# 华为云:rsync://mirrors.huaweicloud.com/
# 清华:rsync://mirrors.tuna.tsinghua.edu.cn/
# 4. 如果所有外部源都不可达,临时挂起同步
crontab -e -u repo_admin
# 注释掉同步任务,系统管理员修复网络后再取消注释
# 5. 同步超时处理
# 增加 rsync 超时时间
rsync -avz --delete --timeout=3600 --bwlimit=10240 \
rsync://mirrors.aliyun.com/centos/7/os/x86_64/ \
/var/www/html/repo/centos/7/os/x86_64/7.3 仓库元数据损坏
现象:客户端报 "Cannot retrieve repository metadata"
解决:
# 1. 检查 repodata 目录
ls -la /var/www/html/repo/centos/7/os/x86_64/repodata/
# 2. 如果目录为空或不完整,重新生成元数据
createrepo --database /var/www/html/repo/centos/7/os/x86_64/
# 3. 如果仍有问题,清理后重新生成
rm -rf /var/www/html/repo/centos/7/os/x86_64/repodata/
createrepo --database /var/www/html/repo/centos/7/os/x86_64/
# 4. 验证
ls -la /var/www/html/repo/centos/7/os/x86_64/repodata/7.4 磁盘空间满
现象:df -h 显示磁盘使用率 100%,同步失败
解决:
# 1. 紧急释放空间:查看各仓库大小
du -sh /var/www/html/repo/*/
# 2. 清理不再需要的旧版本仓库
rm -rf /var/www/html/repo/centos/6/ # 如果已不再使用 CentOS 6
# 3. 清理 debug/debuginfo 包(通常不需要)
find /var/www/html/repo -path "*/debug/*" -delete
# 4. 清理临时文件和日志
rm -rf /tmp/reposync-*
rm -f /var/log/repo_sync/*.log-???????? # 清理旧日志
> /var/log/nginx/yum-repo-access.log # 清空访问日志
# 5. 如果是 rsync 同步,立即停止当前占用磁盘的同步
pkill -9 rsync
pkill -9 reposync
# 6. 长期方案:添加磁盘或清理同步策略
# 修改同步脚本,只同步最新包(--newest-only)7.5 SELinux 导致访问 403
现象:curl 访问返回 403 Forbidden
解决:
# 1. 查看 SELinux 审计日志
ausearch -m avc -ts recent
# 2. 临时测试(关闭 SELinux)
setenforce 0
curl -I http://localhost/repo/ # 如果恢复正常,确认是 SELinux 问题
# 3. 恢复并修正 SELinux 上下文(不要长期关闭 SELinux)
setenforce 1
semanage fcontext -a -t httpd_sys_content_t "/var/www/html/repo(/.*)?"
restorecon -Rv /var/www/html/repo/
# 4. 验证
curl -I http://localhost/repo/7.6 同步脚本不执行(crontab)
现象:发现仓库很久没更新,crontab 没执行
解决:
# 1. 检查 crontab 服务
systemctl status crond
# 2. 检查 crontab 内容
crontab -l -u repo_admin
# 3. 检查 cron 日志
grep "sync_repo" /var/log/cron
# 4. 手动执行测试
su - repo_admin -c "/usr/local/bin/sync_repo.sh base"
# 5. 常见问题:
# - 脚本没有执行权限
chmod +x /usr/local/bin/sync_repo.sh
# - 脚本中使用了相对路径,需改为绝对路径
# - crontab 环境变量与交互式 shell 不同,脚本中 PATH 需要写完整8. 备份与恢复
8.1 配置备份(元数据+配置文件)
backup_date=$(date +%Y%m%d_%H%M)
mkdir -p /backup/yum-repo/$backup_date
# 备份 Web 配置文件
tar czf /backup/yum-repo/$backup_date/nginx_conf.tar.gz /etc/nginx/conf.d/yum-repo.conf
# 备份同步脚本和 crontab
tar czf /backup/yum-repo/$backup_date/scripts.tar.gz /usr/local/bin/sync_repo.sh
crontab -l > /backup/yum-repo/$backup_date/crontab.txt
# 备份 GPG 密钥
gpg --export -a "密钥名" > /backup/yum-repo/$backup_date/gpg-public.key
gpg --export-secret-keys -a "密钥名" > /backup/yum-repo/$backup_date/gpg-private.key
# 备份仓库列表
find /var/www/html/repo -name repomd.xml | sed 's|/repodata/repomd.xml||' > /backup/yum-repo/$backup_date/repo_list.txt
echo "Backup completed: /backup/yum-repo/$backup_date"8.2 完整恢复
# 1. 安装 Web 服务
yum install -y nginx createrepo yum-utils
# 2. 恢复配置文件
tar xzf /backup/yum-repo/20260630/nginx_conf.tar.gz -C /
nginx -t && systemctl restart nginx
# 3. 恢复 GPG 密钥
gpg --import /backup/yum-repo/20260630/gpg-private.key
# 4. 恢复同步脚本
cp /backup/yum-repo/20260630/scripts.tar.gz /tmp/
tar xzf /tmp/scripts.tar.gz -C /
chmod +x /usr/local/bin/sync_repo.sh
# 5. 恢复 crontab
crontab /backup/yum-repo/20260630/crontab.txt
# 6. 重新同步仓库(如没有 RPM 包备份,需要重新同步)
/usr/local/bin/sync_repo.sh base
# 7. 恢复仓库目录权限
chown -R root:root /var/www/html/repo/
restorecon -Rv /var/www/html/repo/
# 8. 验证
yum repolist8.3 RPM 包增量备份(按需)
# 如果需要备份实际 RPM 包(数据量大,按需执行)
# 使用 rsync 备份到远程备份服务器
rsync -avz --delete /var/www/html/repo/ backup-server:/backup/yum-repo/