Skip to content

现场环境里最值钱的,往往不是某一套产品怎么升,而是那些换一台机器还能用的操作。下面按「通用」和「半通用」整理。命令里的地址、口令、网段都换成占位符,用的时候按现场改。

危险命令单独标了出来。测试环境可以练手,生产环境先备份,再确认自己知道会丢掉什么。

怎么分类 ​

类型含义
通用不绑死某一套产品。Docker、Consul、PostgreSQL、压缩、Linux 账号这类,换环境也能用。
半通用工具是通用的,坑是现场的。Hadoop NameNode、国产系统提示、达梦连配置中心,都落在这里。

产品安装包、仓库地址、业务升级路径不收录。


通用操作 ​

1. 看日志 ​

单机 Compose 和 Swarm 不是同一套命令。先分清当前环境。

单机 / Compose

bash
docker logs -f -t --tail=100 $(docker ps | grep 服务名关键字 | awk '{print $1}' | awk 'NR==1')

grep 只是方便定位。关键字要写到只命中一个容器,否则 NR==1 可能拿到别的服务。

Swarm

bash
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. 清无用镜像 ​

bash
docker image prune -a

会删掉当前没有容器在用的镜像。磁盘紧了再用,不要当日常习惯。

3. 压缩和解压 ​

两种常见格式,别混。

tar.gz

bash
tar -czvf ./deploy_YYYYMMDD.tar.gz ./deploy_YYYYMMDD
tar -xvf ./deploy_YYYYMMDD.tar.gz

xz + cpio

有些包不是普通 tar,而是目录树打成 cpio 再 xz。解压要回到原目录结构:

bash
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 导入导出 ​

两处最容易踩:

  1. 开了 ACL 却不带 token,导出会得到空数组 [],看起来像成功。
  2. 导入文件前必须加 @,否则会把文件名当 JSON 解析,报 Cannot unmarshal data。

宿主机

bash
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

bash
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。别交叉用。

先定位容器:

bash
PG=$(docker ps | grep postgres | awk '{print $1}' | awk 'NR==1')

自定义格式备份

bash
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 /

还原到空库

bash
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 文件

bash
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 网络坏了 ​

常见症状:自定义网找不到、容器起不来、宿主机网桥残留。

重建自定义网

网段按现场规划改,不要照抄。

bash
# 先停掉占用该网络的容器
docker network rm <NET_NAME>
docker network create --driver bridge --attachable --subnet=<SUBNET> --gateway=<GATEWAY> <NET_NAME>

拆掉 docker0 再让 Docker 重建

bash
systemctl stop docker
ip link set dev docker0 down
brctl delbr docker0
systemctl start docker

网桥常用命令

bash
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:

bash
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

bash
docker service scale <service_name>=<replica_count>
docker service rm <service_name>

副本数调到 0 是暂停;rm 是删服务定义。

单机

bash
docker compose stop <service>
docker stop <container>

8. Swarm 解散再组 ​

多网卡机器必须指定 --advertise-addr,否则节点会拿错 IP,后面 join 全是坑。

bash
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>:2377

join 的 token 每次 init 都会变,不要沿用旧记录。先在每个节点 leave,再在 manager 上 init。

9. 防火墙开端口 ​

同一套脚本里同时判断 firewalld 和 ufw 更稳:

bash
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 镜像、启停容器」这种重复动作。骨架是:

  1. 校验参数个数和动作(RUN / STOP)。
  2. 远程确认 expect、docker 是否存在。
  3. 用 spawn ssh / spawn scp,匹配 yes/no 和密码提示。
  4. RUN:建目录、拷文件、删旧容器、load、开端口、启动。
  5. STOP:只停并删除目标容器。

写脚本时注意:

  • 密码不要写进仓库。用参数或本地密文。
  • scp 的通配符经常失效,路径写死更稳。
  • 端口列表用逗号分隔,在远程循环处理。
  • 防火墙改完等几秒再重启 Docker,避免规则还没生效。

11. CentOS 密码输错被锁 ​

PAM 把 SSH 认证失败次数记下来后,对的密码也会被拒。下面两招都是权宜之计,解开后应改回安全配置。

方法 1:临时关掉 UsePAM

bash
sudo vi /etc/ssh/sshd_config
# UsePAM no
sudo systemctl restart sshd

部分发行版不建议 UsePAM no。改之前看配置文件里的注释。

方法 2:调整 PAM 规则

编辑 SSH 对应的 PAM 文件,把卡住的 pam_unix.so / 失败计数规则改成可登录,然后:

bash
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 不一致。

处理顺序:

  1. 先看 dfs.namenode.name.dir 里的元数据是否损坏。
  2. 有备份就用最近一套完好的 fsimage / edits 替换。
  3. 没有备份再尝试恢复:
bash
hdfs namenode -recover
  1. 没有需要保留的数据时,才格式化:
bash
hdfs namenode -format

-format 会清空 HDFS 里的数据。有业务数据就不要用这条当第一选择。

  1. 核对 hdfs-site.xml、core-site.xml 里的 dfs.namenode.name.dir 和 fs.defaultFS。
  2. 启动后再用 jps 确认有 NameNode。

2. 达梦连配置中心 ​

业务侧通常是把连接串写进配置中心,而不是写进代码。字段形态类似:

json
{
  "ConnectionStrings": {
    "DefaultProvider": "dameng",
    "Default": "SERVER=<DB_HOST>;PORT=5236;USER=<USER>;PASSWORD=<PASSWORD>;"
  }
}

公开笔记里不要写真实地址和口令。改完重启读取该配置的服务,并确认配置中心里「是否已初始化」一类开关符合预期,避免二次初始化冲掉数据。

3. 国产系统弹通知 ​

个别国产桌面/服务器会反复弹系统通知。临时压住的办法是去掉执行权限并杀掉进程:

bash
chmod 600 /usr/libexec/sysnotify
pkill -9 sysnotify

这是对症处理,不是官方配置。升级系统后可能被还原,也有可能影响其它桌面通知。能改系统策略就不要靠杀进程。


不要当日常技能的命令 ​

「重置环境」这类脚本会停掉全部容器、删 volume、卸载 Docker、清空数据盘。看起来像通用清理,实际是毁灭性操作。

只在明确要重建的测试机上用,并且:

  • 先确认不是生产
  • 先备份数据库和配置中心
  • 单独挂载的分区删不掉,脚本不会替你处理

使用时记住三件事 ​

  1. 先分清 Compose 还是 Swarm。 日志、扩缩容、停服务的命令完全不同。
  2. 带认证的导出一定要先验货。 Consul 空数组、PG 立刻返回,都是「看起来成功」。
  3. 地址、口令、网段、token 全部当占位符。 笔记可以公开,现场值放在自己的密码器里。

测试开发工程师 · 专注自动化与系统架构 | 邮箱: hansblog@atumsoul.win