本文分析 OB 数据库在服务器重启后自动拉起的原理。
起因是客户有一次服务器重启后 OB 没有拉起,然后多次重启测试又拉起了。于是客户想知道 OB 进程是哪里拉起的。仔细一分析发现 OB 产品在这块设计还有一段曲折的历史。
本文案例 OCP 版本不低于 4.4.0 ,OB 版本不低于 4.2.5 ,早期版本可能也有或者没有,这里就不研究了。
OB 进程宕机场景
首先从一个简单的场景入手。如果服务器没有宕机,只是 OB 进程自己宕机了,是否会自动拉起?又是谁拉起的?
OB 进程名叫 observer
,这里直接杀进程。
kill -9 $(pidof observer)
过了差不多 1 分钟后, OB 进程又自动起来了。

这个 OB 进程自动拉起,是 OCP 的【预案管理】的行为。当 OCP 发现 OB 进程不可用发出告警的时候,会自动执行预案。

OCP 里会有个预案执行历史。

点击“查看任务”,可以看执行细节,就是告警信息。

这里注意预案执行结果是“成功”。如果不成功,则必定有其他原因导致 OB 进程拉起失败。这个分析不是本文重点。
如果没有预案执行历史,则说明 OCP 没有拉起 OB 进程。为了确认这点,再看一下 OCP Agent 日志。
cd /home/admin/ocp_agent/log
grep "/home/admin/oceanbase/bin/observer" *.log |grep -v POST
[root@server61 log]# grep "/home/admin/oceanbase/bin/observer" *.log |grep -v POST
......
mgragent.log:2026-06-06T16:17:06.12835+08:00 INFO [1574,ad36bf661044e2de] caller=shell/exec.go:125:execute: execute shell command start, command=Command{user=admin, program=/bin/bash, outputType=combined, cmd=cd /home/admin/oceanbase; ulimit -s 10240 -u 655350 -n 655350 -c unlimited; LD_LIBRARY_PATH=/home/admin/oceanbase/lib:$LD_LIBRARY_PATH LD_PRELOAD='' /home/admin/oceanbase/bin/observer, timeout=10s} fields:, duration="114.89µs"
mgragent.log:2026-06-06T16:17:06.2824+08:00 INFO [1574,ad36bf661044e2de] caller=shell/exec.go:180:execute: execute shell command end, command=Command{user=admin, program=/bin/bash, outputType=combined, cmd=cd /home/admin/oceanbase; ulimit -s 10240 -u 655350 -n 655350 -c unlimited; LD_LIBRARY_PATH=/home/admin/oceanbase/lib:$LD_LIBRARY_PATH LD_PRELOAD='' /home/admin/oceanbase/bin/observer, timeout=10s} fields: duration=154.167428ms
mgragent.log:2026-06-06T16:17:06.44681+08:00 INFO [1574,fa36076a39e5ade7] caller=mgragent/system_handler.go:24:getProcessInfoHandler: get process info done fields:, name=observer, skipPorts=false, processes="[ProcessInfo{pid: 20259, name: observer, cmdLine: home/admin/oceanbase/bin/observer, username: admin, createTime: 2026-06-06 16:17:05 +0800 CST, elapsedTime: 1378}]"
mgragent.log:2026-06-06T16:17:11.59114+08:00 INFO [1574,7829498d81131605] caller=mgragent/system_handler.go:24:getProcessInfoHandler: get process info done fields:, name=observer, skipPorts=false, processes="[ProcessInfo{pid: 20259, name: observer, cmdLine: home/admin/oceanbase/bin/observer, username: admin, createTime: 2026-06-06 16:17:05 +0800 CST, elapsedTime: 6509}]"
[root@server61 log]#
如果预案自动拉起失败,手动拉起方法如下:
su - admin
export LD_LIBRARY_PATH=/home/admin/oceanbase/lib:$LD_LIBRARY_PATH LD_PRELOAD=''
cd /home/admin/oceanbase && bin/observer
推荐用相对路径启动,这样可以确保你是在正确的目录下启动。
服务器宕机重启场景
服务器宕机重启命令:reboot
。 通常重启后会自动加载一序列服务。OB 的进程自动拉起就在这些服务里。
早期版本写在 rc-local 服务里。
rc-local 服务
当主机重启后,首先确认一下主机启动的准确时间。
uptime -s
[root@server61 ~]# uptime -s
2026-06-06 16:30:19
查看 rc-local
服务内容。
[root@server61 ~]# systemctl cat rc-local | grep . |grep -v '^#'
[Unit]
Description=/etc/rc.d/rc.local Compatibility
ConditionFileIsExecutable=/etc/rc.d/rc.local
After=network.target
[Service]
Type=forking
ExecStart=/etc/rc.d/rc.local start
TimeoutSec=0
RemainAfterExit=yes
服务执行脚本在文件 /etc/rc.d/rc.local
文件中。
[root@server61 ~]# ls -lrth etc/rc.local
lrwxrwxrwx. 1 root root 13 Jan 8 20:07 etc/rc.local -> rc.d/rc.local
[root@server61 ~]# ls -lrth etc/rc.d/rc.local
-rwxr-xr-x 1 root root 1.2K Mar 26 15:09 etc/rc.d/rc.local
[root@server61 ~]#
[root@server61 ~]# cat etc/rc.local | grep . |grep -v '^#'
touch var/lock/subsys/local
/usr/local/bin/set_deadline.sh
echo never > sys/kernel/mm/transparent_hugepage/enabled
/usr/local/sbin/set_nic_irq_ob.sh start
/usr/local/bin/auto_start_ob.sh >> var/log/ob.autostart.log 2>&1 &
/usr/local/bin/set_cpufreq.sh
sysctl -e -p || sysctl -p
echo tsc > sys/devices/system/clocksource/clocksource0/current_clocksource
[[ -f home/admin/ens192-speed.mock ]] || echo 10000 > home/admin/ens192-speed.mock
for ((i=0;i<60;i++)); do [[ -f sys/class/net/ens192/speed ]] && { mount --bind /home/admin/ens192-speed.mock sys/class/net/ens192/speed && break; } || sleep 5; done; [[ $i -eq 60 ]] && echo 'set nic speed timeout: nic not ready after 5 minutes.'
[root@server61 ~]#
操作系统默认在这个文件里不会写这么多内容,这里大部分内容都是 OB 产品(OAT 或者 OCP ) 塞进去的。塞进去的理由有设置 SSD 调度策略为 deadline
、禁用透明大页、设置网卡中断、自动启动 OB、CPU 频率设置、内核参数设置、时钟源设置、网卡速率模拟等。为什么我用‘塞’这个字眼呢,因为这些脚本的测试并不充分,它导致 rc-local
服务执行可能没有正确退出。我看了客户生产环境,好几台机器都出现 rc.local
服务异常退出。
grep "rc.local" /var/log/messages
Jun 6 16:30:24 server61 systemd: rc-local.service: control process exited, code=exited status=1
Jun 6 16:30:24 server61 systemd: Failed to start etc/rc.d/rc.local Compatibility.
Jun 6 16:30:24 server61 systemd: Unit rc-local.service entered failed state.
Jun 6 16:30:24 server61 systemd: rc-local.service failed.

