资讯动态

Ubuntu下PostgreSQL服务状态检查:从systemctl到pg_isready的完整手册

发布时间:2026/10/1 11:32:49 来源:尧图企业网站定制
管理 PostgreSQL 的时候恐怕每个人都碰到过这么一幕客户端连不上应用一直报错你跑到服务器上敲systemctl status postgresql看到一行绿色的active (running)心想服务明明在跑可数据库就是连不上。这个矛盾背后其实是 Ubuntu 下 PostgreSQL 服务状态检查的复杂性。作为在 Ubuntu 上维护 PostgreSQL 很长时间的人我来把这套状态检查方法从头到尾捋一遍——systemctl、pg_isready、端口监听、cluster 管理命令各有各的用途它们回答的其实不是同一个问题。这篇文章不是简单丢几个命令让你复制而是把每种状态检查方法背后的逻辑、常见坑、组合排查思路都讲清楚。无论你是刚开始接触 PostgreSQL 的新手还是已经被线上故障折磨过的运维这套方法都能帮你更快定位“服务到底挂没挂、挂在哪一层”。1. 服务状态的本质先搞懂 Ubuntu 上的 PostgreSQL 是怎么被拉起来的1.1 systemd 与 PostgreSQL 服务的关系在 Ubuntu 上PostgreSQL 大多由 systemd 管理但这和你在 CentOS 上看到的 service 体系不太一样。Ubuntu 的 PostgreSQL 包使用了一套 cluster 管理机制同一台机器上可以存在多个版本、多个实例每个实例有独立的端口、数据目录和配置文件。默认安装时它会自动初始化一个名为 main 的 cluster比如16/main。平时你执行systemctl status postgresql看到的是聚合单元的状态。真正干活的是具体的 cluster 单元命名规则类似postgresql16-main.service。如果你有多个 clusterpostgresql.service只是负责把所有已经注册的 cluster 单元都拉起来。这个设计在 Debian/Ubuntu 系里很典型也是很多人状态判断出错的根源——聚合单元显示 active但某个具体的 cluster 可能早就 failed 了。所以检查状态时我的第一建议永远是不仅看postgresql还要看postgresql版本-main。先搞清楚系统里有哪些 cluster再谈状态。1.2 检查前必做的准备确认安装方式与版本在 Ubuntu 上检查 PostgreSQL 状态之前先确认你这套 PostgreSQL 是怎么装的。方法不同可用命令和默认行为差异很大。官方 apt 仓库PGDG安装的 PostgreSQL一般自带 systemd 单元源码编译安装的可能压根没有 systemd 单元需要你手动管理Docker 容器里跑的那 unit 概念就更不一样了系统里可能根本没有 PostgreSQL 的 systemd 服务。确认方法很简单执行pg_lsclusters看输出。这个命令是 Ubuntu 的 postgresql-common 包提供的专门用来管理本地 PostgreSQL cluster。我最常用的方式pg_lsclusters输出会列出版本、Cluster 名、端口、状态、属主、数据目录和日志路径。例如Ver Cluster Port Status Owner Data directory Log file 16 main 5432 online postgres /var/lib/postgresql/16/main /var/log/postgresql/postgresql-16-main.log看到Status是online说明这个 cluster 已经被 systemd 管理起来了。如果看到down或offline那不管systemctl status postgresql显示什么实际对外提供服务的进程大概率没起来。这一步是整个状态检查的地基地基没打好后面看什么都容易误判。2. 五类最常用的状态检查方法一次全讲透2.1 systemctl 命令全解析不只是看颜色systemctl status postgresql是新手最爱用的命令因为它有颜色、有动画看起来直观。但这里有个细节如果你没加 sudo很多信息会缺失进程 PID、内存占用、CGroup 内容你都看不到。我一般直接执行sudo systemctl status postgresql16-main --no-pager--no-pager是为了避免命令卡在交互式分页器里在脚本和远程排查时尤其好用。这条命令的输出大致包含这几个关键字段Loaded显示这个服务单元是否被加载以及 enable 状态。loaded (/usr/lib/systemd/system/postgresql.service; enabled; preset: enabled)里的 enabled 表示开机自动启动。Active这是大家最关注的部分。active (running)表示主进程仍在运行inactive (dead)表示已停止failed表示启动失败systemd 已经放弃。Main PIDPostgreSQL 主进程的 PID通常叫 postmaster。Tasks进程树里线程/进程数量包含 PostgreSQL 的辅助进程。Memory服务占用内存。CGroup显示这个 unit 管理的进程列表。如果你只想拿到一个纯粹可脚本化的状态值不要用systemctl status去 grep直接使用systemctl is-active postgresql16-main # 输出 active 或 inactive 或 failed再看开机自启systemctl is-enabled postgresql16-main记住is-active回答的是“现在是否在运行”is-enabled回答的是“下次开机是否会自动启动”。这两个概念经常被混淆。比如服务现在 active 但 disabled意味着这次 reboot 后它就不会自启到时候故障就来了。2.2 pg_isready从数据库视角进行探测systemctl回答的是“进程层面活没活”而pg_isready回答的是“数据库层面能不能接受连接”。两者有重叠但绝对是两个维度。最典型的场景PostgreSQL 主进程存活但它卡在恢复、正在启动、或者因为pg_hba.conf配置把所有连接都拒了这时systemctl依然显示 activepg_isready却会告诉你异常。基础用法pg_isready -h localhost -p 5432 -U postgres正常输出一般是localhost:5432 - accepting connections这个命令的退出码非常有用脚本化监控时可以重点依赖0服务器正在接受连接。1服务器正在运行但拒绝连接常见于启动恢复期。2服务器没有响应连 ping 都没回。3无法连接通常是端口错、服务未启动、防火墙拦截。用退出码判断状态比用字符串 match 可靠得多。我在自动化巡检脚本里几乎只用pg_isready的退出码而不是去解析日志。2.3 端口监听检查ss 一抓一个准进程活了、数据库也 ready但外部客户端还是连不上这时候就要看网络层。PostgreSQL 默认监听 5432 端口如果监听地址只绑定了本地回环远程自然连不进来。检查端口监听状态我最常用ss -ltnp | grep 5432输出类似LISTEN 0 200 127.0.0.1:5432 0.0.0.0:* users:((postgres,pid1234,fd7))这里127.0.0.1:5432表示只监听本地回环外部 IP 无法访问如果是0.0.0.0:5432或*:5432说明监听在所有地址上。很多人看到的“连接被拒”问题根因就在这里。ss命令比老牌的netstat更高效现代 Ubuntu 默认都有。如果没装可以sudo apt install iproute2带上它。除了 TCP 端口PostgreSQL 还会在/var/run/postgresql/目录下创建 Unix socket 文件文件名类似.s.PGSQL.5432。用ls /var/run/postgresql/能看到如果 socket 文件存在说明 postmaster 正常初始化了本地 socket 监听。2.4 进程和连接数观察状态检查的纵深视角ps aux | grep postgres也是老运维习惯用的方法。执行后你会看到以postgres用户运行的多个进程第一行是主进程 postmaster后面跟着多个 worker 进程比如checkpointer、background writer、walwriter、autovacuum launcher等。这一组进程共同构成了 PostgreSQL 实例。需要提醒的是看到主进程存在只说明“进程没死透”不说明它健康。比如一个被网线断掉、磁盘 IO 卡死的 PostgreSQL进程可能还在但实际无法处理查询。观察连接情况我更喜欢直接进到数据库里查SELECT count(*) FROM pg_stat_activity; SELECT datname, state, count(*) FROM pg_stat_activity GROUP BY datname, state;这里可以看到当前活跃连接数、空闲连接数、事务状态。如果连接数已经堆到max_connections上限附近客户端就会开始报 “sorry, too many clients already”这时候服务状态看似正常实际已经不可用了。2.5 psql 客户端验证最终以实际请求为准所有状态检查的终极裁判是真实执行一次查询。在服务器本机上用 psql 试一下sudo -u postgres psql -h localhost -p 5432 -c SELECT 1;如果能看到返回的1说明从客户端到服务端的整个链路是通的。巧妙在这里sudo -u postgres会切换为 postgres 系统用户使用的 Unix socket 通常不受pg_hba.conf中 host 规则的严格限制能帮你区分“数据库本身问题”还是“网络/认证配置问题”。如果这条命令报错错误信息会直接带你进入下一步排查。比如connection refused说明服务在 TCP 层就没接受连接password authentication failed说明链路通但账号认证失败no pg_hba.conf entry说明匹配到了拒绝规则。这些错误引导的价值远大于单纯看状态灯。3. 实操记录Ubuntu 上完整走一遍状态检查流程3.1 从零开始的检查清单很多新手拿到一台 Ubuntu 服务器面对一堆命令不知从哪下手。我给一个固定的排查顺序照着走基本不会漏# 1. 看聚合状态 systemctl status postgresql --no-pager # 2. 看具体 cluster 状态 pg_lsclusters # 3. 看具体 cluster 单元状态 sudo systemctl status postgresql16-main --no-pager # 4. 数据库层探测 pg_isready -h localhost -p 5432 # 5. 端口层确认 ss -ltnp | grep 5432 # 6. 真实查询验证 sudo -u postgres psql -h localhost -c SELECT 1; # 7. 查看最近日志 sudo journalctl -u postgresql16-main --no-pager -n 50这个顺序的核心思想是从系统管理层逐步往数据库内层探测每一步都回答不同层面的问题。第一步看整体、第二步看集群、第三步看具体进程、第四步看数据库心跳、第五步看网络监听、第六步看真实可用性、第七步确认根因。3.2 系统提示的细节解读执行sudo systemctl status postgresql16-main后输出末尾常常有一小段日志记录默认显示最后几行 journal 消息。很多人忽略这块其实它对判断“这个服务是正常关闭还是异常崩溃”特别有帮助。比如看到类似database system was shut down at ...说明上次是正常关闭看到database system is starting up说明正在启动过程中看到invalid record length、database system is in recovery mode那就得提高警惕可能是数据页损坏或者非正常断电导致的崩溃恢复。还要注意 unit 文件路径的区别。/lib/systemd/system/postgresql.service是模板单元/etc/systemd/system/下的覆盖文件优先级更高。如果有人在/etc/systemd/system/里放了同名的 override 文件行为就会和默认包安装不一样。检查时可以顺带看systemctl cat postgresql16-main这个命令会把该单元最终的合并配置打出来能很快发现是否被某些自定义配置覆盖了。3.3 pg_lsclusters 输出重点在哪里回到pg_lsclusters这个命令在 Ubuntu 生态里的地位被严重低估。它的核心价值在于systemd 单元按“版本-集群名”区分而pg_lsclusters是唯一一个能完整展示机器上所有 PostgreSQL 集群状态的命令。假设机器上装了 PostgreSQL 14 和 16每个版本都有自己的 main cluster可能 14 的端口是 543216 的端口是 5433。此时systemctl status postgresql会显示聚合 active但pg_lsclusters能明确显示 14 的 main 是 online、16 的 main 却是 down。如果你只操作 16不看这个命令就会误以为“服务状态没问题”。pg_lsclusters还支持手动启停某集群sudo pg_ctlcluster 16 main start sudo pg_ctlcluster 16 main stop这比直接操作 systemd 单元更贴近 Ubuntu 原生的 cluster 管理理念。它在启动时还会自动检查哪些配置需要调整避免一些不必要的启动失败。日常运维如果条件允许cluster 粒度的操作我都优先用这套工具。3.4 日志是状态检查的最终底牌状态检查的本质是缩小范围但真正定位根因几乎离不开日志。Ubuntu 下 PostgreSQL 日志主要有两个去处journal 和/var/log/postgresql/下的独立日志文件。使用 journal 查看最近的 FATAL 或 ERRORsudo journalctl -u postgresql16-main --since 1 hour ago | grep -E FATAL|ERROR使用传统日志文件sudo tail -n 100 /var/log/postgresql/postgresql-16-main.log | grep -E FATAL|ERROR|PANIC我见过的很多服务状态异常日志里第一行都会明确写下原因。比如权限错误、磁盘空间不足、配置语法错误、端口冲突。学会先看日志再动手能避免大量无意义的反复重启。重启服务通常只能解决一小部分问题真正的修复必须基于日志给出的原因去改配置或修复环境。4. 状态检查中频繁翻车的场景与排查实录4.1 服务显示 active但客户端连不进去这是排在榜首的经典故障。服务明明 active外部应用却一直报连接失败。我第一次遇到时也懵了花了不少时间才把整套逻辑理清楚。排查链路是先确认监听地址。看ss -ltnp | grep 5432如果是127.0.0.1:5432那远程连不上太正常了因为 PostgreSQL 根本没监听外部网卡。原因往往在postgresql.conf里的listen_addresses参数默认值是localhost只会监听回环地址。查看方法sudo -u postgres psql -c SHOW listen_addresses; sudo -u postgres psql -c SHOW port;如果需要监听外部地址改listen_addresses *然后 reload而不是 restart。reload 与 restart 的区别我必须强调reload 只是重新读配置文件不断开现有连接restart 会终止所有连接造成业务中断。PostgreSQL 的很多配置项支持 reload 生效端口和监听地址这类参数也支持。执行并不复杂sudo systemctl reload postgresql16-main或者进入数据库执行SELECT pg_reload_conf();此时注意如果云服务器还有安全组、Ubuntu 本机还有 UFW 防火墙也得逐一放行端口。ss显示已经在监听但外部还是connection timed out十有八九就是防火墙或安全组拦截。可以用telnet或nc从本机测试外部访问路径。4.2 服务状态直接转成 failed怎么办failed状态说明 systemd 启动该服务时反复失败已经标记为异常。这种情况下的关键动作是别急着反复start先看日志。sudo journalctl -u postgresql16-main --since today常见的失败原因我遇到过这些数据目录权限不对。PostgreSQL 数据目录必须属于 postgres 用户权限通常是 700。如果曾经用 root 操作过数据目录很可能把属主改坏导致 postmaster 无法打开文件。磁盘空间满。数据目录所在分区满了以后启动过程中会报No space left on device服务直接起不来。可以用df -h检查。配置文件语法错误。手动改过postgresql.conf或者pg_hba.conf语法写错启动时解析失败。PostgreSQL 会在日志里明确提示第几行有问题。端口冲突。另一个实例或应用程序提前占用了 5432 端口postmaster 绑定失败。修复方式对应根因权限错误用chown -R postgres:postgres修正磁盘满就清理空间配置错误修正语法后再启动。注意每改完一次再执行一次sudo systemctl start postgresql16-main并用systemctl status确认是否转为 active。经验是启动失败往往不是一次就能找到根因的要有耐心每次失败日志都会更接近真相。4.3 应用层面看到 503 / 5xx 之类的错误在应用架构里PostgreSQL 经常不直接对外暴露前面可能还有应用网关或负载均衡层。这时候客户端报 503 之类“服务不可用”的错误并不直接等价于数据库服务没起来。数据库本身 active但应用层和数据库之间的连接池耗尽、超时时间设置过短、应用线程阻塞同样会导致这类错误。我的排查建议是先回到数据库服务器用pg_isready从本机探测。如果本机接受连接再检查连接数和数据库负载。看几个关键指标SELECT count(*) FROM pg_stat_activity; SELECT state, count(*) FROM pg_stat_activity GROUP BY state;如果连接数开始逼近上限排查应用连接池配置如果查询大量堆积在active状态数据库性能可能出现问题需要进一步看慢查询和锁等待SELECT pid, state, wait_event_type, wait_event, query_start, now() - query_start AS duration FROM pg_stat_activity WHERE state active ORDER BY duration DESC;还有一种容易忽略的情况机器负载过高内存耗尽触发 OOM killer把 postmaster 进程杀了systemd 还没来得及拉起来客户端就会间歇性报错。这时候检查dmesg | grep -i oom往往能看到内核杀进程的记录。4.4 开机后服务没起来但安装时明明是默认启用的systemctl status显示 inactive手动 start 又能起来说明服务当前没有运行。问题可能出在两个地方第一enable 状态不是 enabled第二某个 cluster 没有正确纳入 systemd 管理。验证 enable 状态systemctl is-enabled postgresql16-main如果输出 disabled就把开机自启补上sudo systemctl enable --now postgresql16-main在 Ubuntu 上出现这种情况还有一个可能是有人曾用pg_ctlcluster 16 main stop停止过集群而stop会把集群标记为手动停止部分情况下会反过来影响 systemd 状态。此时用pg_ctlcluster 16 main start启动并再次pg_lsclusters查看状态是否回到 online。这类“系统明明显示没跑手动又能起来”的场景用户做状态检查时最容易绕弯路但只要想到 cluster 和 systemd 单元的关联排查路径就很短了。4.5 多版本多集群共存时状态眼花缭乱Ubuntu 下同时安装 PostgreSQL 14 和 16 完全可行但状态检查会复杂化。比如systemctl status postgresql显示 active但你没注意到 16 的 cluster 是 down结果应用连 5433 端口就一直失败。这种场景唯一的可靠办法就是坚持使用pg_lsclusters作为总览工具。它会清楚列出每个集群的端口和状态避免你对着 systemd 的聚合状态瞎猜。如果某个 cluster 不需要开机自启可以在/etc/postgresql/版本/集群名/start.conf里修改写成manual这样 systemd 就不会在开机时尝试拉起它。检查开机自启行为时这个文件值得顺手看一眼。它有三个可选值auto、manual、disabled含义和 systemd 的 enable 概念相互呼应但管理界面更直观。5. 把状态检查做成日常习惯脚本与监控5.1 一条命令快速巡检人工一步步敲命令没问题但一旦服务器数量增多效率就低了。我自己会写一个简单的巡检脚本一次检查多个维度输出明确结论。#!/bin/bash CLUSTER16/main PORT5432 echo systemd is-active systemctl is-active postgresql${CLUSTER%%/*} echo pg_lsclusters pg_lsclusters echo pg_isready pg_isready -h localhost -p $PORT echo listening port ss -ltnp | grep :$PORT | head -n 3 echo quick query check sudo -u postgres psql -h localhost -p $PORT -t -c SELECT ok; || echo query failed这个脚本我通常配合crontab或 systemd timer 每五分钟跑一次异常时将输出重定向到日志文件。关键点是脚本本身不要直接重启服务状态检查和自动修复必须分开避免在误判时做出破坏性操作。5.2 结合监控平台提前发现问题光靠手动检查很难覆盖深夜故障。有条件的话建议把服务状态接入监控平台。开源方案里 Prometheus 加 postgres_exporter 是主流pg_isready的探测结果可以通过node_exporter的 textfile collector 暴露变成可告警的指标。更轻量的做法是写一个简单的告警脚本pg_isready连续三次失败就发邮件或调用 webhook 通知。但要注意监控脚本本身不能太复杂复杂反而会引入新的故障点。我见过不少监控脚本因为权限配置错误导致每次执行都误报最终让团队对告警麻木。5.3 我个人的状态检查体会经历多次故障后我对“服务状态”这四个字的理解已经不再局限于 systemd 那个状态灯。真正的状态至少包含四个层次进程状态、数据库可连接状态、网络可达状态、真实查询可用状态。四者缺一不可任何一层出问题用户实际体验都会被影响。我现在排查 PostgreSQL 问题时几乎每次都是 systemctl、pg_isready、ss、psql 四把刀一起上快速定位到底挂在哪一层。这也算是一点点实战沉淀别看这四个命令简单组合起来使用几乎能覆盖 PostgreSQL 运维排查 80% 以上的场景。下次你再遇到“状态明明 active 但连不上”心里就有数了顺着层次一步步排查问题基本藏不住。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