Registra la rotazione di stdout?


53

Ho un programma Linux che può scrivere informazioni su stdout e stderr.

Ho uno script di shell che reindirizza l'output su un file /var/log. (Via >>e 2>&1.)

C'è un modo per far ruotare quel file di registro? (dimensione massima, quindi passa a un altro file, mantieni solo un numero limitato di file)

Ho visto alcune risposte che parlano del logrotateprogramma, che suona bene, ma sembrano anche concentrarsi su programmi che generano internamente file di registro e gestiscono segnali HUP. C'è un modo per farlo funzionare con uno script di reindirizzamento dell'output di base?


1
Perché non puoi semplicemente modificare lo script che reindirizza l'output per contenere la logica per la rotazione?
MaQleod,

Potrei, se qualcuno potesse dirmi come rilevare la dimensione di un file di registro e ruotarlo da sotto lo stdout di un processo senza disturbarlo. Non devo usare logrotatese c'è un'opzione migliore, che sembrava solo un comodo punto di partenza per la discussione.
Miral,

2
Non è necessario utilizzare logrotate, ma l'utilizzo di logrotate consente solo di risparmiare tempo ... Di solito è poco utile reinventare la ruota.
bubu,

Esattamente il mio punto. Quindi c'è un modo per far funzionare logrotate con lo stdout reindirizzato di un processo in corso?
Miral,

Risposte:


44

In alternativa, è possibile reindirizzare l'output tramite strumenti progettati con lo scopo principale di mantenere set di file di registro con dimensioni limitate, ruotati automaticamente, come:

Gli strumenti per elaborare i multilogformati di file di log di formattazione includono, tra gli altri:

Ulteriori letture


1
Grazie, multilogsembra proprio quello di cui avevo bisogno.
Miral

multilog sembra essere l'unica soluzione plug-and-play in debian (daemontools ha un pacchetto ufficiale). Ma nel mio caso particolare, dove volevo archiviare i log su una partizione fat32, la rotazione non funziona, poiché multilog vuole usare un link simbolico. Nessun plug and play per me :)
Arnout

Ciò non può essere vero, poiché multilognessun luogo crea o esige collegamenti simbolici. È del tutto neutrale rispetto a loro.
JdeBP,

L'URL di "Non usare logrotate o newsyslog in questo secolo" ha un punto in più
duyue

15

lo rotatelogsstrumento fornito con apache (nella bindirectory) (vedi documenti ) accetta input da stdin e ruota il registro dopo un determinato periodo di tempo


14

Se puoi farlo andare su uno dei flussi di log standard (syslog, demone, cron, utente, sicurezza, posta, ecc.) Puoi invece usare il loggercomando e pipe ad esso.

echo "Hello." | logger -p daemon.info

Altrimenti, è meglio eseguire il piping del contenuto registrato a un programma o script personalizzato per gestirlo o guardare l'impostazione della logrotateconfigurazione.

EDIT: la risposta di JdeBP sembra avere quello che potresti cercare.


2
+1 per semplicità. A proposito, puoi anche configurare una funzione personalizzata (local0) invece di quelle standard (demone nel tuo esempio)
Roger Keays,

14

Ho avuto un problema simile e inizialmente avevo scartato logrotate ma si è scoperto che logrotate può effettivamente farlo bene, la direttiva chiave è " copytruncate ". Per qualche motivo quel termine non è emerso in nessuno dei googling che ho fatto, quindi sto aggiungendo questa risposta per chiarire esattamente come usarlo per questo caso.

Il trucco è che funziona solo se il reindirizzamento viene eseguito con " >> " (append) anziché " > " (create).

File di configurazione (truncate.cfg):

/tmp/temp.log {
    size 10M
    copytruncate
    rotate 4
    maxage 100
}

Programma di prova (non rinuncia mai al file). Puoi vederlo riempire il disco e sebbene l'eliminazione del file di registro sembrerà funzionare, in realtà non libererà spazio sul disco:

cat /dev/urandom >> /tmp/temp.log

Ruota registro in esecuzione:

logrotate truncate.cfg

È una buona teoria, ma in realtà non funziona su nessun sistema su cui l'ho provato. Il file non viene effettivamente troncato e il programma continua ad aggiungerlo come prima. (E sì, questo è anche con il reindirizzamento effettuato tramite >>.) ((A proposito, questa risposta è già stata data in precedenza.))
Miral

1
... come discusso in logrotate non troncerà il file originale (sul nostro sito Unix e Linux). Inoltre, echo /dev/urandom >> /tmp/temp.logscriverà 13 caratteri deterministici /tmp/temp.loge poi uscirà immediatamente. Volevi dire cat /dev/urandom?
G-Man dice "Ripristina Monica" il

2
Ho appena testato qui e sembra funzionare. Il contenuto del file viene copiato nel nuovo file di registro. Il file originale viene mantenuto aperto dal processo e viene troncato (la dimensione ora mostra 0).
Philipp,

1
Prestare attenzione alla possibile perdita di dati con copytruncate.
wanghq,

1
+1 anche se "Notare che c'è un intervallo di tempo molto piccolo tra la copia del file e il suo troncamento, quindi alcuni dati di registrazione potrebbero andare persi."
Tagar,

3

