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.logdeviceFileCreatorどちらのスクリプトもステートメントをaccelMonitor使用し、printfCで書かれています。

私の質問はこの質問に対する答えです。: スクリプトが実行されると、deviceFileCreatorprintf ステートメントがaccelMonitor.logファイルに正しく書き込まれます。ただし、accelMonitorスクリプトが実行されると、両方のスクリプトがcにあり、printfを使用しても印刷ステートメントが.logファイルに正しく書き込まれません。 systemdサービスに精通している人なら、以下のコードを見て、なぜこれが起こるのかを簡単に理解できることを願っています。明確にすると、accelMonitorサービスとして実行されていない場合はコンソールに正しく印刷されます。

私が今まで試したこと:

サービス単位ファイル自体で、次のオプションを試しましたStandardOutputsyslog、、、、。これらのオプションのどれもコンソール、ログ、または.logファイルに印刷されないようです。加速度計割り込みが発生した後にリセットされるため、スクリプトが実行されていると確信しています。syslog+consoleconsoleappend:/var/log/accelMonitor.logaccelMonitoraccelMonitor

accelMonitorまた、問題が発生した場合に備えて、デバイスファイルを生成する部分をdeviceFileCreator以前に実行されたスクリプトに分割しました。何も変更されていないようですが、この変更が有効になったら、accelMonitor.servicestart()で実行中であると印刷します[ 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

関連情報