Come reindirizzare l'output del servizio systemd su un file


171

Sto cercando di reindirizzare l'output di un systemdservizio su un file ma non sembra funzionare:

[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

Per favore, correggi il mio approccio.

Risposte:


234

Penso che ci sia un modo più elegante per risolvere il problema: inviare lo stdout / stderr a syslog con un identificatore e dare istruzioni al gestore syslog di dividere l'output in base al nome del programma.

Utilizzare le seguenti proprietà nel file dell'unità di servizio systemd:

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

Quindi, supponendo che la tua distribuzione stia utilizzando rsyslog per gestire syslog, crea un file /etc/rsyslog.d/<new_file>.confcon il seguente contenuto:

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

Ora rendi il file di registro scrivibile da 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

Riavvia rsyslog ( sudo systemctl restart rsyslog) e divertiti! Il tuo programma stdout / stderr sarà ancora disponibile tramite journalctl ( sudo journalctl -u <your program identifier>) ma saranno anche disponibili nel tuo file preferito.

Fonte tramite archive.org


8
Non funziona per me su Ubuntu 16.04. journalctl -ufunziona ancora ma non viene inviato nulla al file specificato.
Duncan Calvert,

1
Funziona alla grande su Debian stretch, tuttavia si lamenta che ~è deprecato e stopdovrebbe essere usato invece. Si noti inoltre che la seconda riga può essere accorciata & stopse i due si susseguono.
jlh

48
Con systemd 236 o più recente puoi anche scrivere direttamente su un file usando StandardOutput = file: / some / path github.com/systemd/systemd/pull/7198
leezu

5
Ho funzionato cambiando il /etc/rsyslog.d/<newfile>.confcontenuto in: :programname, isequal, "<your program identifier>" /var/log/somelog.log Ecco la documentazione sui filtri rsyslog : rsyslog.com/doc/v8-stable/configuration/filters.html Ed ecco i documenti sulle proprietà come programname: rsyslog.com/doc/master/configuration/properties .html
mbil,

1
Ho avuto problemi nell'uso di questa configurazione fino a quando non ho scoperto che rsyslogha un proprio utente sysloge che deve avere accesso in scrittura alla posizione dei registri. Quindi utilizzare di chownconseguenza. Spero che questo aiuti qualcuno.
Imaskar,

73

Se hai una distro più recente con una più recente systemd( systemdversione 236 o più recente ), puoi impostare i valori di StandardOutputo StandardErrorsu file:YOUR_ABSPATH_FILENAME.


Lunga storia:

Nelle versioni più recenti systemdc'è un'opzione relativamente nuova ( la richiesta github è del 2016 ish e il miglioramento è unito / chiuso nel 2017 ish ) dove è possibile impostare i valori di StandardOutputo StandardErrorto file:YOUR_ABSPATH_FILENAME. L' file:pathopzione è documentata nella pagina man più recentesystemd.exec .

Questa nuova funzionalità è relativamente nuova e quindi non è disponibile per le distribuzioni più vecchie come centos-7 (o qualsiasi centos prima).


10
Non funziona in Ubuntu 1604 nel 20-03-2018. La versione systemd di Ubuntu 1604 è solo 229.
uomo di bronzo,

Grazie, hai detto molto chiaro. Non riesco proprio a credere che il systemd in Ubuntu 1604 non riesca a reindirizzare l'output su un file semplicemente tramite la configurazione. Devo usare il modo sh per risolvere questo problema.
uomo di bronzo,

@bronzeman la richiesta di funzionalità non è stata chiusa fino al 2017, mentre Ubuntu 16.04 è uscito nel 2016. In una data versione importante di Ubuntu (ad esempio 16.04, 16.10, 17.04, ecc.), Ubuntu mantiene la compatibilità ABI nei suoi pacchetti di sistema principali. Quindi non aggiorneranno systemd (o il kernel Linux, o glibc o altro) a meno che non mantenga la stessa ABI di quando è stata rilasciata la versione di Ubuntu.
villapx,

1
FWIW: Ho cercato un po ', ma questa funzione non sembra avere disposizioni per la rotazione del registro, come la funzione per riaprire il file di registro, con uno che deve usare simili a copytruncatein logrotate.
Antak,

49

Probabilmente ottieni questo errore:

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

Dalla systemd.exec(5)pagina man:

StandardOutput=

Controlla dove è collegato il descrittore di file 1 (STDOUT) dei processi eseguiti. Prende una delle inherit, null, tty, journal, syslog, kmsg, journal+console, syslog+console, kmsg+consoleo socket.

La systemd.exec(5)pagina man spiega altre opzioni relative alla registrazione. Vedi anche le pagine man systemd.service(5)e systemd.unit(5).

O forse puoi provare cose del genere (tutte su una riga):

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

7
Tra le opzioni, si consiglia di accedere al journal di systemd. È possibile visualizzare solo i registri per il processo nel journal utilizzando journalctl -u your-unit-name.
Mark Stosberg,

6
Per specificare un file, c'è un'altra opzione più pulita, come indicato dalla documentazione: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").
Orion

5
Risposta incredibile, ha risolto il mio problema. Voglio solo di estendere perché, al momento, se il servizio di riavvio sovrascrivere i vecchi tronchi, necessario sostituire questa parte: 2>&1 > /var/log.loga questo: 2>&1 >> /var/log.log. Grazie
PumpkinSeed

10
Francamente, chiamare shell con una stringa di comando in ExecStart sembra il modo davvero sbagliato di farlo.
David Tonhofer,

1
"/ bin / sh" è un'ottima soluzione, ma DEVI usare "exec", altrimenti il ​​servizio non si riavvierà correttamente poiché SIGTERM non verrà passato al processo figlio. Vedi veithen.io/2014/11/16/sigterm-propagation.html
Ricco

33

Suggerirei di aggiungere stdoute stderrarchiviare il servicefile systemd stesso.

Riferendosi: https://www.freedesktop.org/software/systemd/man/systemd.exec.html#StandardOutput=

Come hai configurato, non dovrebbe piacere:

StandardOutput=/home/user/log1.log
StandardError=/home/user/log2.log

Dovrebbe essere:

StandardOutput=file:/home/user/log1.log
StandardError=file:/home/user/log2.log

Funziona quando non si desidera riavviare il servizio ancora e ancora .

Ciò creerà un nuovo file e non verrà aggiunto al file esistente.

Usa invece:

StandardOutput=append:/home/user/log1.log
StandardError=append:/home/user/log2.log

NOTA: assicurarsi di aver già creato la directory. Immagino che non supporti la creazione di una directory.


5
Duplica di questa risposta , con meno dettagli
Gert van den Berg,

9
Penso che l'ho reso più diretto \ facile da capire.
Rajat jain

1
Per me il file:percorso funziona al primo caricamento del servizio, ma ai successivi riavvii non scrive più nel file. Ho provato append:dai documenti e non ha funzionato affatto.
rb-

3
Si noti che i documenti chiariscono che file:scrive ogni volta all'inizio del file e non si troncano ... inoltre, append:sembra essere una nuova aggiunta (ovvero non presente nella man systemd.execpagina su Ubuntu 18.04).
Cole

19

Se per qualche motivo non è possibile utilizzare rsyslog, ciò farà: ExecStart=/bin/bash -ce "exec /usr/local/bin/binary1 agent -config-dir /etc/sample.d/server >> /var/log/agent.log 2>&1"


Cosa fa l'opzione -e di bash?
Lampada

3

Supponiamo che i log siano già messi su stdout / stderr e abbiano il login dell'unità systemd/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 (System Logging Service)

# 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

Riavvia rsyslog

systemctl restart rsyslog.service

1

Stiamo usando Centos7, l'applicazione di avvio a molla con systemd. Stavo correndo Java come di seguito. e l'impostazione di StandardOutput su file non funzionava per me.

ExecStart=/bin/java -jar xxx.jar  -Xmx512-Xms32M

Di seguito la soluzione alternativa funziona senza impostare StandardOutput. eseguendo java attraverso sh come di seguito.


ExecStart=/bin/sh -c 'exec /bin/java -jar xxx.jar -Xmx512M -Xms32M >> /data/logs/xxx.log 2>&1'

inserisci qui la descrizione dell'immagine


-1 per la definizione dei parametri jvm in ordine errato. -Xmx512M deve essere definito prima di -jar. È previsto anche ciò che sperimenti. Systemd non invoca i servizi utilizzando la shell
Sami Korhonen,

1
@SamiKorhonen, ho aggiunto i miei commenti dopo aver testato che funziona. Anche io stavo pensando all'ordine di -Xmx512M ti fa sorridere. Si prega di testare prima di aggiungere commenti non vedenti.
Santhosh Hirekerur,

0

Risposta breve:

StandardOutput=file:/var/log1.log
StandardError=file:/var/log2.log

Se non si desidera cancellare i file ogni volta che si esegue il servizio, utilizzare invece append:

StandardOutput=append:/var/log1.log
StandardError=append:/var/log2.log

2
Duplica di questa risposta , con meno dettagli
rustyx il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.