221 votes

Comment rediriger la sortie du service systemd vers un fichier

J'essaie de rediriger la sortie d'un systemd dans un fichier mais cela ne semble pas fonctionner :

[Unit]
Description=customprocess
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/bin/binary1 agent -config-dir /etc/sample.d/server
StandardOutput=/var/log1.log
StandardError=/var/log2.log
Restart=always

[Install]
WantedBy=multi-user.target

Veuillez corriger mon approche.

300voto

Valerio Versace Points 1204

Je pense qu'il existe une manière plus élégante de résoudre le problème : envoyez le stdout/stderr à syslog avec un identifiant et demandez à votre gestionnaire syslog de diviser sa sortie par nom de programme.

Utilisez les propriétés suivantes dans votre fichier d'unité de service systemd :

StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=<your program identifier> # without any quote

Ensuite, en supposant que votre distribution utilise rsyslog pour gérer les syslogs, créez un fichier dans le répertoire /etc/rsyslog.d/<new_file>.conf avec le contenu suivant :

if $programname == '<your program identifier>' then /path/to/log/file.log
& stop

Maintenant, rendez le fichier journal accessible en écriture par syslog :

# ls -alth /var/log/syslog 
-rw-r----- 1 syslog adm 439K Mar  5 19:35 /var/log/syslog
# chown syslog:adm /path/to/log/file.log

Redémarrer rsyslog ( sudo systemctl restart rsyslog ) et profitez-en ! Votre programme stdout/stderr sera toujours disponible via journalctl ( sudo journalctl -u <your program identifier> ) mais ils seront également disponibles dans le fichier de votre choix.

Source : archive.org

10 votes

Ne fonctionne pas pour moi sur Ubuntu 16.04. journalctl -u fonctionne toujours mais rien n'est envoyé au fichier spécifié.

1 votes

Cela fonctionne trÃ?s bien sur Debian stretch, mais il se plaint que ~ est déprécié et stop doit être utilisé à la place. Notez également que la deuxième ligne peut être raccourcie en & stop si les deux se suivent.

70 votes

Avec systemd 236 ou plus récent, vous pouvez également écrire directement dans un fichier en utilisant StandardOutput=file:/some/path. github.com/systemd/systemd/pull/7198

104voto

Trevor Boyd Smith Points 3513

Si vous avez une distro plus récente avec une nouvelle systemd ( systemd version 236 ou plus récente ), vous pouvez définir les valeurs de StandardOutput o StandardError a file:YOUR_ABSPATH_FILENAME .


Longue histoire :

Dans les versions plus récentes de systemd il existe une option relativement nouvelle ( la demande github date de 2016 environ et l'amélioration a été fusionnée/fermée en 2017 environ. ) où vous pouvez définir les valeurs de StandardOutput o StandardError a file:YOUR_ABSPATH_FILENAME . Le site file:path est documentée dans le document le plus récent systemd.exec page de manuel .

Cette nouvelle fonctionnalité est relativement récente et n'est donc pas disponible pour les anciennes distributions comme centos-7 (ou tout autre centos avant cela).

12 votes

Ne fonctionne pas dans ubuntu 1604 en 2018-03-20. La version de systemd dans ubuntu 1604 est seulement 229.

0 votes

Merci, vous avez dit très clairement. Je ne peux pas croire que le systemd dans ubuntu 1604 ne peut pas rediriger la sortie vers un fichier juste par la configuration.je dois utiliser la manière sh pour résoudre ce problème.

0 votes

@bronzeman la demande de fonctionnalité n'a pas été fermée avant 2017, alors qu'Ubuntu 16.04 est sortie en 2016. Dans une version majeure donnée d'Ubuntu (par exemple 16.04, 16.10, 17.04, etc.), Ubuntu maintient la compatibilité ABI dans ses paquets système de base. Ainsi, ils ne mettront pas à jour systemd (ou le noyau Linux, ou glibc, ou quoi que ce soit) à moins qu'il ne maintienne la même ABI que lorsque la version Ubuntu a été publiée pour la première fois.

52voto

Shuangistan Points 531

Vous pouvez obtenir cette erreur :

Failed to parse output specifier, ignoring: /var/log1.log

De la systemd.exec(5) page de manuel :

StandardOutput=

Contrôle où le descripteur de fichier 1 (STDOUT) des processus exécutés est connecté. Prend l'une des options suivantes inherit , null , tty , journal , syslog , kmsg , journal+console , syslog+console , kmsg+console o socket .

El systemd.exec(5) La page de manuel explique d'autres options liées à la journalisation. Voir également la page systemd.service(5) y systemd.unit(5) pages du manuel.

Ou peut-être pouvez-vous essayer des choses comme ceci (tout sur une ligne) :

ExecStart=/bin/sh -c '/usr/local/bin/binary1 agent -config-dir /etc/sample.d/server 2>&1 > /var/log.log'

7 votes

Parmi les options, il est recommandé de se connecter au journal systemd. Vous visualisez uniquement les journaux de votre processus dans le journal à l'aide de la commande journalctl -u your-unit-name .

6 votes

Pour spécifier un fichier, il existe une autre option plus propre, comme l'indique la documentation : The fd option connects the output stream to a single file descriptor provided by a socket unit. A custom named file descriptor can be specified as part of this option, after a ":" (e.g. "fd:foobar").

5 votes

Excellente réponse, elle a résolu mon problème. Je veux juste étendre, parce qu'actuellement si le service redémarre écraser les anciens journaux, ont à remplacer cette partie : 2>&1 > /var/log.log à ça : 2>&1 >> /var/log.log . Merci.

22voto

Tigra Points 1134

Si pour une raison quelconque, vous ne pouvez pas utiliser rsyslog, ceci fera l'affaire : ExecStart=/bin/bash -ce "exec /usr/local/bin/binary1 agent -config-dir /etc/sample.d/server >> /var/log/agent.log 2>&1"

0 votes

Que fait l'option -e de bash ?

0 votes

La seule solution qui a fonctionné dans mon cas pour ne pas perdre le fichier journal à chaque redémarrage du service comme append n'est pas disponible dans ma version actuelle de systemd malheureusement.

4voto

Hieu Huynh Points 53

Supposons que les journaux sont déjà mis à stdout/stderr et faire en sorte que l'unité systemd se connecte /var/log/syslog

journalctl -u unitxxx.service

Jun 30 13:51:46 host unitxxx[1437]: time="2018-06-30T11:51:46Z" level=info msg="127.0.0.1
Jun 30 15:02:15 host unitxxx[1437]: time="2018-06-30T13:02:15Z" level=info msg="127.0.0.1
Jun 30 15:33:02 host unitxxx[1437]: time="2018-06-30T13:33:02Z" level=info msg="127.0.0.1
Jun 30 15:56:31 host unitxxx[1437]: time="2018-06-30T13:56:31Z" level=info msg="127.0.0.1

Config rsyslog (Service de journalisation du système)

# Create directory for log file
mkdir /var/log/unitxxx

# Then add config file /etc/rsyslog.d/unitxxx.conf

if $programname == 'unitxxx' then /var/log/unitxxx/unitxxx.log
& stop

Redémarrer rsyslog

systemctl restart rsyslog.service

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X