tags search: script
LogHappens - come tenere d'occhio i log files, senza impazzire
Qualche tempo fa ho scoperto un tool dal nome divertente e con uno scopo utilissimo: poter tenere d'occhio log files, a piacimento, senza diventare matti interpretando file di testo da centinaia di righe, solitamente formattati in modo non troppo chiaro.
Tutto molto bello, peccato che creare dei nuovi parser è un delirio di regex, regole e requisiti non proprio chiarissimi... così ho iniziato a fare un mio parser.
LogHappened
Così è nato LogHappens. La grafica è minimale e molto semplice: un menu laterale in cui scegliere il log che si vuole visualizzare, un contatore per avere sempre un'idea di quante entries sono presenti per ogni log file... ed i log. Suddivisi come preferisci, anche se probabilmente farlo per data e ora è il modo più semplice. Quando succede qualcosa di nuovo, per esempio viene rilevato una nuova entry in uno dei file, LogHappens mostra un popup del browser (mostrato quindi dal sistema operativo, anche quando l'app non è in primo piano).
Sì, ma come funziona?
Il funzionamento, come dicevo, doveva essere molto semplice: In una cartella `logics` sono presenti tanti files quanti sono i log che vuoi tenere sotto controllo. Nella cartella `logics_templates` sono presenti invece, come puoi immaginare, alcuni esempi di file logics. Uno di questi serve per interpretare i log files di apache, e contiene questo codice:
<?php
$menu = [
'icon' => 'build',
'color' => 'red',
'title' => 'Apache error.log',
'file' => '/var/log/apache2/error.log'
];
$content = file($menu['file']);
$log = [];
foreach ($content as $line) {
// Grab the log's time and group logs by time
$time = substr($line, 1, 19);
$time = date("l d-m-Y - H:i:s", strtotime($time));
// Remove date-time and other useless informations from the log details
$line = substr($line, 34);
$line = preg_replace('[\[:error.*\]]', '', $line);
$line = preg_replace('[\[pid .*\]]', '', $line);
$line = str_replace('PHP', '', $line);
$line = trim($line);
// Highlight the type of errors, using a badge
$line = preg_replace("/^Notice: /", "Notice: ", $line);
$line = preg_replace("/^Warning: /", "Warning: ", $line);
$line = preg_replace("/^Fatal error: /", "Fatal error: ", $line);
$line = preg_replace("/^Parse error: /", "Parse error: ", $line);
$line = preg_replace("/^Error: /", "Error: ", $line);
// Save the log entry
$log[$time][] = $line;
}
// Reverse the logs, so that we can see last errors first
$logs = array_reverse($log);
Piuttosto semplice, non è vero? Modificando un po' questo file, è possibile creare un parser per virtualmente qualunque tipo di log file.
Stampare un PDF per ogni file LibreOffice in una directory
Questa mattina avevo necessità di creare un file PDF per ogni file LibreOffice CALC presente in una directory. È una cosa che devo fare, periodicamente, ed aprire i singoli file è un'operazione noiosa, soprattutto quando iniziano ad esserci decine di documenti da convertire.
Per fortuna uso linux :) ed è semplice creare uno script che mi permetta di effettuare quest'operazione da linea di comando... ma ancora non mi è sufficiente, vorrei poterlo fare direttamente da Nautilus.
Detto fatto
Prima di tutto è necessario creare un nuovo file nella directory ~/.local/share/nautilus/scripts, io l'ho chiamato "Crea PDF da documento LibreOffice" (senza estensione perché anche quest'ultima verrebbe mostrata nel menu contestuale di Nautilus). Dentro ci ho messo questo:
#!/usr/bin/perl -w
# By Emanuele "ToX" Toscano
use strict;
my @files = split("\n", $ENV{NAUTILUS_SCRIPT_SELECTED_FILE_PATHS});
foreach my $file (@files)
{
if ( -f $file )
{
system("libreoffice --headless --convert-to pdf --outdir ./pdf/ '$file'");
shift;
}
}
Ho salvato il file, l'ho reso eseguibile, ho selezionato un po' di files e cliccato tasto destro... vedo che lo script "Crea PDF da documento LibreOffic", lo lancio e... inaspettatamente ha funzionato tutto al primo colpo :) Mi ha creato tanti file PDF quanti erano i file selezionati, e li ha salvati all'interno di una sottocartella "pdf".
Facile, no? :)
Affiancare più video con FFMPEG
Oggi ho avuto necessità di fare una cosa diversa dal solito: niente programmazione, ma ho dovuto realizzare un video che fosse il risultato di quattro video, affiancati due a due (2 video sopra, 2 video sotto).
Realizzare qualcosa del genere può sembrare difficile, ma con gli strumenti giusti (ed un minimo di dimestichezza con la shell) si tratta di una cosa veramente semplice. Dopo un po' di ricerche e di tentativi, ecco il risultato:
#!/bin/bash ffmpeg -i 1.avi -vf "movie=2.avi [in1]; [in]pad=500:210:color=white[in0]; [in0][in1] overlay=250:0 [out]" -crf 5 -b:v 8M out1.avi ffmpeg -i 3.avi -vf "movie=4.avi [in1]; [in]pad=500:236:color=white[in0]; [in0][in1] overlay=230:15 [out]" -crf 5 -b:v 8M out2.avi ffmpeg -i out1.avi -vf "movie=out2.avi [in1]; [in]pad=500:446:color=white[in0]; [in0][in1] overlay=0:216 [out]" -crf 5 -b:v 8M out.avi rm out1.avi rm out2.avi
La prima riga affianca i primi due video (1.avi e 2.avi) in un file temporaneo chiamato out1.avi. Le dimensioni del file risultante sono specificate nell'istruzione pad=500:210, che si occupa di "creare" lo spazio in cui inserire il secondo video, impostando uno sfondo bianco fra un video e l'altro (ho voluto lasciare qualche pixel di distanza fra i due video). L'istruzione overlay=250:0 invece inserisce il secondo video nello spazio creato in precedenza, a 250px da sinistra e 0 dall'alto.
I parametri finali (-crf 5 -b:v 8M) sono necessari per mantenere una qualità decente nel file risultante. Non conosco precisamente il significato di questi parametri, so solo che mi hanno permesso di mantenere inalterata la qualità iniziale dei singoli video. Per maggiori informazioni, consulta il manuale di ffmpeg.
La seconda riga fa la stessa cosa con i file 3.avi e 4.avi, creando un file out2.avi.
La terza riga prende out1.avi e out2.avi e li posiziona uno sopra l'altro. Le istruzioni sono simili, cambiano solamente il padding e l'overlay.
Fatto questo elimino i file temporanei et voilà, il file out.avi contiene i 4 video, affiancati.
Facile, no?
Pre-push GIT Hook - Aggiornare un sito remoto ed il database tramite SSH con un git push
In questi giorni mi è capitato di dover lavorare su un nuovo progetto e di dover caricare le modifiche online man mano che il procedimento andava avanti... siccome farlo manualmente è un'operazione noiosa e ad alto rischio di errori (collegati all'ftp, carica le modifiche, elimina i files non più utilizzati...) ho pensato di sfruttare la potenza e la velocità di rsync agli hooks di GIT per effettuare questa operazione in automatico, ogni volta che faccio un push.
Puoi vedere il gist a questo indirizzo: Gist
Il funzionamento è molto semplice, eccolo riassunto:
#!/bin/sh ############## ## CONFIGURATION ############## # remote access sshUser="" sshPass="" remoteServer="192.168.1.1" remotePath="/var/www/production" # local database localDbName="myapp" # remote database remoteDdbUser="root" remoteDbPass="" remoteDbName="myapp" ############## ## WORKFLOW ############## # create a database backup and add it to the last commit (amend) mysqldump -uroot --skip-extended-insert $localDbName > database.sql git add database.sql git commit --amend --no-edit # since you can't force the password for SSH, echo it here as a hint (don't do this for critical projects! :)) echo When prompted, please insert this password: $sshPass # update all the files through rsync echo echo Updating files... rsync -rzhe ssh --delete --filter=':- .gitignore' ./ $sshUser@$remoteServer:$remotePath # update the database echo echo Updating database... cat database.sql | ssh $sshUser@$remoteServer "mysql -u$remoteDdbUser -p$remoteDbPass $remoteDbName" # and you're done! exit 0
Facile, no?
Personalizzare la shell bash quando si lavora su un progetto GIT
Per chi utilizza GIT da riga di comando può essere utile avere sottomano lo stato del proprio repository, per sapere al volo se ci sono dei file modificati mandare in stage, se c'è da farne il commit o se c'è qualcosa da pushare.
Per fortuna il file .bashrc ci viene in aiuto ed è (relativamente) semplice personalizzare la propria shell Bash secondo le nostre necessità. Nella fattispecie, ho optato per indicare in rosso fra parentesi graffe il nome del branch attivo in cui sono presenti files modificati non ancora mandati in stage, in giallo (sempre fra graffe) i files in stage di cui fare il commit, mentre in verde (fra parentesi tonde) i repository puliti, con un asterisco ad indicare se è necessario fare il push fra il repository locale e quello remoto. In azzurro, infine, i repository che contengono untracked files.
Dopo un po' di utilizzo sono soddisfatto del risultato, è comodo avere quelle informazioni a portata di mano senza dover fare git status ogni volta.
Se vuoi implementare anche tu questa modifica, segui le istruzioni che trovi qua (https://github.com/ToX82/git-bashrc).
Facile, no?
Backup script differenziale con salvataggio su mega.co.nz, il tutto in BASH
Script di backup ne ho già trovati, letti e scritti diversi in passato. Più o meno funzionavano tutti bene ma nessuno faceva davvero quello che mi serviva, cioè offrirmi un solo comando per effettuare il backup differenziale di files e database, impacchettamento del tutto e salvataggio su un luogo al sicuro anche da danni fisici alla macchina stessa. Così ne ho fatto uno nuovo :) Ma partiamo dal fondo.
Mega.co.nz
Ho scelto di usare mega.co.nz per diversi motivi: il primo è che mette un sacco di spazio a disposizione gratuitamente (50gb) ed un'infinità di spazio con i piani a pagamento. Il secondo è che i files vengono criptati lato client prima di essere trasferiti. Questo aiuta la protezione durante il traferimento ed evita che i dati vengono salvati in modo leggibile sul cloud. Infine ci sono degli ottimi tool da riga di comando per usare mega su linux, cosa fondamentale visto che dobbiamo utilizzarli in uno script BASH. Per il trasferimento dal server al cloud ho optato per un tool scritto in Python chiamato megacl, che è incredibilmente comodo e facilmente installabile su qualunque sistema operativo linux (ho provato anche megacmd, ma su debian wheezy andava in segmentation fault).
Ma io voglio salvare i backup in locale!
È un tuo diritto. Vai nelle configurazioni (vedi sotto) ed imposta la variabile BACKUP_ON_MEGA a false. In questo modo non avrei necessità di installare megacmd, ed i backup verranno mantenuti nella directory di destinazione (naturalmente i backup vecchi vengono cancellati, mantenendo solamente gli ultimi 2 backup completi ed almeno gli ultimi 7 differenziali).
Backup
I backup, come dicevo, sono differenziali: il primo backup è ovviamente completo mentre gli altri contengono solamente i file che sono cambiati rispetto all'ultimo backup completo. Ogni primo giorno del mese viene fatto un altro backup completo. Vengono salvati sia i files che i database (tutti, oppure solo quelli specificati in un apposito file).
Configurazione
La configurazione richiede il minimo indispensabile:
MAIL='miamail@email.com' ORIGIN='/var/www' DESTINATION='/media/External/Backups' BACKUP_ON_MEGA=true DB_USER='root' DB_PASS=''
Abbastanza semplice, no? :)
Puoi trovare lo script a questo indirizzo.
Per lanciarlo è sufficiente eseguire ./megabackup.sh da utente, mentre per automatizzarlo si può usare crontab... Più semplice di così!