借助systemd操控GreatSQL服务全解析

利用systemd对GreatSQL服务的全面掌控

1. GreatSQL服务文件

官方所提供的 greatsql.service 文件内容如下:

[Unit]
Description=GreatSQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]

# 本文省略部分限制内容

User=mysql
Group=mysql
Type=notify
TimeoutSec=10
PermissionsStartOnly=true
ExecStartPre=/usr/local/GreatSQL-8.0.32-27-Linux-glibc2.28-x86_64/bin/mysqld_pre_systemd
ExecStart=/usr/local/GreatSQL-8.0.32-27-Linux-glibc2.28-x86_64/bin/mysqld $MYSQLD_OPTS
EnvironmentFile=-/etc/sysconfig/mysql
Restart=on-failure
RestartPreventExitStatus=1
Environment=MYSQLD_PARENT_PID=1
PrivateTmp=false

上述服务文件中,MYSQLD_OPTSMYSQLD_PARENT_PID有着怎样的作用?TypeExecStart之间存在何种关联?服务停止的逻辑是怎样的?TimeoutSec超时会出现什么状况?

2. 环境变量

[Service]
ExecStart=/data/svr/greatsql/bin/mysqld --defaults-file=/data/conf/greatsql4306.cnf $MYSQLD_OPTS
EnvironmentFile=-/data/conf/greatsql

2.1 MYSQLD_OPTS

MYSQLD_OPTS是一个特殊的环境变量,用于在启动时向 MYSQLD 进程传递额外的命令行参数,适用于需要动态调整参数的场景。

设置MYSQLD_OPTS的方式如下:

  1. 使用 systemctl 设置全局环境变量
# 进行设置
systemctl set-environment MYSQLD_OPTS="--general_log=1"
# 进行取消
systemctl unset-environment MYSQLD_OPTS
  1. 在服务文件中设置单个服务的环境变量
[Service]
Environment=MYSQLD_OPTS=--general_log=1
EnvironmentFile=-/data/conf/greatsql

2.2 Environment

  1. 在服务文件中设置 Environment
[Service]
Environment=LD_PRELOAD=/usr/local/jemalloc-5.3.0/lib/libjemalloc.so
Environment=LD_PRELOAD=/data/svr/greatsql/lib/mysql/libjemalloc.so  # 对之前同名变量进行覆盖
Environment=  # 清空所有环境变量

若同一变量被多次设置,后续的赋值会覆盖之前的值。若将此选项赋值为空字符串,则会重置环境变量列表,之前的所有设置均失效。

  1. 在服务文件中设置 EnvironmentFile
[Service]
EnvironmentFile=-/etc/sysconfig/mysql  # -表示忽略文件不存在的错误
EnvironmentFile=-/data/conf/greatsql
EnvironmentFile=  # 清空所有待读取的文件

$ cat /data/conf/greatsql
LD_PRELOAD=/data/svr/greatsql/lib/mysql/libjemalloc.so
LD_LIBRARY_PATH=/data/svr/greatsql/lib
TZ=CST
MYSQLD_OPTS=--general_log=1 --port=4307

EnvironmentFile 可以多次设置,所有匹配的文件都会被读取。若将此选项赋值为空字符串,则会清空待读取的文件列表,之前所有设置均失效。

EnvironmentFile 按顺序依次读取,后加载的变量会覆盖之前的设定,且会覆盖 Environment 中的同名变量。

Environment、EnvironmentFile 在服务启动前解析,这些变量会被直接写入服务的环境变量列表,对所有后续命令(ExecStartPre、ExecStart、ExecStartPost)可见。

如果 EnvironmentFile 指定的文件在运行时动态生成,systemd 会尝试读取它,如果文件在读取时被修改,systemd 会使用最新的内容。

3. 启动

systemd 通过 fork-exec + cgroups 的机制创建并严格管理服务进程,确保所有进程均为其子进程。

  • 采用 fork() + execve() 来生成新进程:
    • fork():创建子进程(systemd 父进程的副本)。
    • execve():用目标二进制文件覆盖子进程。
  • 将进程分配到专用的 cgroup
    • 确保所有子进程保持在同一个 cgroup 内。
    • 启用资源限制和进程跟踪。

3.1 Type=simple

