现场环境里最值钱的,往往不是某一套产品怎么升,而是那些换一台机器还能用的操作。下面按「通用」和「半通用」整理。命令里的地址、口令、网段都换成占位符,用的时候按现场改。
危险命令单独标了出来。测试环境可以练手,生产环境先备份,再确认自己知道会丢掉什么。
怎么分类
| 类型 | 含义 |
|---|---|
| 通用 | 不绑死某一套产品。Docker、Consul、PostgreSQL、压缩、Linux 账号这类,换环境也能用。 |
| 半通用 | 工具是通用的,坑是现场的。Hadoop NameNode、国产系统提示、达梦连配置中心,都落在这里。 |
产品安装包、仓库地址、业务升级路径不收录。
通用操作
1. 看日志
单机 Compose 和 Swarm 不是同一套命令。先分清当前环境。
单机 / Compose
docker logs -f -t --tail=100 $(docker ps | grep 服务名关键字 | awk '{print $1}' | awk 'NR==1')grep 只是方便定位。关键字要写到只命中一个容器,否则 NR==1 可能拿到别的服务。
Swarm
docker service ls
docker service ps <service_name> --no-trunc
docker service logs -f --tail 5 <service_name>
docker service logs -f --since 5m <service_name>
docker service logs -f --since "2024-04-14T00:00:00" <service_name>
docker service logs -f <service_name>容器起不来,先看 service ps --no-trunc,不要上来就翻日志。
2. 清无用镜像
docker image prune -a会删掉当前没有容器在用的镜像。磁盘紧了再用,不要当日常习惯。
3. 压缩和解压
两种常见格式,别混。
tar.gz
tar -czvf ./deploy_YYYYMMDD.tar.gz ./deploy_YYYYMMDD
tar -xvf ./deploy_YYYYMMDD.tar.gzxz + cpio
有些包不是普通 tar,而是目录树打成 cpio 再 xz。解压要回到原目录结构:
find /deploy_YYYYMMDD -print0 | cpio --null --create --format='newc' | xz > deploy_YYYYMMDD.xz
xz -d < deploy_YYYYMMDD.xz | cpio --extract --make-directories --format='newc'解压前先确认当前目录。这类包经常要求在根目录展开。
4. Consul KV 导入导出
两处最容易踩:
- 开了 ACL 却不带 token,导出会得到空数组
[],看起来像成功。 - 导入文件前必须加
@,否则会把文件名当 JSON 解析,报Cannot unmarshal data。
宿主机
consul kv export --http-addr=http://127.0.0.1:8500 > consul_kv.json
consul kv import --http-addr=http://127.0.0.1:8500 @consul_kv.json容器内,且开启 ACL
CID=$(docker ps | grep consul | awk '{print $1}')
docker exec $CID /bin/sh -c \
'consul kv export --http-addr=http://<CONSUL_ADDR>:8500 -token=<CONSUL_TOKEN> > /consul_kv.json'
docker cp $CID:/consul_kv.json ./consul_kv.json
docker cp ./consul_kv.json $CID:consul_kv.json
docker exec $CID /bin/sh -c \
'consul kv import --http-addr=http://<CONSUL_ADDR>:8500 -token=<CONSUL_TOKEN> @consul_kv.json'导入前先看一眼 JSON 是不是空数组,地址和文件名按目标环境改。导入会覆盖同名 key。
5. 容器里的 PostgreSQL 备份还原
自定义格式(-F c)走 pg_restore;纯 SQL 走 psql。别交叉用。
先定位容器:
PG=$(docker ps | grep postgres | awk '{print $1}' | awk 'NR==1')自定义格式备份
docker exec -it $PG /usr/bin/pg_dump -h 127.0.0.1 -U postgres -p 5432 -F c -f /app.bak <SOURCE_DB>
docker cp $PG:/app.bak /还原到空库
docker exec -it $PG /bin/bash
su postgres
psql
CREATE DATABASE target_db;
\q
exit
exit
docker exec -i $PG /usr/bin/pg_restore -h 127.0.0.1 -U postgres -p 5432 -d target_db < /app.bak如果这条命令没要密码就立刻结束,多半是重定向没进容器。先进容器,再在里面跑 pg_restore。
SQL 文件
gunzip app_20240808.sql.gz
docker cp app_20240808.sql $PG:/
docker exec -i $PG /usr/bin/psql -U postgres -d target_db -f /app_20240808.sql
PGPASSWORD='<PASSWORD>' pg_dump -U <USER> -d <DB> -f /path/to/backup.sql还原前先建空库。生产库不要直接拿备份覆盖。
6. Docker 网络坏了
常见症状:自定义网找不到、容器起不来、宿主机网桥残留。
重建自定义网
网段按现场规划改,不要照抄。
# 先停掉占用该网络的容器
docker network rm <NET_NAME>
docker network create --driver bridge --attachable --subnet=<SUBNET> --gateway=<GATEWAY> <NET_NAME>拆掉 docker0 再让 Docker 重建
systemctl stop docker
ip link set dev docker0 down
brctl delbr docker0
systemctl start docker网桥常用命令
brctl show
brctl addbr <BR>
brctl delbr <BR>
brctl addif <BR> <IFACE>
brctl delif <BR> <IFACE>
ip link set <BR> down
brctl delbr <BR>服务报「找不到网络」时,先停再启,不要反复 up:
docker compose -f /path/to/docker-compose.yml -p <project> down
docker compose -f /path/to/docker-compose.yml -p <project> up -d
docker compose -f /path/to/docker-compose.yml -p <project> restart-p 用来隔离项目名,一台机器上多套栈时尤其有用。
7. 停单个服务
Swarm
docker service scale <service_name>=<replica_count>
docker service rm <service_name>副本数调到 0 是暂停;rm 是删服务定义。
单机
docker compose stop <service>
docker stop <container>8. Swarm 解散再组
多网卡机器必须指定 --advertise-addr,否则节点会拿错 IP,后面 join 全是坑。
docker node ls
docker node rm <NODE_ID>
docker swarm leave --force
docker swarm init
docker swarm init --advertise-addr <INNER_IP>
docker swarm join --token <JOIN_TOKEN> <MANAGER_IP>:2377join 的 token 每次 init 都会变,不要沿用旧记录。先在每个节点 leave,再在 manager 上 init。
9. 防火墙开端口
同一套脚本里同时判断 firewalld 和 ufw 更稳:
if command -v firewall-cmd >/dev/null 2>&1; then
firewall-cmd --zone=public --add-port=${PORT}/tcp --permanent
systemctl restart firewalld
elif command -v ufw >/dev/null 2>&1; then
ufw allow ${PORT}/tcp
ufw reload
else
echo "未找到 firewalld 或 ufw,请手动开放端口"
fi改完用 firewall-cmd --list-all 或 ufw status 核对。远程 SSH 时不要先关默认策略再开端口。
10. expect 做远程批量操作
适合「登录、拷包、开端口、load 镜像、启停容器」这种重复动作。骨架是:
- 校验参数个数和动作(
RUN/STOP)。 - 远程确认
expect、docker是否存在。 - 用
spawn ssh/spawn scp,匹配yes/no和密码提示。 RUN:建目录、拷文件、删旧容器、load、开端口、启动。STOP:只停并删除目标容器。
写脚本时注意:
- 密码不要写进仓库。用参数或本地密文。
scp的通配符经常失效,路径写死更稳。- 端口列表用逗号分隔,在远程循环处理。
- 防火墙改完等几秒再重启 Docker,避免规则还没生效。
11. CentOS 密码输错被锁
PAM 把 SSH 认证失败次数记下来后,对的密码也会被拒。下面两招都是权宜之计,解开后应改回安全配置。
方法 1:临时关掉 UsePAM
sudo vi /etc/ssh/sshd_config
# UsePAM no
sudo systemctl restart sshd部分发行版不建议 UsePAM no。改之前看配置文件里的注释。
方法 2:调整 PAM 规则
编辑 SSH 对应的 PAM 文件,把卡住的 pam_unix.so / 失败计数规则改成可登录,然后:
sudo systemctl restart sshd登录成功后,把失败计数清掉,再把 PAM 和 UsePAM 改回去。
半通用操作
工具通用,后果绑现场。先看清数据在哪,再决定修还是重建。
1. Hadoop NameNode:edit log 有间隙
典型现象:进程看着在,9000 访问不了。日志里是 There appears to be a gap in the edit log,期望的事务 ID 和实际对不上。常见原因是突然断电,fsimage 和 edits 不一致。
处理顺序:
- 先看
dfs.namenode.name.dir里的元数据是否损坏。 - 有备份就用最近一套完好的
fsimage/edits替换。 - 没有备份再尝试恢复:
hdfs namenode -recover- 没有需要保留的数据时,才格式化:
hdfs namenode -format-format 会清空 HDFS 里的数据。有业务数据就不要用这条当第一选择。
- 核对
hdfs-site.xml、core-site.xml里的dfs.namenode.name.dir和fs.defaultFS。 - 启动后再用
jps确认有NameNode。
2. 达梦连配置中心
业务侧通常是把连接串写进配置中心,而不是写进代码。字段形态类似:
{
"ConnectionStrings": {
"DefaultProvider": "dameng",
"Default": "SERVER=<DB_HOST>;PORT=5236;USER=<USER>;PASSWORD=<PASSWORD>;"
}
}公开笔记里不要写真实地址和口令。改完重启读取该配置的服务,并确认配置中心里「是否已初始化」一类开关符合预期,避免二次初始化冲掉数据。
3. 国产系统弹通知
个别国产桌面/服务器会反复弹系统通知。临时压住的办法是去掉执行权限并杀掉进程:
chmod 600 /usr/libexec/sysnotify
pkill -9 sysnotify这是对症处理,不是官方配置。升级系统后可能被还原,也有可能影响其它桌面通知。能改系统策略就不要靠杀进程。
不要当日常技能的命令
「重置环境」这类脚本会停掉全部容器、删 volume、卸载 Docker、清空数据盘。看起来像通用清理,实际是毁灭性操作。
只在明确要重建的测试机上用,并且:
- 先确认不是生产
- 先备份数据库和配置中心
- 单独挂载的分区删不掉,脚本不会替你处理
使用时记住三件事
- 先分清 Compose 还是 Swarm。 日志、扩缩容、停服务的命令完全不同。
- 带认证的导出一定要先验货。 Consul 空数组、PG 立刻返回,都是「看起来成功」。
- 地址、口令、网段、token 全部当占位符。 笔记可以公开,现场值放在自己的密码器里。