Systemd 서비스가 콘솔/syslog/journal에 출력을 인쇄하지 않습니다.

Systemd 서비스가 콘솔/syslog/journal에 출력을 인쇄하지 않습니다.

업데이트: 하단 참조

저는 systemd 버전 241을 사용하여 debian Linux에서 systemd 서비스를 만들었습니다. 그 목적은 accelMonitor.c커널 모듈에 연결된 컴파일된 버전을 시작하는 것입니다. 이 커널 모듈은 가속도계의 GPIO 인터럽트에 응답하는 스크립트용 이벤트를 제공합니다. 이벤트를 받은 후 accelMonitor장치의 방향을 콘솔에 인쇄합니다. 스크립트를 서비스로 변환하는 시스템 단위 파일은 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.log. deviceFileCreator두 스크립트 모두 명령문을 accelMonitor사용하며 printfC로 작성되었습니다.

내 질문은 이 질문에 대한 답변입니다.: 스크립트가 실행될 때 deviceFileCreatorprintf 문이 accelMonitor.log파일에 올바르게 기록됩니다. 그러나 accelMonitor스크립트가 실행되면 두 스크립트 모두 c에 있고 printf를 사용하더라도 인쇄 문이 .log 파일에 올바르게 기록되지 않습니다. systemd 서비스에 익숙한 사람이라면 아래 코드를 보고 왜 이런 일이 발생하는지 쉽게 알아낼 수 있기를 바랍니다. 명확히 하자면, accelMonitor서비스로 실행되지 않는 경우 콘솔에 올바르게 인쇄됩니다.

내가 지금까지 시도한 것 :

서비스 단위 파일 자체에서 다음 옵션을 시도했습니다 StandardOutput: syslog, syslog+console, console, append:/var/log/accelMonitor.log. 이러한 옵션 중 어느 것도 accelMonitor콘솔, 로그 또는 .log 파일 에 인쇄되지 않는 것 같습니다 . accelMonitor가속도계 인터럽트가 발생한 후 재설정되기 때문에 스크립트가 실행 중이라고 확신합니다 .

accelMonitor또한 문제가 발생할 경우를 대비하여 장치 파일을 생성하는 부분을 deviceFileCreator이전에 실행된 스크립트로 분할했습니다. 아무 것도 변경되지 않는 것 같지만 일단 이 변경 사항이 활성화되면 accelMonitor.service이제 start()에서 실행 중이라고 인쇄 하게 됩니다 [ 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")으로 전환했습니다 . 이것은 작동하지만 둘 다 서비스 단위 파일(현재)에서 동일한 설정으로 설정되어 있음에도 불구하고 stderr 스트림만 인쇄하는 새로운 문제가 있습니다.fprintf(stdout,"Hello")fprintf(stderr,"Hello")StandardOutputStandardErrorsyslog

관련 정보