Quindi c'è un modo per far funzionare logrotate con lo stdout reindirizzato di un processo in corso?

Sì! Scopri la direttiva "copytruncate" offerta da logrotate. Specificare che indica a logrotate di gestire proprio questa situazione: un semplice programma che mantiene il suo file di registro aperto indefinitamente.

Un avvertimento può o meno essere un problema nella tua situazione:

Si noti che c'è un intervallo di tempo molto piccolo tra la copia del file e il suo troncamento, quindi alcuni dati di registrazione potrebbero andare persi.

Aneddoticamente, ho visto alcune fonti di log del "mondo reale" che incoraggiano gli utenti ad applicare questa direttiva. C'è qualche discussione su questa opzione qui .


3

Usa split, fa parte di coreutils. Può prendere lo stdin e dividerlo in blocchi (in base alla dimensione del blocco, al numero di linee, ecc.).

Esempio:

app | split --bytes 1G - /var/logs/put-prefix-here

Il trattino della nota (-) indica a "split" di usare stdin invece del file.


Puoi espandere la tua risposta per descrivere come farlo? Grazie.
fixer1234,

ho appena aggiornato la mia risposta con l'esempio.
Nazar,

L'1G ha una dimensione arbitraria, dopo di che avvia un nuovo file?
fixer1234,

1
Questa non è una soluzione particolarmente buona al problema perché significa che puoi finire con metà messaggio in un file e metà nel successivo. C'è anche il rischio di perdita di dati se la macchina si arresta in modo anomalo mentre splitcontiene dati in quello che potrebbe essere un buffer di grandi dimensioni. Dato che ci sono più strumenti che risolvono correttamente questo problema, non credo che questo tipo di soluzione roll-your-own possa essere assolutamente raccomandato.
David Richerby,

1
@David Richerby- che ne dici di aggiungere -u per non bufferizzato?
Nick,

3

Mi piace multilogper il mio caso d'uso, ma il mio caso d'uso è così banale / semplice che non è esposto molto semplicemente nei documenti / esempi che ho trovato. Ecco un semplice esempio di rotazione multipla:

mkdir /tmp/myapp
./myapp | multilog t s10000 n5 '!tai64nlocal' /tmp/myapp 2>&1

Alcune note:

  • questo dump accede a quella directory / tmp / myapp /
  • s10000 rappresenta 10.000 byte *
  • n5 rappresenta 5 file. * Il registro 'corrente' conta come uno dei file, quindi include 4 registri più vecchi + 'corrente'
  • questo si basa, adattato dagli esempi forniti da François Beausoleil su: http://blog.teksol.info/pages/daemontools/best-practices
  • Non capisco molte delle opzioni - ti rimando alla diversa documentazione per estendere questo ...
  • I documenti avvertono che: "Note that running processor may block any program feeding input to multilog."dove "processore" è la '!tai64nlocal'parte del comando

* Per molte applicazioni, queste sono scelte sbagliate per un uso a lungo termine. Consentono di osservare il comportamento del riempimento e della rotazione dei registri più rapidamente rispetto ai registri di grandi dimensioni.

Infine, non dimenticare di fare nulla se necessario! Con nohup, non hai bisogno di 2>&1(s = 10e6 e n = 30 qui):

mkdir -p /tmp/myapp
nohup ./myapp | multilog t s10000000 n30 '!tai64nlocal' /tmp/myapp &

Questo comando dovrebbe iniziare.


1

Volevo solo aggiungere al commento di Sam Hendley sopra:

Il trucco è che funziona solo se il reindirizzamento viene eseguito con >>(append) anziché >(create).

Ho riscontrato lo stesso problema in cui il file originale continua a crescere se si utilizza >(crea) ma se si utilizza >>(aggiungi) Logrotate copytruncate funziona perfettamente e come previsto. Il file originale torna a zero byte e il programma continua a scrivere.

Reindirizzare STDOUT e STDERR su un file di registro rotante:

  1. some-program.sh >> /tmp/output.txt 2>&1 &
  2. Crea un file di configurazione logrotate sotto /etc/logrotate.dqualunque cosa, output_roll nel mio caso.

    Esempio di configurazione per il mio caso:

    /tmp/output.txt {
        notifempty
        missingok
        size 1G
        copytruncate
        start 0
        rotate 15
        compress
    }
    
  3. Imposta il tuo cron job all'interno del /etc/crontabfile

    *  *  *  *  * root /usr/sbin/logrotate /etc/logrotate.d/output_roll
    

    Questo controllerà il file ogni minuto. Puoi adattarti alle tue esigenze.

  4. Avvialo:

    $> service crond restart
    
  5. Questo è tutto

Nota: ho anche avuto un problema con SELinux impostato su, SELINUX=enforcingquindi l'ho impostato su SELINUX=disabled.


1

Ho scritto un logrotee questo fine settimana. Probabilmente non lo farei se avessi letto la grande risposta di @ JdeBP e multilog.

Mi sono concentrato sul fatto che fosse leggero e in grado di bzip2 i suoi blocchi di output come:

verbosecommand | logrotee \
  --compress "bzip2 {}" --compress-suffix .bz2 \
  /var/log/verbosecommand.log

Tuttavia, c'è ancora molto da fare e testare.

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.