为什么在 'systemd' 服务中设置 'echo V > /dev/watchdog1' 不起作用?
Why is setting 'echo V > /dev/watchdog1' not working when inside a 'systemd' service?
如果我手动停止服务然后执行 echo V > /dev/watchdog1
,看门狗会正常停止。
如果我在 systemd 服务中执行相同的 echo
命令,我得到:
watchdog did not stop!
ExecStopPost=echo V > /dev/watchdog1
为什么行为不一样?
由于 post 中提到的相同原因,这不起作用:
来自 systemd 服务内部的命令未在适当的 shell 环境中执行。即便如此,我也没有明确说明这一点的某种来源。根据经验,单个 systemd exec 的功能如下:运行 一个带参数的命令(不是多个命令,没有输出重定向等)。
就像引用的post一样,解决方案可以这样写:
ExecStopPost=/bin/bash -c 'echo V > /dev/watchdog1'
您可以通过回声与看门狗互动,但我强烈建议您不要这样做。
在每个 运行 上回显 opens/closes 你的看门狗,需要将其配置为 non-stoppable 看门狗。此外,对于每个 open/close,您都会在 kmsg log 中收到警告,收到不必要数量的疯狂垃圾邮件。
做对;通过编写您自己的应用程序并处理其文件描述符来实现。不要再使用回声了!请参阅以下示例:
#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;
}
另一个(更简单的)选项是设置 ready-made 看门狗服务。请参阅 Debian/Ubuntu 的 watchdog
包。
如果我手动停止服务然后执行 echo V > /dev/watchdog1
,看门狗会正常停止。
如果我在 systemd 服务中执行相同的 echo
命令,我得到:
watchdog did not stop!
ExecStopPost=echo V > /dev/watchdog1
为什么行为不一样?
由于 post 中提到的相同原因,这不起作用:
来自 systemd 服务内部的命令未在适当的 shell 环境中执行。即便如此,我也没有明确说明这一点的某种来源。根据经验,单个 systemd exec 的功能如下:运行 一个带参数的命令(不是多个命令,没有输出重定向等)。
就像引用的post一样,解决方案可以这样写:
ExecStopPost=/bin/bash -c 'echo V > /dev/watchdog1'
您可以通过回声与看门狗互动,但我强烈建议您不要这样做。
在每个 运行 上回显 opens/closes 你的看门狗,需要将其配置为 non-stoppable 看门狗。此外,对于每个 open/close,您都会在 kmsg log 中收到警告,收到不必要数量的疯狂垃圾邮件。
做对;通过编写您自己的应用程序并处理其文件描述符来实现。不要再使用回声了!请参阅以下示例:
#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;
}
另一个(更简单的)选项是设置 ready-made 看门狗服务。请参阅 Debian/Ubuntu 的 watchdog
包。