这最后一段报错我在多个客户环境都看到,其他信息就可能彼此不一样。 通过这个日志我们间接推测 rc.local
服务脚本里的执行情况。我们主要目的是推测那个 /usr/local/bin/auto_start_ob.sh
脚本到底有没有跑。它不会有日志记录,但是从前后的脚本记录可以推测。每个客户情况都不一样,这就是糟糕的地方。
脚本 auto_start_ob.sh
这个脚本从 OCP 早期版本就有。不同版本的 OCP 其脚本内容可能有些变化。这里展示的是 4.4.0 以后版本的内容。内容太长,我们只看最后 20 行。
[root@server61 ~]# tail -n 20 usr/local/bin/auto_start_ob.sh
if systemctl list-units -t service | grep -qw ocp_agent; then
# from ocp 420, ocp_agent handles all auto start logic, and service file may not in normal dir
ts_echo "ocp_agent is managed by systemd, skip auto start step"
exit
fi
# 兼容ocp4.2.0、4.2.1找不到service的bug
current_version=$(rpm -q --queryformat '%{VERSION}\n' ocp-agent 2>/dev/null)
if [[ $current_version =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] && [[ "$(echo -e "$current_version\n4.2.0" | sort -V | head -n1)" == "4.2.0" ]]; then
echo"ocp_agent is managed by systemd, skip auto start step"
exit
fi
wait_until_startup_finished
autostart_obproxy
autostart_ob
autostart_ocp_agent
autostart_obagent
[root@server61 ~]#
脚本大概意思:
如果存在服务 ocp_agent
,就退出脚本,不执行后面的逻辑。这是 OCP 4.2.0 后的变化。OCP 自 4.2.0 后通过ocp_agent
去自动拉起 OB 进程。如果是 OCP 4.2.0/4.2.1 版本,生成的 ocp_agent
服务文件可能在某些系统上通过 systemd 认不到。这里直接看ocp_agent
软件版本,命中 BUG 也会自动退出。自动拉起 ODP 进程/ OB 进程 OCP AGENT 进程 OB AGENT 进程。
如果要判断是不是这个脚本拉起的 OB 进程,可以看脚本的日志文件时间和内容。
[root@server61 ~]# ls -lrth var/log/ob.autostart.log
-rw-r--r-- 1 root root 172 Jun 6 15:33 var/log/ob.autostart.log
[root@server61 ~]#
[root@server61 ~]# tail -n 5 var/log/ob.autostart.log
[2026-01-15 18:36:43.270169] [ocp_agent is managed by systemd, skip auto start step]
[2026-06-06 15:33:18.793270] [ocp_agent is managed by systemd, skip auto start step]
[root@server61 ~]#
[root@server61 ~]# uptime -s
2026-06-06 16:30:19
我这个测试环境还算符合预期,这个日志文件能看到内容和最后修改时间跟重启后的时间比较符合。
在客户的环境里,这个文件的最后一次修改时间跟重启时间点不符合,并且没有内容。 如果文件没有内容,排除掉人为清除掉内容外,可以判断为这个脚本没有执行。这个就很诡异了,说明前面执行就报错了。不过 OCP 产品也不在乎这个了,因为本来就没打算再用这个脚本去启动 OB 进程了。所以,产品连“打扫一下”的想法都没有,仿佛厨房水槽下的排水管设计。
[root@server61 ~]# uptime -s
2026-06-06 16:30:19
[root@server61 ~]# ps -p `pidof observer` -o pid,user,lstart,etime,cmd
PID USER STARTED ELAPSED CMD
1716 admin Sat Jun 6 16:30:27 2026 30:01 home/admin/oceanbase/bin/observer
[root@server61 ~]#
OB 进程确实启动了,也确认不是脚本 auto_start_ob.sh
启动的。 我这里测试环境比较顺利,脚本日志里提到了关键字 ocp_agent
。所以,接着看这个服务。
服务 ocp_agent
大概从 OCP 4.2.0 版本开始,OCP 将 ocp_agent
的启动做成了 systemd
服务。
[root@server61 ~]# systemctl list-units -t service |grep ocp_agent
ocp_agent.service loaded active running start ocp_agent
查看一下服务文件内容。
[root@server61 ~]# systemctl cat ocp_agent.service
# usr/lib/systemd/system/ocp_agent.service
[Unit]
Description=start ocp_agent
After=network.target syslog.target rc-local.target
[Service]
Type=forking
ExecStart=/home/admin/ocp_agent/bin/ocp_agentctl start
ExecStop=/home/admin/ocp_agent/bin/ocp_agentctl stop
ExecReload=/home/admin/ocp_agent/bin/ocp_agentctl restart
RemainAfterExit=yes
KillMode=none
[Install]
WantedBy=multi-user.target
首先这个是一个 systemd 服务文件,不是 target 文件。其次这个服务定义了 ocp_agent
的启动顺序在 network.target syslog.target rc-local.target
之后。
刚开始我还认为 rc-local.target
就是 rc-local.service
。顿时陷入疑惑。 rc.local
脚本逻辑里有判断 ocp_agent
服务。判断方法如下:
[root@server61 ~]# systemctl list-units -t service |grep -qw ocp_agent
[root@server61 ~]# systemctl list-units -t service |grep -w ocp_agent
ocp_agent.service loaded active running start ocp_agent
如果 rc.local
发现没有 ocp_agent
服务,就会走 auto_start_ob
后面的自动拉起逻辑。这里又说 ocp_agent
服务会在 rc-local
后启动。 这逻辑明显有矛盾。
后来发现 rc-local.target
不等于 rc-local.service
。实际上,根本不存在所谓 rc-local.target
。
[root@server61 ~]# systemctl list-units |grep rc-local
● rc-local.service loaded failed failed /etc/rc.d/rc.local Compatibility
操作系统只有 rc-local.service
。
[root@server61 ~]# systemctl cat rc-local.service | grep . |grep -v '^#'
[Unit]
Description=/etc/rc.d/rc.local Compatibility
ConditionFileIsExecutable=/etc/rc.d/rc.local
After=network.target
[Service]
Type=forking
ExecStart=/etc/rc.d/rc.local start
TimeoutSec=0
RemainAfterExit=yes
在这个服务文件里也提到一个 network.target
。这个可是确实存在的。
[root@server61 ~]# systemctl list-units |grep -w network
network.service loaded active exited LSB: Bring up/down networking
rhel-domainname.service loaded active exited Read and set NIS domainname from /etc/sysconfig/network
rhel-import-state.service loaded active exited Import network configuration from initramfs
network-online.target loaded active active Network is Online
network.target loaded active active Network
所以,服务 ocp_agent
的启动顺序跟 rc-local
服务,没有定义先后关系。那么实际启动顺序就是扫描 units 文件的顺序了。
虽然 ocp_agent
字母排名在前,systemd 启动各个服务并不一定要等待每个服务文件,这取决于 systemd
各个服务文件的具体定义。我们可以通过操作系统日志 /var/log/messages
去确认它们的启动顺序。
grep -Hn "ocp_agent" /var/log/messages |egrep -i "starting|started|failed"
grep -Hn "rc.local" /var/log/messages |egrep -i "starting|started|failed"
这里会查出我多次重启的记录,正好看看顺序。


这里有 2 次重启主机记录,根据时间不一定能严格看到 2 个服务启动顺序,可以从日志在文件里记录号判断顺序。 服务 ocp_agent
比 rc-local
服务几乎是同时启动,但是确实晚一步。不过,可以确定在 rc.local
执行到 auto_start_ob.sh
脚本的时候, ocp_agent
服务肯定是启动中或已经启动。
再查看 ocp-agent
进程的运行日志。
cd /home/admin/ocp_agent/log
grep "/home/admin/oceanbase/bin/observer" *.log |grep -v POST

从这个图能看到 2 次重启服务器后 ocp_agent
拉起 OB 进程的日志,时间点跟重启时间都能对上。
所以,结论是服务器重启后 ocp_agent
进程会拉起一次 OB 进程。这个在 OCP 页面里不会看到记录,只能在 mgragent.log
里看到。
至于客户那次服务器重启没有自动拉起 OB 进程,大概率是 OB 进程拉起后失败退出了。这个在测似环境也经常见。总有一些外部环境变化导致 OB 进程重启后拉不起来。比如说内存不足、或日志空间满了 或 OB 文件目录权限被改了等等。
问题到此基本得到解释了。不过这个 ocp_agent
服务设计的还是不完美。
查看服务状态,为 "running start" 。
[root@server61 log]# systemctl list-units -t service |grep ocp_agent
ocp_agent.service loaded active running start ocp_agent
此后,如果你在 OCP 里重启主机的 Agent 后,这个 ocp_agent
服务的状态就会有一点变化。

再次查看服务状态,变成 "active exited" 了。
[root@server61 log]# systemctl list-units -t service |grep ocp_agent
ocp_agent.service loaded active exited start ocp_agent
这个设计的问题在于用主机 SYSTEMD 和 OCP 同时去管理 ocp_agent
进程带来了冲突。
结论
在早期的版本里, OB 服务器重启是需要 DBA 手动拉起 OB 进程的。估计后来有客户提需求,OCP 才做了自动拉起的逻辑。先用脚本 auto_start_ob.sh
拉起 OB/ODP/OCPAGENT/OBAGENT 相关进程。后来又改为通过 ocp_agent
进程去做这个。
其实方案有多种。个人认为更好的方法是将 OB 进程做成 systemd
服务,自动启动更好,这样就不依赖 OCP 产品了。特别是单机版客户后面都没有 OCP 产品了(还有一说 OCP 后面可能收费)。当然,如果把 OB 进程启动做成 systemd
服务,也会面临一样如果跟 OCP 管理冲突了,状态也会有不对。
再往深处说一些,如果把 OB/ODP/OCPAGENT 进程都做成 systemd
服务并且还做成如果服务退出自动拉起,那就不依赖 OCP 了。现有的设计,如果手动将 OCP AGENT 相关进程都 KILL 掉(模拟 AGENT 包括守护进程自己出问题退出),那么这个进程就彻底歇菜了。OCP 的性能采集和 OB 进程自动拉起机制就彻底失效。








