程序从 rc.local 启动但不执行任何操作

程序从 rc.local 启动但不执行任何操作

我有一个使用 msqllib 的程序。它扫描我构建的一些硬件,然后更新 mysql 数据库。这个程序已经运行了很多年,但我从来没有能够在系统重新启动时自动启动它。现在我遇到了一个超出我控制范围的电源循环问题,因此希望让它自动运行。

在 rc.local 中:我有:

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi
/home/nigel/scan
exit 0

现在,当我在命令提示符下输入代码并更新我的数据库时,代码运行良好。但是,当我将其放入 rc.local 中时, ps -ef 显示:

root       356   350  0 20:54 ?        00:00:03 /home/nigel/scan

但程序没有执行 SQL 调用来更新数据库。

如果我询问 rc.local 的状态:

root@Pi-Scan:~# systemctl status rc-local.service
● rc-local.service - /etc/rc.local Compatibility
   Loaded: loaded (/lib/systemd/system/rc-local.service; enabled-runtime; vendor preset: enabled)
  Drop-In: /usr/lib/systemd/system/rc-local.service.d
           └─debian.conf
           /etc/systemd/system/rc-local.service.d
           └─ttyoutput.conf
   Active: activating (start) since Sat 2023-05-06 20:54:19 EDT; 12min ago
     Docs: man:systemd-rc-local-generator(8)
Cntrl PID: 350 (rc.local)
    Tasks: 2 (limit: 414)
      CPU: 3.903s
   CGroup: /system.slice/rc-local.service
           ├─350 /bin/sh -e /etc/rc.local start
           └─356 /home/nigel/scan

May 06 20:54:21 Pi-Scan rc.local[356]: error: first parameter is not a valid address family: Transport endpoint is not connected
May 06 20:54:22 Pi-Scan rc.local[356]: error: first parameter is not a valid address family: Transport endpoint is not connected
May 06 20:54:23 Pi-Scan rc.local[356]: error: first parameter is not a valid address family: Transport endpoint is not connected
May 06 20:54:24 Pi-Scan rc.local[356]: error: first parameter is not a valid address family: Transport endpoint is not connected
May 06 20:54:25 Pi-Scan rc.local[356]: error: first parameter is not a valid address family: Transport endpoint is not connected
May 06 20:54:26 Pi-Scan rc.local[356]: error: first parameter is not a valid address family: Transport endpoint is not connected
May 06 20:54:27 Pi-Scan rc.local[356]: error: first parameter is not a valid address family: Transport endpoint is not connected
May 06 20:54:28 Pi-Scan rc.local[356]: error: first parameter is not a valid address family: Transport endpoint is not connected

但是,如果我发出systemctl restart rc-local.service 该程序执行第二个实例并且工作正常!

考虑到这可能是一种竞争状况,我尝试在命令前添加 sleep 5,但仍然遇到同样的问题。

答案1

请注意评论

# This script is executed at the end of each multiuser runlevel.

可能不再完全正确。

当使用经典的 SysVinit 并且所有启动脚本严格按顺序运行时确实如此。但在启动脚本首次被重新设计以添加更多并行性之后,特别是在 SysVinit 被 systemd 取代之后,不再保证rc.local结尾的启动过程。

除非 systemd 被明确告知rc-local.service应该只启动您的数据库正在运行,它可能会在网络启动并运行后立即执行(通常/usr/lib/systemd/system/rc-local.service.d/debian.conf具有排序约束After=network-online.target)。

由于您的 MySQL 数据库很可能具有相同的排序约束,因此您的rc-local.service数据库和数据库很可能同时并行启动,从而有效地相互竞争。由于启动数据库很容易花费超过 5 秒的时间(尤其是在 RasPi 上),因此很可能rc-local.service会“赢得”比赛,并在数据库尚未完全运行时尝试连接到数据库。

在我看来,您/home/nigel/scan可能会受益于错误处理代码的改进。重复的Transport endpoint is not connected错误表明您的程序可能尝试打开与数据库的连接,忽略了失败的事实,然后不断重试通过最初未成功打开的连接发送一些数据:这种尝试已经注定要失败。主要需要重试的部分是打开连接, 不是发送数据

答案2

为了扩展 telcoM 的出色答案(恕我直言,您至少应该投票并接受!):

解决这个问题最直接的方法是不使用古老的 rc.local 机制,而是创建一个hardware-scan服务文件,并使其依赖于已经启动的数据库服务器。然后,您将得到保证,您所需要的内容会在其依赖项准备就绪后立即启动,但不会更早。

[Unit]
Description=Scan the hardware using "scan"
# I'm assuming the service is called mariadb.service, but you can check that:
# systemctl status mariadb
# should show it running; if it says that the service couldn't be found,
# try mysql.service instead (I really don't know what you've installed)
After=mariadb.service

[Service]
Type=oneshot
ExecStart=/home/nigel/scan

[Install]
WantedBy=multi-user.target

放置hardware-scan.service在 /etc/systemd/system/ 中,并运行sudo systemctl enable hardware-scan以使其在下次启动时启动。

请注意,它将以 root 身份运行!

相关内容