Systemd 服务不会将输出打印到控制台/syslog/journal

Systemd 服务不会将输出打印到控制台/syslog/journal

更新:见底部

我在 debian Linux 上使用 systemd 版本 241 创建了一个 systemd 服务,其目的是启动accelMonitor.c连接到内核模块的编译版本。该内核模块为脚本提供一个事件,以响应来自加速度计的 GPIO 中断。收到事件后,accelMonitor将设备的方向打印到控制台。将脚本转换为服务的 systemd 单元文件accelMonitor如下所示:

[Unit]
Description=Accelerometer Orientation Monitor


[Service]
Type=simple
ExecStartPre=/etc/systemd/system/deviceFileCreator
ExecStart=/etc/systemd/system/accelMonitor
RemainAfterExit=true
KillMode=process
StandardOutput=append:/var/log/accelMonitor.log
StandardError=append:/var/log/accelMonitor.log

[Install]
WantedBy=multi-user.target

该服务首先执行编译后的deviceFileCreator.c脚本,为内核模块生成设备文件并accelMonitor进行通信。然后,服务执行accelMonitor脚本本身,该脚本通过所述设备文件向内核模块注册。目前,输出正在写入文件accelMonitor.logdeviceFileCreator和脚本都accelMonitor使用printf语句 和 都是用 C 编写的。

我的问题是针对这个问题的回应:当deviceFileCreator脚本运行时,printf 语句会accelMonitor.log正确记录到文件中。但是,当accelMonitor脚本运行时,尽管两个脚本都使用 c 语言并使用 printf,但 .log 文件中没有正确记录任何打印语句。我希望熟悉 systemd 服务的人可以通过查看下面的代码轻松找出发生这种情况的原因。需要明确的是,accelMonitor当不作为服务运行时,会正确打印到控制台。

到目前为止我已经尝试过:

在服务单元文件本身中,我尝试了以下选项StandardOutputsyslog, syslog+console, console, append:/var/log/accelMonitor.log。这些选项似乎都不会打印到accelMonitor控制台、日志或 .log 文件。我确信该accelMonitor脚本正在运行,因为它在发生后重置了加速度计中断。

accelMonitor我还将创建设备文件的部分拆分到deviceFileCreator之前运行的脚本中,以防出现问题。它似乎没有改变任何东西,但是一旦启用此更改,就会导致accelMonitor.service现在打印出它正在启动 ( [ OK ] Started Accelerometer Orientation Monitor) 上运行,而之前它没有运行(但它最终仍然运行)。

Type=oneshot除了 之外我也尝试过Type=simple

如果有人能让我深入了解为什么我没有从中获取日志信息,accelMonitor而是从中获取日志deviceFileCreator信息,我将不胜感激。谢谢!

deviceFileCreator.c文件如下所示:

// deviceFileCreator.c

#include <stdio.h>
#include <limits.h>
#include <signal.h>
#include <fcntl.h>

// Helper function to run bash commands in c
// This allows me to create the device file using terminal commands
char* exec(char* cmd) {
    FILE* fp;
    int status;
    char path[PATH_MAX];
    char* regValue;
    fp = popen(cmd, "r");
    if (fp == NULL)
        /* Report error */
        perror("popen error");
    while (fgets(path, PATH_MAX, fp) != NULL)
        //printf("%s", path);
        regValue = path;

    status = pclose(fp);
    if (status == -1) {
        /* Error reported by pclose() */
        printf("Error reported by pclose()");
    }
    return regValue;
}

int main() {
        int fd;
        printf("Creating Device File irq_signal \n");

        // Command to create device file
        exec("sudo mknod /dev/irq_signal c 64 0");
        /* Open the device file */
        fd = open("/dev/irq_signal", O_RDONLY);
        if (fd < 0) {
                perror("Could not open device file\n");
                return -1;
        }
        printf("Device file /dev/irq_signal created \n");
        return 0;
}

当此脚本在启动时运行时,accelMonitor.log 中的输出为:

Creating Device File irq_signal
Device file /dev/irq_signal created

accelMonitor.c文件如下所示:

/* 
Event handler to monitor signals from 
associated kernel module. Triggers whenever
an interrupt is detected by the kernel module 
(gpio_irq) from the MMA8451Q accelerometer and 
is passed as a signal (SIGTX 44) to this script. 
This occurs everytime the device orientation changes 
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <string.h>
#include <sys/time.h>
#include <limits.h>
#include <error.h>
#include <stdbool.h>

/* Signals to connect to Kernel Module */
#define SIGTX 44
#define REGISTER_UAPP _IO('R', 'g')

/* Define registers to be accessed on Accelerometer over i2c */
const char* deviceADDR = " 0x1C";
const char* PL_STATUS = " 0x10";
const char* INT_SOURCE = " 0x0C";
const char* PL_CFG = " 0x11";
const char* PL_COUNT = " 0x12";
const char* CTRL_REG1 = " 0x2A";
const char* CTRL_REG3 = " 0x2C";
const char* CTRL_REG4 = " 0x2D";
const char* CTRL_REG5 = " 0x2E";

/* Defines function structure for i2c-tools package */
const char* cmdGet = "i2cget -y 2";
const char* cmdSet = "i2cset -y 2";

/* Enum for current device orientation state */
enum position { left, right, down, up };
enum position oriented;

