linux 为什么在'systemd'服务中设置'echo V>/dev/watchdog 1'不起作用?

hujrc8aj  于 2023-01-20  发布在  Linux
关注(0)|答案(3)|浏览(343)

如果我手动停止服务,然后执行echo V > /dev/watchdog1,看门狗将正常停止。
如果在systemd服务中执行相同的echo命令,则会得到:
看门狗没有停止!

ExecStopPost=echo V > /dev/watchdog1

为什么行为不一样?

9fkzdhlc

9fkzdhlc1#

这不工作的原因在这篇文章中提到的相同:Execute multiple commands with && in systemd service ExecStart on RedHat 7.9
systemd服务内部的命令不会在正确的shell环境中执行。即使如此,我也没有某种源代码明确说明这一点。根据经验,单个systemd exec的功能如下:运行一个带参数的命令(不是多个命令,没有输出重定向等)。
就像在引用的帖子中一样,解决方案可以如下所示:

ExecStopPost=/bin/bash -c 'echo V > /dev/watchdog1'
rhfm7lfc

rhfm7lfc2#

你可以通过回声与你的看门狗互动,但我强烈建议你不要这样做。
echo会在每次运行时打开/关闭你的看门狗,需要将它配置为不可停止的看门狗。而且,对于每次打开/关闭,你会在kmsg日志中得到一个警告,接收到不必要数量的疯狂垃圾邮件。
做得对;通过编写你自己的应用程序和处理它的文件描述符来实现。2不要再使用回显了!3参见下面的例子:

#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

// Read more:
// https://www.kernel.org/doc/Documentation/watchdog/watchdog-api.txt
#include <linux/watchdog.h>

#define WATCHDOG_DEV "/dev/watchdog"

int main(int argc, char** argv) {

  /* Open your watchdog */
  int fd = open(WATCHDOG_DEV, O_RDWR);
  if (fd < 0) {
    fprintf(stderr, "Error: %s\n", strerror(errno));
    exit(EXIT_FAILURE);
  }

  /* Query timeout */
  int timeout = 0;
  if (ioctl(fd, WDIOC_GETTIMEOUT, &timeout) < 0) {
    fprintf(stderr, "Error: Cannot read watchdog timeout: %s\n", strerror(errno));
    exit(EXIT_FAILURE);
  }
  fprintf(stdout, "The timeout is %d seconds\n", timeout);

  /* Query timeleft */
  int timeleft = 0;
  if (ioctl(fd, WDIOC_GETTIMELEFT, &timeleft) < 0) {
    fprintf(stderr, "Error: Cannot read watchdog timeleft: %s\n", strerror(errno));
    exit(EXIT_FAILURE);
  }
  fprintf(stdout, "The timeleft is %d seconds\n", timeleft);

  /* Touch your watchdog */
  if (ioctl(fd, WDIOC_KEEPALIVE, NULL) < 0) {
    fprintf(stderr, "Error: Cannot write watchdog keepalive: %s\n", strerror(errno));
    exit(EXIT_FAILURE);
  }
  fprintf(stdout, "Keepalive written successfully\n");

  /* Stop your watchdog */
  write(fd, "V", 1);

  /* Close your watchdog */
  close(fd);

  return 0;
}

另一个(也是更简单的)选择是设置一个现成的看门狗服务,参见Debian/Ubuntu的watchdog包。

6mzjoqzu

6mzjoqzu3#

我知道这稍微偏离了OP的问题,但是您也可以使用systemd的套接字API将监视器管理委托给systemd。

[Unit]
Description=My Unit

[Service]
ExecStart=/my/app args
WatchdogSec=30 # 30s, but you can specify whatever you want
# Optional: Restart=on-watchdog # Restart app on watchdog failure
# Optional: WatchdogSignal=SIGABRT # Change signal sent to kill app
#

然后,您必须定期从您的应用重置看门狗:

sd_notify(0, "WATCHDOG=1");

如果服务失败,还有一些选项可以要求systemd重新启动机器,尽管我不记得是哪一个。
如果您需要更多信息,您可以在此处查看综合指南:https://0pointer.de/blog/projects/watchdog.html

相关问题