
1. 为什么卸载 GPCC 比安装更值得单独写一篇装过 Greenplum Command Center下面统一简称 GPCC的人都知道安装过程虽然步骤多但官方文档给得还算清楚照着走基本能跑起来。可一旦涉及到卸载情况就完全不一样了——文档里往往只有寥寥几句甚至不同版本之间的卸载方式差异还挺大。我见过太多人在这上面翻车有人直接删了安装目录结果 Web 服务还在后台跑着有人把数据库里的元数据表删了但系统服务没停重启之后又冒出来还有人卸载完发现 Greenplum 集群本身的监控数据采集进程还在偷偷占资源。这篇内容就是专门解决这个问题的。我会把 GPCC 卸载这件事从头到尾拆开讲清楚它到底由哪几部分组成、每一部分卸载时会发生什么、正确的卸载顺序是什么、卸载完怎么验证干净了、以及那些官方文档不会告诉你的坑。不管你是刚接触 GPCC 的新手还是已经用过一段时间想彻底清理环境的老手这篇都能直接拿来当操作手册用。需要先说明一点GPCC 的卸载之所以比安装更容易出问题核心原因在于它不是一个单一软件而是由多个组件拼起来的——Web 前端服务、后台数据采集代理、数据库内的元数据 schema、系统级服务注册、以及和 Greenplum 集群的集成配置。这五块东西分散在不同的位置卸载时如果只处理其中一部分剩下的就会变成幽灵组件平时看不出来关键时刻给你添乱。提示在做任何卸载操作之前先确认你手头有 GPCC 的安装版本号和管理员权限。不同版本的卸载命令和路径会有差异盲目操作可能导致 Greenplum 集群本身受影响。2. GPCC 到底装了哪些东西先搞清楚卸载对象2.1 五个核心组件及其落盘位置很多人卸载不干净根本原因是对 GPCC 的组件构成没有清晰认知。我把它拆成五块每一块都有典型的落盘位置和卸载方式。组件作用典型位置卸载方式Web 服务端提供监控页面和 APIGPCC 安装目录下的 web 子目录停止服务后删除目录数据采集代理从集群各节点收集指标各 Segment 节点的代理目录逐节点停止并清理数据库元数据存储监控配置和历史数据指定数据库内的 schemaSQL 方式删除系统服务注册开机自启和进程守护系统服务管理目录服务管理命令注销集成配置与集群的连接和认证配置集群配置目录及环境变量手动清理配置文件这五块里面前三块是实体后两块是影子。实体部分你删了目录就能看到效果影子部分不清理的话表面上没事但系统重启或者集群做某些操作时就会暴露问题。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 使用的数据库和 schemaGPCC 的元数据存储在一个指定的数据库里通常是一个独立的库比如叫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 卸载细节有差异这些记录积累下来就是自己的经验库。