/* Function that runs bash commands in c 
Allowing one to use the i2c-tools package */
char* exec(char* cmd) {
    FILE* fp;
    int status;
    char path[PATH_MAX];
    char* regValue;

    fp = popen(cmd, "r");
    if (fp == NULL)
        /* Report error */
        perror("popen error");

    while (fgets(path, PATH_MAX, fp) != NULL)
        //printf("%s", path);
        regValue = path;

    status = pclose(fp);
    if (status == -1) {
        /* Error reported by pclose() */
        printf("Error reported by pclose()");
    }
    return regValue;
}

/* Function that performs i2cget */
char* get(const char* reg1, const char* reg2) {
    char str[100];
    char str2;

    strcpy(str, cmdGet);
    strcat(str, reg1);
    strcat(str, reg2);

    char* regValue = exec(str);
    return regValue;

}

/* Function that performs i2cset */
char* set(const char* reg1, const char* reg2, const char* value) {
    char str[100];
    char str2;

    strcpy(str, cmdSet);
    strcat(str, reg1);
    strcat(str, reg2);
    strcat(str, value);
    //printf("%s\n",str);
    char* regValue = exec(str);
    return regValue;
}

/* Helper function to check whether or not a bit k is set */
bool bitSet(char* x, int k) {
    int n = strtoul(x, NULL, 16);
    //printf("%d\n", n);
    if (n & (1 << (k - 1))) {
        return true;
    }
    else {
        return false;
    }
}

/* Event handler for signal from Kernel Module */
void signalhandler(int sig) {

    // Never Prints
    printf("Event Detected");

    // This clears the interrupt, which is how I know the script is functioning
    char* orientation = get(deviceADDR, PL_STATUS);
    if (bitSet(orientation, 2) && bitSet(orientation, 3) && oriented != left) {
        printf("Landscape Left   \n");
        oriented = left;
    }
    else if (!bitSet(orientation, 2) && bitSet(orientation, 3) && oriented != right) {
        printf("Landscape Right  \n");
        oriented = right;
    }
    else if (bitSet(orientation, 2) && !bitSet(orientation, 3) && oriented != down) {
        printf("Portrait Down    \n");
        oriented = down;
    }
    else if (!bitSet(orientation, 2) && !bitSet(orientation, 3) && oriented != up) {
        printf("Portrait Up      \n");
        oriented = up;
    }
}

int main() {
    int fd;
    signal(SIGTX, signalhandler);

    /* Configure the Accelerometer */
    printf("Configuring Accelerometer...\n");
    set(deviceADDR, CTRL_REG1, " 0x00");   // Put in Standby
    set(deviceADDR, CTRL_REG1, " 0x20");   // Set data rate to 50Hz
    set(deviceADDR, PL_CFG, " 0x40");      // Enable orientation detection
    set(deviceADDR, CTRL_REG4, " 0x10");   // Enable interrupts
    set(deviceADDR, CTRL_REG5, " 0x10");   // Route interrupt to INT1 pin
    set(deviceADDR, PL_COUNT, " 0x05");    // Set debounce to 100ms
    set(deviceADDR, CTRL_REG1, " 0x02");   // Set interrupt to Active High
    set(deviceADDR, CTRL_REG1, " 0x01");   // Put in Active Mode
    get(deviceADDR, PL_STATUS); // Read PL_STATUS to clear initial interrupt
    printf("Configured!\n");

        // Also does not print
    printf("PID: %d\n", getpid());

    /* Open the device file */
    fd = open("/dev/irq_signal", O_RDONLY);
    if (fd < 0) {
        perror("Could not open device file\n");
                return -1;
        }

    /* Register app to Kernel Module */
    if (ioctl(fd, REGISTER_UAPP, NULL)) {
        perror("Error registering app");
        close(fd);
        return -1;
    }

    /* Wait for Signal */
    printf("Wait for signal...\n");
    while (1)
        sleep(1);

    return 0;
}

输出来自systemctl status accelMonitor.service

● accelMonitor.service - Accelerometer Orientation Monitor
   Loaded: loaded (/lib/systemd/system/accelMonitor.service; enabled; vendor pre
   Active: active (running) since Thu 2022-11-17 17:06:52 UTC; 26min ago
  Process: 565 ExecStartPre=/etc/systemd/system/deviceFileCreator (code=exited,
 Main PID: 655 (accelMonitor)
    Tasks: 1 (limit: 1026)
   Memory: 1.3M
   CGroup: /system.slice/accelMonitor.service
           └─655 /etc/systemd/system/accelMonitor

Nov 17 17:06:49 beaglebone systemd[1]: Starting Accelerometer Orientation Monitor..
Nov 17 17:06:52 beaglebone sudo[573]:     root : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/bin/mknod /dev/irq_signal c 64 0
Nov 17 17:06:52 beaglebone sudo[573]: pam_unix(sudo:session): session opened for user root by (uid=0)
Nov 17 17:06:52 beaglebone sudo[573]: pam_unix(sudo:session): session closed for user root
Nov 17 17:06:52 beaglebone deviceFileCreator[565]: Creating Device File irq_signal
Nov 17 17:06:52 beaglebone deviceFileCreator[565]: Device file /dev/irq_signal created
Nov 17 17:06:52 beaglebone systemd[1]: Started Accelerometer Orientation Monitor.

更新

我没有使用,而是printf("Hello")切换到了显式fprintf(stdout,"Hello")fprintf(stderr,"Hello")版本。这是可行的,但是我有一个新问题,即仅打印出 stderr 流,即使两者StandardOutput在服务单元文件中StandardError设置为相同的设置(当前)。syslog

相关内容