[Service]
Type=simple
ExecStart=/data/svr/greatsql/bin/mysqld --defaults-file=/data/conf/greatsql4306.cnf $MYSQLD_OPTS

3.1.1 行为

  • 要求 ExecStart 启动的是前台命令,其将作为服务的主进程(Main Process)
  • ExecStart 进程创建即启动成功(即使进程还在初始化或监听端口未就绪);如果进程崩溃或退出,systemd 会根据 Restart= 规则决定是否重启
  • 适用于不 fork() 且不依赖其他进程的服务

3.1.2 错误示例

如果 ExecStart 启动的命令以 daemon 模式运行,daemon 进程有一个瞬间退出的中间父进程,对应就是子进程。在子进程退出时,systemd 会将其从监控队列中踢掉,同时杀掉所有附属进程(杀进程的方式由 KillMode 控制)。

# KillMode=control-group
$ systemctl start db-4306
$ systemctl status db-4306
● db-4306.service - db-4306 Server
   Loaded: loaded (/usr/lib/systemd/system/db-4306.service; enabled; vendor preset: disabled)
   Active: inactive (dead) since Fri 2025-05-30 11:03:26 CST; 9s ago
  Process: 1914 ExecStart=/data/svr/greatsql/bin/mysqld --defaults-file=/data/conf/greatsql4306.cnf --daemonize $MYSQLD_OPTS (code=exited, status=0/SUCCESS)
 Main PID: 1914 (code=exited, status=0/SUCCESS)

Jun 05 11:03:22 dbcluster-165 systemd[1]: Started db-4306 Server.
$ ps aux |grep 4306 |grep -v grep

Type=simple,执行 daemon 命令,默认启动后马上会停止。

3.2 Type=forking

[Service]
Type=forking
PIDFile=/data/dbdata/data4306/data/mysql.pid
ExecStart=/data/svr/greatsql/bin/mysqld --defaults-file=/data/conf/greatsql4306.cnf --daemonize $MYSQLD_OPTS

3.2.1 行为

  • 要求 ExecStart 启动的命令以 daemon 模式运行,服务预期自行 fork() 并退出
  • ExecStart 进程 fork() 出的进程将作为服务的主进程(Main Process),推荐设置 PIDFile 用以正确监控服务主进程,否则通过 cgroup 跟踪
  • PIDFile 只适合在 Type=forking 模式下使用,如果有设置 PIDFile,systemd 会在 ExecStart 进程退出后立即读取这个 PIDFile,读取成功后就认为该服务已经启动成功,读取失败就认为该服务启动失败
  • 适用于传统 Unix 守护进程

以下是 forking 模式下正常启动的服务

$ systemctl status db-4306
● db-4306.service - db-4306 Server
   Loaded: loaded (/usr/lib/systemd/system/db-4306.service; enabled; vendor preset: disabled)
   Active: active (running) since Thu 2025-05-29 22:28:03 CST; 11s ago
  Process: 24262 ExecStart=/data/svr/greatsql/bin/mysqld --defaults-file=/data/conf/greatsql4306.cnf --daemonize $MYSQLD_OPTS (code=exited, status=0/SUCCESS)
 Main PID: 24342 (mysqld)
    Tasks: 54
   CGroup: /system.slice/db-4306.service
           └─24342 /data/svr/greatsql/bin/mysqld --defaults-file=/data/conf/greatsql4306.cnf --daemonize

May 29 22:28:01 dbcluster-165 systemd[1]: Starting db-4306 Server...
May 29 22:28:03 dbcluster-165 systemd[1]: Started db-4306 Server.

ExecStart 启动的进程 PID=24262,且该进程的状态是已退出,退出状态码为0,这个进程是 daemon 类进程创建过程中瞬间退出的中间父进程。Main PID: 24342 (mysqld),这是 systemd 真正监控的服务主进程。

3.2.2 错误示例

如果 ExecStart 是一个前台命令,systemd 会一直等待 ExecStart 启动的进程作为中间父进程退出,在等待过程中,systemctl start 会一直卡住,直到等待超时而失败。

