systemd 退出代码 EXIT_FDS 是什么意思?

systemd 退出代码 EXIT_FDS 是什么意思?

systemd status我停止服务后收到此消息:

Actice: failed (Result: exit-code) <...> Main PID: 4747 (code=exited, status=202/FDS)

状态 FDS 定义在文档像这样:

202 EXIT_FDS 无法关闭不需要的文件描述符,或调整传递的文件描述符。

启动服务工作正常,没有报告任何错误systemd status

问题

  1. EXIT_FDS 更实际的细节意味着什么?
  2. 状态代码是来自我的应用程序,还是来自 systemd 本身?
  3. 我的应用程序打开一个 TCP 套接字,该套接字在停止时不会关闭。是这个原因吗?
  4. 如果是这样,我可以让 systemd 忽略延迟套接字而不将其报告为错误吗?

细节

完整的状态消息:

tool-user@tool-box:~$ systemctl status tool.service
● tool.service - Tool application
   Loaded: loaded (/home/tool-user/tool.service; linked; vendor preset: enabled)
   Active: failed (Result: exit-code) since Mon 2022-02-07 14:14:46 CET; 3s ago
  Process: 4758 ExecStop=/bin/bash -c tool-stop && while ps -p $MAINPID >/dev/null
  Process: 4601 ExecStart=/bin/bash -c tool-start (code=exited, status=0/SUCCESS)
 Main PID: 4747 (code=exited, status=202/FDS)

Feb 07 14:14:31 tool-box systemd[1]: Starting Tool application...
Feb 07 14:14:32 tool-box bash[4601]: Server started on port 44680
Feb 07 14:14:32 tool-box systemd[1]: Started Tool application.
Feb 07 14:14:44 tool-box systemd[1]: Stopping Tool application...
Feb 07 14:14:45 tool-box systemd[1]: tool.service: Main process exited, code=exited, status=202/FDS
Feb 07 14:14:46 tool-box systemd[1]: tool.service: Failed with result 'exit-code'.
Feb 07 14:14:46 tool-box systemd[1]: Stopped Tool application.

服务定义文件如下所示:

[Unit]
Description=Tool application
# Standard dependencies for web server
After=network.target remote-fs.target nss-lookup.target httpd-init.service

[Service]
Type=forking
Restart=on-failure
RestartSec=10
ExecStart=/bin/bash -c 'toolStart'
ExecStop=/bin/bash -c 'toolStop && while ps -p $MAINPID >/dev/null 2>&1; do sleep 1; done'
User=tool-user
StandardOutput=syslog
StandardError=syslog
TimeoutStopSec=60

[Install]
WantedBy=multi-user.target

操作系统:Ubuntu 18.04 Server,在 Windows 10 上的 VirtualBox 中运行。

tool-user@tool-box:~$ uname -a
Linux tool-box 4.15.0-166-generic #174-Ubuntu SMP Wed Dec 8 19:07:44 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

答案1

由于该服务具有Type=forkingPID ExecStart4758,并且您询问的退出代码与主 PID 4747 一起列出,我们可以得出结论,systemd管理到fork()一个子进程,然后该子进程成功execve()执行了 ExecStart 进程,因此 systemd 表- 特定的退出代码此处不适用。

systemd如果错误来自于 :之后fork()但之前的实际子进程,则将应用特定于 systemd 的退出代码表,execve()具体来说,错误 202 意味着在服务定义中实现StandardInput=,StandardOutput=或指令时出现问题。StandardError=但由于ExecStart具体报告为 PID 4601 并已退出status=0/SUCCESS,因此此处发生的情况并非如此。它ExecStop是作为 PID 4758 执行的,所以它也不是来自那个。

状态代码 202 来自应用程序的“主进程”(PID 为 4747 的进程),它的含义与应用程序开发人员想要的含义无关。

残留的 TCP 套接字不是原因:由于您的应用程序进程已经死亡,内核将清理它可能存在的任何残留套接字。

当然,如果应用程序没有使用 SO_REUSEADDR 套接字选项,则可能无法立即重新启动应用程序并让它使用相同的端口号,直到延迟套接字的 TIME_WAIT 过期...但这不是 systemd 的问题;这是应用程序必须自己处理的事情。

/FDS部分来自exit_status_to_string()函数位于 shared/exit-status.csystemd源代码包中的文件中。

如果状态代码具有任何标准化含义,该函数应该添加一个简短的提示来说明状态代码的含义。该函数可以采用一个参数来确定要使用哪一组状态代码提示,但是何时systemctl status使用该函数(即在文件中)systemctl/systemctl-show.c,它(截至撰写本文时)似乎总是将参数设置为 来调用它EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD,即“根据 libc 和 systemd 本身的使用情况显示状态代码提示”,而不检查状态代码实际上是否来自某个进程是否是 systemd 软件套件的成员。

最终结果是状态 202 总是附加到/FDS它上面,无论它是否已知有systemd 特定含义 “无法关闭不需要的文件描述符,或调整传递的文件描述符”或不。这只是一个简单的表查找:不要认为它有更多的智能。

(在 Unix 编程文献和程序员行话中,“fds”是“文件描述符”一词的通用简写。它还/FDS暗示了 systemd 代码中状态代码 202 的符号名称:EXIT_FDS- 并且因为所有 systemd 的状态代码符号都有EXIT_前缀,为简洁起见,将其删除。)

相关内容