J'essaye d'écrire propre démon à la MPD très simple (c'est le travail de laboratoire de systèmes d'exploitation). Je l'ai fait fonctionner: il commence comme un démon (sortie de ps):
1 14877 14877 14877 ? -1 Ss 0 0:00 lab1_daemon
ça joue, ça reçoit des signaux.
Le problème est que je ne peux pas l'exécuter avec systemd. J'ai écrit un file .service très simple:
[Unit] Description=Operating systems lab 1 daemon [Service] Type=forking PIDFile=/run/lab1_daemon.pid ExecStart=/path/lab1_daemon [Install] WantedBy=multi-user.target
Mais quand je lance daemon avec systemctl start
il se bloque pendant 0,5 min et puis dans les journaux je vois:
Failed to read PID from file /run/lab1_daemon.pid: Invalid argument lab1_daemon.service never wrote its PID file. Failing.
Mais ça l'a fait! Je l'ai vérifié:
-rw-r--r-- 1 root root 13 Mar 5 00:13 /run/lab1_daemon.pid
Qu'est ce que j'ai mal fait?
PS: J'ai même essayé la fonction daemon
pour vérifier, que j'ai fait la démonisation correctement. Mais j'ai eu les mêmes résultats. Code source minimal (58 LOC, déplacé de 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 <ssortingng.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); }
De la documentation de systemd, je suppose que le problème est le format incorrect de votre file PID. Au lieu d'écrire "PPID: yourpid ". Vous devriez juste écrire " yourpid ". Par ailleurs, PID signifie Process ID et PPID pour Parent Process ID. Vous ne pouvez pas les utiliser de manière interchangeable.
Donc au lieu de
char buf[16]; sprintf(buf, "PPID: %ld\n", (long)getpid()); write(lock_file, buf, strlen(buf) + 1);
Tu devrais faire
fprintf(lock_file, "%ld\n", (long) getpid());
Ce serait aussi une bonne pratique de débloquer le file que @samiam dit dans sa réponse.
Je ne pense pas que systemd puisse lire un file qui est verrouillé. Essayez quelque chose comme ceci:
void unlockfile() { struct flock fl; fl.l_type = F_UNLCK; /* etc. */ return fcntl(fd, F_SETLK, &fl); }
Depuis que pastebin a des publicités parlantes désagréables, voici le code source complet de l'affiche originale:
#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 <ssortingng.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); }