我有一组在Postgresql
启动时不断运行的脚本。我修改了文件ExecStop
中的命令.service
,以便在数据库关闭之前运行一个特殊的脚本来停止这些脚本并等待它们完成。这一切都有效。
然而,昨天 IT 部门关闭了服务器,并且ExecStop
命令没有运行。我知道这一点是因为脚本中存在一些混乱的结果,并且因为特殊脚本将其输出记录到文件中,并且该文件昨天没有更新。
注意:我刚刚查看了 root 用户的历史记录,我认为 IT 跑了
shutdown -h now
这会绕过 systemctl 设置吗?
我可以在.service
文件中添加一些内容以确保ExecStop
在系统关闭时运行,还是需要创建一个与关闭相关的特殊服务?
我不认为这与“如何在关闭前使用 systemd 运行脚本”重复,因为我不想创建一个与现有 Postgresql 服务重复的特殊服务。
我非常确定我的特殊脚本没有运行,因为它在运行时附加到日志文件,而该日志文件最后一次附加到大约一周前,当时我上次运行“systemctl stop my-service-name”。服务' 。
这是服务文件:
[Unit]
Description=PostgreSQL 9.3 main database server
After=syslog.target
After=network.target
[Service]
Type=forking
User=postgres
Group=postgres
# Location of database directory
Environment=PGDATA=/db_tier1/main/
ExecStartPre=/usr/pgsql-9.3/bin/postgresql93-check-db-dir ${PGDATA} ; /bin/rm -f /db_tier2/PGSERVICE-PROD-ABORT
ExecStart=/usr/pgsql-9.3/bin/pg_ctl start -D ${PGDATA} -s -w -t 300
ExecStop=/bin/sh /var/lib/pgsql/bin/PROD/run_db_pre_stop.sh ${PGDATA} ; /usr/pgsql-9.3/bin/pg_ctl stop -D ${PGDATA} -s -m fast
ExecReload=/usr/pgsql-9.3/bin/pg_ctl reload -D ${PGDATA} -s
# Give a reasonable amount of time for the server to start up/shut down
TimeoutSec=600
[Install]
WantedBy=multi-user.target
答案1
systemd 将执行ExecStop=
在关闭期间停止的所有服务,因此您的脚本可能是正在被处决。
一个常见问题是您的服务单元(在本例中postgresql.service
)没有正确设置所有依赖项,在这种情况下,其他关闭过程(例如关闭网络或卸载文件系统)可能会与您的脚本并行发生。
为了确保这些保持足够长的时间以便ExecStop=
脚本完成,您应该将它们列在After=
服务的依赖项中。 (关闭时的顺序与启动时的顺序相反,因此您的服务将会停止前这些依赖项的停止。)例如,After=network.target
如果您需要在停止脚本中建立网络,您很可能希望拥有。
如果您要写入根目录以外的文件系统,请使用RequiresMountsFor=
以确保他们在手术过程中可用。
如果您有日志并且有持久存储(我认为这是可能的),您可以查看它的内容,看看它是否提到您的ExecStop=
脚本或执行脚本时发生的一些错误。
例如,这个命令:
$ journalctl -u postgresql -b -1
它将列出postgresql.service
机器最后一次启动(-b -1
意味着当前启动之前的启动)的所有日志(假设这是您的服务单元的确切名称)。因此它应该显示您在启动时启动并在关机期间停止它。希望这可以帮助您解决问题。
答案2
启动服务时systemd
,还会创建一个专门的控制组(cgroup
简称)每个服务。您可以运行类似的命令ps ax -O cgroup:150 | grep system.slice
来查看分配给每个服务的 cgroup,尽管列表会相当广泛。
请注意,如果您停止并重新启动postgresql
而不使用systemctl
(例如,使用pg_ctl
),则重新启动的postgresql
进程将不再是systemd
为该服务创建的控制组的成员。结果,systemd
会认为该服务现在已关闭。
ExecStop=
在关闭时对已知已关闭的服务运行操作是没有用的,因此systemd
将跳过它们。
如果您有一个不愿意学习systemctl
命令的数据库管理员,一个单独的管理工具,它会postgresql
在必要时以传统方式停止和启动,或者作为某些数据库操作的一部分,您自己有一个熟练的巴甫洛夫反射,那么您可以考虑将postgresql.service
单位更改为:
Type=oneshot
RemainAfterExit=true
这将停止systemd
监视 PostgreSQL 数据库引擎的实际状态,但它将允许以传统方式随意停止和重新启动数据库引擎,而不会危及ExecStop=
关闭时的操作。