1. 为什么卸载 GPCC 比安装更值得单独写一篇
装过 Greenplum Command Center(下面统一简称 GPCC)的人都知道,安装过程虽然步骤多,但官方文档给得还算清楚,照着走基本能跑起来。可一旦涉及到卸载,情况就完全不一样了——文档里往往只有寥寥几句,甚至不同版本之间的卸载方式差异还挺大。我见过太多人在这上面翻车:有人直接删了安装目录,结果 Web 服务还在后台跑着;有人把数据库里的元数据表删了,但系统服务没停,重启之后又冒出来;还有人卸载完发现 Greenplum 集群本身的监控数据采集进程还在偷偷占资源。
这篇内容就是专门解决这个问题的。我会把 GPCC 卸载这件事从头到尾拆开讲清楚:它到底由哪几部分组成、每一部分卸载时会发生什么、正确的卸载顺序是什么、卸载完怎么验证干净了、以及那些官方文档不会告诉你的坑。不管你是刚接触 GPCC 的新手,还是已经用过一段时间想彻底清理环境的老手,这篇都能直接拿来当操作手册用。
需要先说明一点:GPCC 的卸载之所以比安装更容易出问题,核心原因在于它不是一个单一软件,而是由多个组件拼起来的——Web 前端服务、后台数据采集代理、数据库内的元数据 schema、系统级服务注册、以及和 Greenplum 集群的集成配置。这五块东西分散在不同的位置,卸载时如果只处理其中一部分,剩下的就会变成"幽灵组件",平时看不出来,关键时刻给你添乱。
提示:在做任何卸载操作之前,先确认你手头有 GPCC 的安装版本号和管理员权限。不同版本的卸载命令和路径会有差异,盲目操作可能导致 Greenplum 集群本身受影响。
2. GPCC 到底装了哪些东西:先搞清楚卸载对象
2.1 五个核心组件及其落盘位置
很多人卸载不干净,根本原因是对 GPCC 的组件构成没有清晰认知。我把它拆成五块,每一块都有典型的落盘位置和卸载方式。
| 组件 | 作用 | 典型位置 | 卸载方式 |
|---|---|---|---|
| Web 服务端 | 提供监控页面和 API | GPCC 安装目录下的 web 子目录 | 停止服务后删除目录 |
| 数据采集代理 | 从集群各节点收集指标 | 各 Segment 节点的代理目录 | 逐节点停止并清理 |
| 数据库元数据 | 存储监控配置和历史数据 | 指定数据库内的 schema | SQL 方式删除 |
| 系统服务注册 | 开机自启和进程守护 | 系统服务管理目录 | 服务管理命令注销 |
| 集成配置 | 与集群的连接和认证配置 | 集群配置目录及环境变量 | 手动清理配置文件 |
这五块里面,前三块是"实体",后两块是"影子"。实体部分你删了目录就能看到效果,影子部分不清理的话,表面上没事,但系统重启或者集群做某些操作时就会暴露问题。
2.2 为什么不能直接 rm -rf 安装目录
我见过最粗暴的做法就是找到 GPCC 安装目录,一个rm -rf完事。这么做的问题在于:
第一,正在运行的 Web 服务进程不会因为你删了目录就自动停止。进程还在内存里跑着,端口还占着,你重新装一个新版本时会发现端口冲突,或者旧进程和新进程抢资源。
第二,数据采集代理是分布在多个节点上的。你只删了主节点的目录,其他节点上的代理还在往数据库里写数据,造成数据混乱。
第三,数据库里的元数据 schema 完全没动。下次安装时如果用了同一个数据库,新旧 schema 冲突,轻则安装失败,重则把原有监控数据搞坏。
第四,系统服务注册没注销。系统重启后,服务管理会尝试启动一个已经不存在的服务,报错日志里一堆找不到文件的提示,排查起来很烦人。
所以正确的卸载思路是:先停服务,再清代理,然后删元数据,接着注销服务,最后清理配置和目录。顺序不能乱,乱了就可能有残留进程或者残留数据。
2.3 卸载前的环境确认清单
动手之前,花五分钟做几个确认,能省掉后面半小时的排查。
- 确认当前登录用户有 GPCC 安装目录的写权限和数据库的管理权限
- 确认 GPCC 的安装路径,可以通过环境变量或者服务注册信息反查
- 确认 GPCC 使用的数据库名和 schema 名,这个信息通常在配置文件里
- 确认集群当前没有正在执行的重大任务,避免卸载操作和业务操作冲突
- 记录当前 GPCC 的版本号,方便后续如果需要重装时选择对应版本
这些信息看起来琐碎,但真到卸载出问题的时候,每一条都能帮你快速定位。特别是数据库名和 schema 名,很多人装的时候随手设的,过几个月就忘了,卸载时找不到元数据在哪,只能一个个库去翻。
3. 停服务:卸载的第一步也是最容易漏的一步
3.1 找到 GPCC 服务的真实名称
GPCC 的服务名称在不同安装方式下可能不一样。通过官方安装包安装的,服务名通常和产品名相关;通过手动部署的,可能是自定义的名称。查找方法有几个:
# 方法一:通过进程查找 ps -ef | grep -i gpcc ps -ef | grep -i "command center" # 方法二:通过端口查找(GPCC 默认 Web 端口通常是 28080 或自定义) netstat -tlnp | grep 28080 # 方法三:通过系统服务列表查找 systemctl list-units | grep -i gpcc service --status-all | grep -i gpcc这三个方法我建议都跑一遍,因为有时候进程名和服务名对不上,只查一个容易漏。比如进程可能叫gpccwebserver,但服务注册名是gpcc-web,你只查服务列表就找不到进程,只查进程就不知道服务注册名。
3.2 停止顺序:先 Web 后代理
停服务的顺序也有讲究。正确的做法是先停 Web 服务端,再停各节点的数据采集代理。原因很简单:Web 服务端会主动去拉取代理的数据,如果你先停了代理,Web 端会不断报错重试,日志里刷一堆连接失败的信息,虽然不影响卸载,但看着闹心,而且可能触发某些告警。
停止 Web 服务的命令取决于你的部署方式:
# 如果是 systemd 管理的服务 systemctl stop gpcc-web.service # 如果是 init.d 脚本 /etc/init.d/gpcc-web stop # 如果是手动启动的进程,找到 PID 后 kill -TERM <pid>用kill -TERM而不是kill -9,给进程一个优雅退出的机会。GPCC 的 Web 服务在退出时会做一些清理工作,比如关闭数据库连接池、刷新缓存到磁盘。直接-9强杀可能导致缓存数据丢失或者连接没有正常释放。
代理的停止需要在每个 Segment 节点上操作。如果你有自动化工具,可以批量执行;如果没有,就逐个节点登录处理。代理进程通常叫gpccagent或者类似的名称,停止方式和 Web 服务类似。
3.3 确认服务真正停止的验证方法
停完之后别急着进行下一步,先验证一下:
# 确认进程没了 ps -ef | grep -i gpcc | grep -v grep # 确认端口释放了 netstat -tlnp | grep 28080 # 确认服务状态 systemctl status gpcc-web.service三条都返回空或者显示 inactive,才算真正停干净。我遇到过一种情况:进程显示停了,但端口还被一个僵尸进程占着,ps看不到,netstat能看到。这种情况通常是父进程没退干净,需要找到父进程一并处理。
注意:如果停服务时提示权限不足,不要直接切到 root 硬来。先确认当前用户是否在 GPCC 的管理组里,用正确的用户身份操作,避免后续文件权限混乱。
4. 清理数据库元数据:别让监控数据变成垃圾
4.1 定位 GPCC 使用的数据库和 schema
GPCC 的元数据存储在一个指定的数据库里,通常是一个独立的库,比如叫gpcc或者gpperfmon。schema 名一般是gpcc或者public。定位方法:
# 查看 GPCC 配置文件,通常在安装目录的 conf 子目录下 cat $GPCC_HOME/conf/gpcc.conf | grep -i database cat $GPCC_HOME/conf/gpcc.conf | grep -i schema如果配置文件找不到了(比如你已经删了安装目录),可以通过数据库端反查:
-- 列出所有数据库 \l -- 连接到疑似库,查看 schema \dn -- 查看 schema 下的表 \dt gpcc.*GPCC 的元数据表通常有固定的命名规律,比如gpcc_metrics、gpcc_alerts、gpcc_config之类的。看到这些表基本就能确认是 GPCC 的库。
4.2 删除元数据的正确 SQL 操作
确认库和 schema 之后,删除操作本身不复杂,但有几个细节要注意:
-- 先断开所有连接到该库的会话,避免删除时被阻塞 SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'gpcc' AND pid <> pg_backend_pid(); -- 删除 schema(会级联删除 schema 下所有对象) DROP SCHEMA IF EXISTS gpcc CASCADE; -- 如果整个库都是 GPCC 专用的,可以直接删库 DROP DATABASE IF EXISTS gpcc;这里的关键点是CASCADE和pg_terminate_backend。不加CASCADE,如果 schema 下有对象依赖,删除会失败;不断开连接,删除操作可能被其他会话阻塞,等半天没反应。
4.3 删库还是删 schema:一个需要权衡的选择
到底删库还是只删 schema,取决于这个库是不是 GPCC 专用的。
如果这个库从创建之初就是给 GPCC 用的,里面没有其他业务数据,那直接删库最干净。但如果这个库里还混着其他东西,比如你当初图省事把 GPCC 的元数据和其他监控数据放在同一个库里,那就只能删 schema,保留库本身。
我个人的建议是:安装 GPCC 时就给它一个独立的库,卸载时直接删库,省心。如果已经混在一起了,删 schema 之前先用\dt和\dn仔细确认一遍,别把业务表误删了。
还有一个容易忽略的点:GPCC 可能在多个数据库里都建了对象。比如主元数据在一个库,但某些扩展功能会在其他库里建辅助表。卸载前最好全局搜一下:
-- 在所有库里查找 GPCC 相关的表 SELECT schemaname, tablename, tableowner FROM pg_tables WHERE tablename LIKE 'gpcc%' OR schemaname LIKE 'gpcc%';这个查询需要在每个库里跑一遍,或者用集群级别的查询工具。确认没有遗漏之后再动手删除。
5. 注销系统服务与清理集成配置
5.1 服务注销的完整流程
服务注销分两步:先停止(前面已经做了),再取消注册。
# systemd 方式 systemctl disable gpcc-web.service rm -f /etc/systemd/system/gpcc-web.service systemctl daemon-reload # init.d 方式 chkconfig --del gpcc-web # 或者 update-rc.d -f gpcc-web remove rm -f /etc/init.d/gpcc-webdaemon-reload这一步很多人会忘。不执行的话,systemd 的缓存里还留着旧的服务定义,虽然文件删了,但systemctl list-units还能看到,状态显示为 not-found,看着别扭,而且可能影响后续操作。
5.2 集成配置文件的清理范围
GPCC 和 Greenplum 集群的集成配置分散在几个地方:
- GPCC 安装目录下的
conf子目录,包含数据库连接、端口、认证等配置 - Greenplum 集群的配置目录,可能有 GPCC 相关的扩展配置
- 环境变量文件,比如
.bashrc、.bash_profile里可能设置了GPCC_HOME等变量 - 系统级别的配置文件,比如
/etc/profile.d/下的相关脚本
清理时逐项检查,不要只删安装目录就完事。环境变量不清理的话,下次登录时GPCC_HOME还指向一个不存在的路径,虽然不报错,但容易让人困惑。
# 检查环境变量 env | grep -i gpcc env | grep -i gpperfmon # 检查 shell 配置文件 grep -i gpcc ~/.bashrc ~/.bash_profile /etc/profile 2>/dev/null5.3 那些藏在角落里的残留文件
除了主要组件,GPCC 还会在系统里留下一些零散文件:
- 日志文件:通常在
/var/log/或者安装目录的log子目录 - 临时文件:
/tmp下可能有 GPCC 运行时产生的临时文件 - PID 文件:
/var/run/或者安装目录下 - 缓存文件:某些版本会在用户主目录下建缓存目录
这些文件不影响功能,但占空间,而且如果残留的 PID 文件里记录了一个已经被复用的 PID,下次启动其他服务时可能产生误判。清理时顺手处理掉:
# 查找残留文件 find /tmp -name "*gpcc*" -o -name "*gpperfmon*" 2>/dev/null find /var/log -name "*gpcc*" 2>/dev/null find /var/run -name "*gpcc*" 2>/dev/null6. 卸载后的验证:怎么确认真的干净了
6.1 进程与端口层面的验证
卸载完成后,做一轮全面检查:
# 进程检查 ps -ef | grep -i gpcc | grep -v grep ps -ef | grep -i gpperfmon | grep -v grep # 端口检查 netstat -tlnp | grep 28080 ss -tlnp | grep 28080 # 服务检查 systemctl list-units | grep -i gpcc service --status-all 2>/dev/null | grep -i gpcc全部返回空,说明进程和服务层面干净了。
6.2 数据库层面的验证
-- 确认 schema 没了 \dn -- 确认相关表没了 SELECT schemaname, tablename FROM pg_tables WHERE tablename LIKE 'gpcc%'; -- 确认没有残留的连接 SELECT datname, count(*) FROM pg_stat_activity WHERE datname = 'gpcc' GROUP BY datname;如果之前删的是 schema 而不是库,库本身还在,但里面应该没有任何 GPCC 相关的对象了。
6.3 文件系统层面的验证
# 确认安装目录已删除 ls -la $GPCC_HOME 2>/dev/null # 确认没有残留的配置引用 grep -r "gpcc" /etc/ 2>/dev/null | head -20 grep -r "gpperfmon" /etc/ 2>/dev/null | head -20文件系统层面的检查主要是防止"删了主目录但配置文件还在"的情况。特别是/etc/下的引用,不清理的话,某些系统操作可能会尝试读取一个不存在的配置,产生不必要的报错。
6.4 重启验证:最彻底的确认方式
如果条件允许,做一次系统重启,然后重新跑一遍上面的检查。重启能暴露那些"运行时看不出来,重启后才冒出来"的问题,比如服务自启配置没清干净、临时文件被重新创建等。
重启后如果所有检查都通过,那就可以确认卸载干净了。如果还有残留,根据残留的类型回到对应章节重新处理。
7. 几个我踩过的坑和对应的处理经验
7.1 卸载后重装报端口占用
这个坑我踩过两次。第一次是卸载时 Web 服务进程没停干净,第二次是停了一个进程但还有子进程占着端口。处理方法是:
# 找到占用端口的进程 lsof -i :28080 fuser -n tcp 28080 # 如果确认是残留进程,强制结束 kill -9 <pid>但要注意,kill -9是最后手段。先尝试kill -TERM,等几秒,不行再-9。而且杀之前确认这个 PID 确实是 GPCC 的残留进程,别误杀了其他服务。
7.2 元数据删除不彻底导致新装失败
有一次我删了 schema,但忘了删库级别的扩展或者自定义函数,结果重装时 GPCC 的初始化脚本检测到已存在的对象,报冲突错误。处理方法是:
-- 查看库里所有对象,包括函数、扩展、类型等 \df gpcc.* \dx \dT gpcc.* -- 逐一清理 DROP FUNCTION IF EXISTS gpcc.xxx CASCADE; DROP EXTENSION IF EXISTS xxx CASCADE;这个坑的教训是:删元数据不能只看表,函数、扩展、自定义类型、序列都要检查。最稳妥的方式还是直接删库,前提是这个库是 GPCC 专用的。
7.3 多节点环境下的代理清理遗漏
GPCC 的代理是分布在多个节点上的。如果集群有 10 个 Segment 节点,你只清理了主节点和其中几个,剩下的节点上的代理还在跑。这些代理会尝试连接已经删掉的元数据库,不断报错,日志刷得飞快。
处理方法是写一个批量脚本,遍历所有节点执行停止和清理操作:
#!/bin/bash # 假设节点列表在 hosts 文件里 for host in $(cat hosts); do echo "处理节点: $host" ssh $host "ps -ef | grep gpccagent | grep -v grep | awk '{print \$2}' | xargs -r kill -TERM" ssh $host "rm -rf /path/to/gpcc/agent" done执行前先在测试环境验证脚本,确认节点列表完整,避免漏节点或者误操作。
7.4 卸载后环境变量导致的诡异问题
环境变量没清理,最典型的表现是:你重装了一个新版本的 GPCC 到不同路径,但登录后GPCC_HOME还指向旧路径,导致命令找不到或者加载了错误的配置。
# 检查所有可能的环境变量文件 grep -rn "GPCC_HOME\|GPCC" ~/.bashrc ~/.bash_profile ~/.profile /etc/profile /etc/profile.d/ 2>/dev/null找到后手动编辑删除相关行,然后重新登录或者source一下使配置生效。
8. 卸载流程的完整清单与执行建议
把前面所有内容浓缩成一份可执行的清单,按顺序操作:
- 确认环境:登录用户权限、安装路径、数据库名、schema 名、版本号
- 停止 Web 服务:根据部署方式选择 systemctl、init.d 或 kill
- 停止各节点代理:逐节点或批量执行
- 验证服务停止:进程、端口、服务状态三重确认
- 清理数据库元数据:断开连接、删除 schema 或库、检查残留对象
- 注销系统服务:disable、删文件、daemon-reload
- 清理集成配置:安装目录、环境变量、系统配置文件
- 清理残留文件:日志、临时文件、PID 文件、缓存
- 全面验证:进程、端口、服务、数据库、文件系统
- 重启验证:最彻底的确认方式
这份清单看起来步骤多,但实际操作起来,熟练之后十分钟以内能完成。关键是要按顺序来,每一步都确认到位再进下一步。我见过太多人图快,跳步操作,结果后面花几倍时间排查残留问题。
提示:如果是在生产环境卸载,建议先在测试环境完整走一遍流程,确认没有遗漏和副作用之后再在生产环境执行。生产环境的卸载最好安排在业务低峰期,并提前通知相关使用方。
最后分享一个个人习惯:每次卸载完,我会把整个操作过程的关键命令和输出记录到一个文档里,包括遇到的报错和处理方式。下次再遇到类似场景,直接翻记录,比重新查文档快得多。而且不同版本的 GPCC 卸载细节有差异,这些记录积累下来,就是自己的经验库。