web-dev-qa-db-ja.com

独自のデーモンを作成します。 systemdエラー:ファイルからPIDを読み取れませんでした:引数が無効です

私は非常に単純なMPD(オペレーティングシステムの実験室での作業)で独自のデーモンを作成しようとしています。私はそれを機能させました:それはデーモンのように始まります(psの出力):

1 14877 14877 14877 ?           -1 Ss       0   0:00 lab1_daemon

再生し、信号を受け取ります。

問題は、systemdでは実行できないことです。私は非常に単純な.serviceファイルを書きました:

[Unit]
Description=Operating systems lab 1 daemon

[Service]
Type=forking
PIDFile=/run/lab1_daemon.pid
ExecStart=/path/lab1_daemon

[Install]
WantedBy=multi-user.target

しかし、systemctl startを指定してデーモンを実行すると、0.5分間ハングし、ログに次のように表示されます。

Failed to read PID from file /run/lab1_daemon.pid: Invalid argument
lab1_daemon.service never wrote its PID file. Failing.

しかし、それはしました!私はそれをチェックしました:

-rw-r--r-- 1 root root 13 Mar  5 00:13 /run/lab1_daemon.pid

私は何を間違えましたか?

PS:daemon関数を試して、デーモン化が正しく行われたことを確認しました。しかし、私は同じ結果を得ました。最小限のソースコード(58 LOC、Pastebinから移動):

#define _BSD_SOURCE
#define _GNU_SOURCE
#define _POSIX_C_SOURCE 199506L
#define _D_XOPEN_SOURCE 700

#define NAME "lab1_daemon"
#define PID_FILE_NAME "/run/" NAME ".pid"

#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int lockfile(int fd)
{
        struct flock fl;
        fl.l_type = F_WRLCK;
        fl.l_start = 0;
        fl.l_whence = SEEK_SET;
        fl.l_len = 0;
        return fcntl(fd, F_SETLK, &fl);
}

bool is_already_running(char const *lock_file_name)
{
        int lock_file = open(lock_file_name, O_RDWR | O_CREAT,
                             S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
        if (lock_file < 0)
                exit(1);

        if (lockfile(lock_file) < 0) {
                if (errno == EACCES || errno == EAGAIN) {
                        close(lock_file);
                        return true;
                }
                exit(1);
        }
        ftruncate(lock_file, 0);
        char buf[16];
        sprintf(buf, "PPID: %ld\n", (long)getpid());
        write(lock_file, buf, strlen(buf) + 1);
        return false;
}

int main(void)
{
        if (is_already_running(PID_FILE_NAME))
                exit(EXIT_FAILURE);
        daemon(0, 0);
        sleep(10);
        exit(EXIT_SUCCESS);
}
3
rominf

Systemdのドキュメントから、問題はPIDファイルの形式が正しくないことが原因だと思います。 「PPID:yourpid "」と書く代わりに。 「yourpid "」と書くだけです。ちなみに、PIDはプロセスID、PPIDは親プロセスIDの略です。それらを同じ意味で使用することはできません。

だから代わりに

char buf[16];
sprintf(buf, "PPID: %ld\n", (long)getpid());
write(lock_file, buf, strlen(buf) + 1);

やったほうがいい

fprintf(lock_file, "%ld\n", (long) getpid());

@samiamが彼の答えで言っているように、ファイルのロックを解除することも良い習慣です。

4
lgeorget

Systemdがロックされたファイルを読み取ることができないと思います。次のようなものを試してください。

void unlockfile() {
    struct flock fl;
    fl.l_type = F_UNLCK;
    /* etc. */
    return fcntl(fd, F_SETLK, &fl);
}

Pastebinには不快な会話広告があるため、元の投稿者のソースコード全体を次に示します。

#define _BSD_SOURCE
#define _GNU_SOURCE
#define _POSIX_C_SOURCE 199506L
#define _D_XOPEN_SOURCE 700

#define NAME "lab1_daemon"
#define PID_FILE_NAME "/run/" NAME ".pid"

#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int lockfile(int fd)
{
    struct flock fl;
    fl.l_type = F_WRLCK;
    fl.l_start = 0;
    fl.l_whence = SEEK_SET;
    fl.l_len = 0;
    return fcntl(fd, F_SETLK, &fl);
}

bool is_already_running(char const *lock_file_name)
{
    int lock_file = open(lock_file_name, O_RDWR | O_CREAT,
                         S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    if (lock_file < 0)
            exit(1);

    if (lockfile(lock_file) < 0) {
            if (errno == EACCES || errno == EAGAIN) {
                    close(lock_file);
                    return true;
            }
            exit(1);
    }
    ftruncate(lock_file, 0);
    char buf[16];
    sprintf(buf, "PPID: %ld\n", (long)getpid());
    write(lock_file, buf, strlen(buf) + 1);
    return false;
}

int main(void)
{
    if (is_already_running(PID_FILE_NAME))
            exit(EXIT_FAILURE);
    daemon(0, 0);
    sleep(10);
    exit(EXIT_SUCCESS);
}
2
samiam