$ systemctl status db-4306
● db-4306.service - db-4306 Server
   Loaded: loaded (/usr/lib/systemd/system/db-4306.service; enabled; vendor preset: disabled)
   Active: activating (start) since Fri 2025-05-30 17:25:01 CST; 52s ago
 Main PID: 27683 (code=exited, status=0/SUCCESS);         : 12646 (mysqld)
    Tasks: 54
   CGroup: /system.slice/db-4306.service
           └─12646 /data/svr/greatsql/bin/mysqld --defaults-file=/data/conf/greatsql4306.cnf

May 30 17:25:01 dbcluster-165 systemd[1]: Starting db-4306 Server...
$ ps axj |grep 4306 |grep -v grep
18266 12640 12640 18266 pts/1    12640 S+       0   0:00 systemctl start db-4306
    1 12646 12646 12646 ?           -1 Ssl    986   0:02 /data/svr/greatsql/bin/mysqld --defaults-file=/data/conf/greatsql4306.cnf

$ tailf /var/log/messages |grep db-4306
May 30 17:25:01 dbcluster-165 systemd: Starting db-4306 Server...
May 30 17:26:31 dbcluster-165 systemd: db-4306.service start operation timed out. Terminating.
May 30 17:26:32 dbcluster-165 systemd: Failed to start db-4306 Server.
May 30 17:26:32 dbcluster-165 systemd: Unit db-4306.service entered failed state.
May 30 17:26:32 dbcluster-165 systemd: db-4306.service failed.
May 30 17:26:32 dbcluster-165 systemd: db-4306.service holdoff time over, scheduling restart.
May 30 17:26:32 dbcluster-165 systemd: Stopped db-4306 Server.
May 30 17:26:32 dbcluster-165 systemd: Starting db-4306 Server...

Type=forking,执行前台命令,在Restart=on-failure场景,启动超时导致服务反复重启。

3.3 Type=notify

[Service]
Type=notify
ExecStart=/data/svr/greatsql/bin/mysqld --defaults-file=/data/conf/greatsql4306.cnf $MYSQLD_OPTS

3.3.1 行为

  • 类似 simple,要求 ExecStart 启动的是前台命令,其将作为服务的主进程(Main Process)
  • 进程支持 sd_notify(),必须正确配置 NotifyAccess 和超时时间
  • 进程在启动完成、状态更新、停止通知后必需主动通过 sd_notify() 向 systemd 发送通知
  • 适用于实现更精确的启动、运行和停止管理服务

3.4 mysqld显示更多变量

当使用 mysqld_safe 启动数据库时,ps 可以看到 mysqld 进程带有很多变量

$ ps aux |grep 4306
mysql   8787  0.0  0.0 113316  1640 pts/1    S    08:59   0:00 /bin/sh /data/svr/greatsql/bin/mysqld_safe --defaults-file=/data/conf/greatsql4306.cnf
mysql  10424  0.6  3.0 1251912 499724 pts/1  Sl   08:59   0:16 /data/svr/greatsql/bin/mysqld --defaults-file=/data/conf/greatsql4306.cnf --basedir=/data/svr/greatsql --datadir=/data/dbdata/data4306/data --plugin-dir=/data/svr/greatsql/lib/plugin --log-error=/data/logs/error4306.log --open-files-limit=65535 --pid-file=/data/dbdata/data4306/data/mysql.pid --socket=/data/dbdata/data4306/data/mysql.sock --port=4306
$ 

mysqld_safe 处理逻辑如下

cmd="`mysqld_ld_preload_text`$NOHUP_NICENESS"

for i in  "$ledir/$MYSQLD" "$defaults" "--basedir=$MY_BASEDIR_VERSION" \
  "--datadir=$DATADIR" "--plugin-dir=$plugin_dir" "$USER_OPTION"
do
  cmd="$cmd "`shell_quote_string "$i"`
done
cmd="$cmd $args"
# Avoid 'nohup: ignoring input' warning
test -n "$NOHUP_NICENESS" && cmd="$cmd < /dev/null"

log_notice "Starting $MYSQLD daemon with databases from $DATADIR"

对于 systemd service,可以添加 ExecStartPre,从 --defaults-file 中获取需要显示的变量

```
[Service]
Type=notify
ExecStartPre=-/bin/bash -c "sed 's/_/-/g; s/ //g; s/#.*//' /data/conf/greatsql4306.cnf |grep -E '^(basedir|datadir|log-error|socket|port)=' |sed 's/^/--/' |tr '\n' ' ' |sed 's/^/MYSQLD_OPTS=/' > /data/conf/greatsql4306.env"
ExecStart=/data/svr/greatsql/bin/mysqld --defaults-file=/data/conf/greatsql4306.cnf $MYSQLD_OPTS
EnvironmentFile=-/data/conf/greatsql4306.env

启动后的效果

$ systemctl -l status db-4306
● db-4306.service - db-4306 Server
Loaded: loaded (/usr/lib/systemd/system/db-4306.service; enabled; vendor preset: disabled)
Active: active (running) since Fri 2025-06-06 10:27:16 CST; 7h ago
Main PID: 12020 (mysqld)
Status: "Server is operational"
Tasks: 53
CGroup: /system.slice/db-4306.service
└─12020 /data/svr/greatsql/bin/mysqld --defaults-file=/data/conf/greatsql4306.cnf --port=4306 --basedir=/data/svr/greatsql --datadir=/data/dbdata/data4306/data --pid-file=/data/dbdata/data4306/data/mysql.pid --socket=/data/dbdata/data4306/data/mysql.sock --log-error=/data/logs/error4306.log

Jun 06 10:27:14 dbcluster-165 systemd[1]: Starting db-4306 Server...
Jun 06 10

文章整理自互联网,只做测试使用。发布者:Lomu,转转请注明出处:https://www.it1024doc.com/12913.html

(0)
LomuLomu
上一篇 2025 年 7 月 20 日
下一篇 2025 年 7 月 20 日

相关推荐

  • DataGrip激活码永久免费使用方法!

    免责声明:以下教程中提到的 DataGrip 破解补丁与激活码均来源于网络,仅限个人学习研究,禁止商业用途。若条件允许,请支持正版:https://panghu.hicxy.com/shop/?id=18(低至 32 元/年,官方全家桶账号)。 先放一张实测截图:DataGrip 2025.2.1 已激活至 2099 年,爽到飞起! 下面用图文方式手把手带你…

    DataGrip激活码 2025 年 9 月 19 日
    10500
  • 最新datagrip激活码获取方式+破解工具

    声明:本文所涉及的 DataGrip 破解补丁与激活码均来自互联网公开资源,仅供个人学习研究,禁止商用。若条件允许,请支持正版! 先放一张“战果”图:DataGrip 2025.2.1 已成功激活至 2099 年,爽歪歪! 下面用图文一步步带你搞定最新版 DataGrip 的激活流程。 嫌折腾?直接买官方正版,全家桶账号低至 32 元/年,一键登录即用:ht…

    DataGrip激活码 2025 年 12 月 3 日
    5300
  • 【永久激活】IDEA 2024激活破解保姆级教程,附激活码+工具,亲测可用

    IntelliJ IDEA 是 Java 编程语言的集成开发环境,被公认为最好的 Java 开发工具之一。本文分享通过脚本免费激活 IDEA 等 Jetbrains 全家桶工具,支持 2021 以上的版本包括最新版本。 一、下载并安装 IDEA 大家可以直接在 JetBrains 官网下载最新版本的 IDEA。安装步骤非常简单,按照提示一步一步进行即可。 二…

    未分类 2024 年 6 月 23 日
    1.7K00
  • IDEA激活码+破解码合集,2025可用工具全都有!

    免责声明:以下补丁与激活码均源自网络,仅供个人学习参考,禁止商业用途。若条件允许,请支持正版!官方正版低至 32 元/年,支持全家桶:https://panghu.hicxy.com/shop/?id=18 先放成果图:IDEA 2025.2.1 已顺利激活至 2099 年,稳! 下面用图文方式手把手演示最新版 IntelliJ IDEA 的完整激活流程。 …

    IDEA破解教程 2025 年 9 月 18 日
    12700
  • Java怎样实现将数据导出为Word文档

    文章首发于我的博客:Java怎样实现将数据导出为Word文档 – Liu Zijian’s Blog 我们在开发一些系统的时候,例如OA系统,经常能遇到将审批单数据导出为word和excel文档的需求,导出为excel是比较简单的,因为excel有单元格来供我们定位数据位置,但是word文档的格式不像表格那样可以轻松的定位,要想将数据导出为一些带有图片和表格…

    2025 年 1 月 14 日
    44800

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信