sabato 30 giugno 2012

È permesso ?

Uno degli aspetti più interessanti dei sistemi operativi Posix è sicuramente la semplicità dei concetti su cui si basano, tanto che chiunque abbia tentato di stravolgere questi concetti inventandosi nuove strategie, ha finito per complicare enormemente le cose e conseguentemente ha dovuto correre ai ripari.

Pensiamo per esempio ai permessi. Per capire i permessi di Unix anni fa, mi è bastato leggere un paio di pagine di un libro e fare due prove su un HP-UX , ma le potenzialità di una simile gestione, dei livelli di accessi degli utenti, dei gruppi e di root, è passata con nonchalance dai mainframes ai telefoni Android.

Suid e Guid

Il sistema dei permessi di Linux come delle altre macchine Posix è piuttosto rigoroso.

Sappiamo che il kernel, dopo avere predisposto le varie funzionalità lancia un programma e lo fa con delle righe di codice sorgente, sublimi nella loro semplicità :

Estratto di init/main.c 



 ...

 /*
  * We try each of these until one succeeds.
  *
  * The Bourne shell can be used instead of init if we are
  * trying to recover a really broken machine.
  */
  if (execute_command) {
      run_init_process(execute_command);
      printk(KERN_WARNING "Failed to execute %s.  Attempting "
                  "defaults...\n", execute_command);
  }
  run_init_process("/sbin/init");
  run_init_process("/etc/init");
  run_init_process("/bin/init");
  run_init_process("/bin/sh");

  panic("No init found.  Try passing init= option to kernel. "
        "See Linux Documentation/init.txt for guidance.");

...

 


Belle vero ?

Comunque, che abbiate apprezzato o meno, sappiate che al processo init è assegnato un PID 1 e un UID di processo uguale a 0, quindi dall'alto della sua posizione di root, init lancia tutta una serie di processi aggiuntivi, come i servizi e i login.

Sono proprio i login che vanno a curiosare nel file passwd, per cercare l'utente che vuole loggarsi e poi, dopo avere verificato i suoi diritti col vecchio sistema del confronto hash o col moderno sistema delle pam, cambia l'UID con quello dell'utente loggato, il quale non essendo presumibilmente root non potrà più cambiarlo, convalidando così tutto il sistema dei permessi.

In questo modo all'utente non sarebbe mai concesso di diventare root senza eseguire una login come tale o senza valide scappatoie, tipo agire attraverso un servizio, come quelli che mettono a disposizion gdm e kdm quando un utente chiede per esempio lo shutdown.

Esiste però un altro modo, si chiama bit di suid, il quale apre tutta una serie di possibilità e di vulnerabilità che spesso i sistemisti amano rimuovere con l'apposita opzione di mount "nosuid" sui volumi bollenti.

Se infatti è impostato il bit 11, cioè il famoso bit di "set uid", su un file eseguibile, quando il nostro valoroso processo, tenterà di "eseguire", il file cambierà assumendo automaticamente l'UID dell'utente proprietario che di solito è root, che è comunque l'unico utente in grado di impostare questo bit su un file.

Per completezza diremo che esiste anche il bit 10  "set gid", che invece cambia il solo gruppo dell'utente ma è poco usato.
 
Se andiamo a vedere per esempio il programma sudo che permette di eseguire altri programmi come super user,  scopriamo che i suoi permessi sono :


ls -l /usr/bin/sudo
-rw
sr-xr-x 2 root root 75456 May 24 19:36 /usr/bin/sudo

e con somma sorpresa scopriamo che usa il suid bit che gli permette di diventare tranquillamente root.

Sarebbe bello poterlo fare con uno script, ma il sistema non funziona in generale con gli interpreti ma solo coi files direttamente eseguibili e questo ci fa capire qual'è il modo migliore per bypassare i controlli.

Grimaldello

Per capire bene come funziona e con quali limitazioni il suid,  scriviamo un piccolo grimaldello.


/* Grimaldello */

#include <stdio.h>
#include <unistd.h>


int main(int ac,char **av)
{
  if (ac<2) return 1;
  system(av[1]);
  return 0;
}


 

Quindi compiliamolo e mettiamo a posto i permessi da root :

gcc grimaldello.c -o grimaldello
sudo chown root:root grimaldello
sudo chmod 4755 grimaldello


Ora proviamo da dare :



./grimaldello whoami
root

Il fatto che il nostro grimaldello ci abbia risposto root, ci fa intuire la mostruosità che abbiamo appena creato, una vulnerabilità di altissimo livello, concedendo a chiunque di eseguire programmi come root, infatti con :



./grimaldello sh
#



otteniamo una stupenda Shell suidata.

Mentre con :


./grimaldello bash
bash-4.2$


Non otteniamo nulla ! Perché la bash come i programmi scritti con le GTK e molti altri, rifiuta questo meccanismo.

Se però inseriamo una semplice riga al nostro programma :



/* Grimaldello */

#include <stdio.h>
#include <unistd.h>


int main(int ac,char **av)
{
  if (ac<2) return 1;
  setuid(0);
  system(av[1]);
  return 0;
}


 
ecco che il grimaldello diventa più aggressivo.


/grimaldello bash
#


e lascio a voi il cercare di capire perché.

Bene, ora che avete capito come funziona grimaldello, cancellatelo.


Pumpkin

Con la stessa logica di grimaldello, possiamo creare un programma che invece potrebbe essere utile, a scopo didattico e non.

Spesso chi è abituato alla gestione della rete e delle cartelle condivise, tende a confondere il concetto di "gruppo di lavoro" inteso come gruppo di persone con il permesso condividere una certa cartella e il gruppo di lavoro dei permessi Posix.

Ciò non è linea di massima un errore ma un'enorme limitazione.

Infatti mentre nel primo caso si tratta di permesso di accesso ai dati, nel secondo si parla di permesso di accesso anche all'hardware della macchina e ai suoi canali di comunicazione, perché nel file system ci sono anche i devices e i files speciali che controllano tutto (tranne le socket e la gestione della rete) e si può proibire l'accesso a intere categorie di utenti e permettere ad altri di fare cose che altrimenti potrebbe fare solo root.

Per esempio sulla maggior parte dei sistemi se un utente limitato non appartiene al gruppo "video" non ha accesso alla telecamera e questo può essere interessante per limitare le funzionalità "invasive" di certi programmi di chat.

Pensate a programmi  closed source, programmi di file sharing che spesso girano per giorni indisturbati sulla macchine o programmi che se ne stanno in background, potrebbero presentare vulnerabilità più o meno volute, e accedere alle risorse della macchina indisturbati.

Anche senza voler essere paranoici, l'errore o l'idiozia la si trova ovunque e capita spesso di vedere sulle reti di condivisione, interi dischi condivisi, compresi documenti, foto, numeri di telefono password e mail.

Comunque, mediante questo sistema è possibile creare un utente che sulla mia macchina ho chiamato pumpkin (invece di sandbox), con permessi molto limitati.

Poi si può poi proteggere la propria home con chmod 750, precludendo l'accesso a tutti coloro che non sono nel vostro gruppo di lavoro (compreso pumpkin).

Diamo per scontato che è possibile con alcune interfacce grafiche, avviare un programma a nome di un altro utente, in questo caso è richiesta la password.

Per evitare la password si può modificare il file di configurazione di sudo , che è piuttosto complesso, perché di solito bisogna calibrare il comportamento su ogni programma o concedere l'accesso comune senza password.

Per testare i vari programmi o per lanciare programmi in background, si può usare un programma simile a grimaldello che ho chiamato pumpkin :


/* Pumpkin */

#include <stdio.h>
#include <unistd.h>


int main(int ac,char **av)
{
  if (ac<2) return 1;
  setuid(5000);
  setenv("USER","pumpkin");
  setenv("HOME","/home/pumpkin");
  execv(av[1],av+1);
  return 0;
}
 

Come vedete ho messo in hard coding sia lo user-id che ho fissato a 5000 che la HOME che la USER, così evito che vi possano essere problemi.

Il programma ha i seguenti permessi :


-rwsr-x---   1 root  user 7114 Jun 30 16:28 pumpkin

Quindi vediamo che è solo leggibile e eseguibile da user che sono io o siete voi ed è modificabile solo da root, che è il proprietario e ha il bit di suid.

Il programma è stato messo in /local/bin.

Con il comando :

pumpkin /usr/bin/<il programma di file sharing>


anche senza sudo, il programma di file sharing, partirà localmente ma come utente pumpkin, che lavora nella sua cartella riservata e con pochissimo accesso al disco, senza possibilità di fare danni, accedere al video eccetera.

E la grafica ?

Ovviamente se avete aperta una sessione X dal vostro utente user, è improbabile che il programma grafico,visualizzi qualcosa, per motivi di sicurezza.

Occorre lanciare un comando di apertura di X server, quello che dà permesso a tutti da chiunque è :

xhost +

fino a qualche anno fa scrivere questo comando era una oscenità ma oggi sulla maggior parte degli Xserver, l'accesso fuori da localhost non è ammesso se non su esplicita richiesta, se volete essere più restrittivi ci dovete lavorare un po`.

Quando va lanciato ?

Ma naturalmente dopo avere avviato l'XServer dalla vostra sessione grafica, io per esempio ho fatto uno script :


#!/bin/bash
/usr/bin/xhost +

e l'ho messo in un file :

~/.kde/Autostart/xhostplus
ovviamente eseguibile ;).

domenica 17 giugno 2012

Backup on Poweroff

Anni fa, tra le pagine di un vecchio blog, parlai di uno stupendo strumento per il backup chiamato rdiff-backup .

Oggi a distanza di anni e dopo una profonda evoluzione di interfacce e sistemi operativi, ritengo che uno dei migliori strumenti per il backup in circolazione sia rdiff-backup che tra l'altro fa da backend a molti famosi programmi in circolazione.

Cos'è e come funziona 

Rdiff-backup, è un programma scritto in Python per linea di comando, ovviamente multi-piattaforma, che unisce svariati concetti e tecnologie, con risultati decisamente interessanti.

Prima di tutto è un backup incrementale inverso, cioè tiene traccia diretta dell'ultima versione e un backup incrementale delle versioni precedenti di ogni singolo oggetto del file system : quindi non occorre inserire tutti i volumi a ritroso per arrivare al backup finale. Le precedenti versioni più vecchie possono poi essere rimosse automaticamente dopo un certo numero di giorni/mesi/anni.

Seconda caratteristica, è che tale struttura incrementale è implementata sulle differenze binarie, che lo rendono lento ma estremamente efficiente. Da tale caratteristica deriva anche il nome rdiff, visto che questo era il vecchio sistema di patch binaria (prima dell'arrivo degli xdelta, già da me citati in un precedente post ).

Terza cosa importante è che l'ultima versione dei files salvati, è direttamente accessibile nella cartella come semplice copia, cioè si dispone di copia fisica direttamente accessibile di questi dati e non sperduta in qualche intricato archivio.

Se ci aggiungete che integra rsync, consentendo i backup in remoto e che soprattutto il file system di destinazione è ininfluente cioè, potete ripristinare qualsiasi file, cartella, link o file speciale, con tanto di date e permessi, anche se il backup è su un volume ntfs o vfat , vi potete rendere facilmente conto di quanto il tutto sia conveniente.

Per quanto riguarda le critiche che si possono fare a rdiff-backup vi è sicuramente la complessità della riga di comando che è piuttosto laboriosa e l'uso improprio che molti programmi ne fanno.

Infatti, nonostante il sistema rsync permetta un backup in tempi ragionevolmente rapidi, se per qualche motivo si interrompe un backup in corso, alla successiva ripartenza rdiff-backup esegue un complesso rollback che può allungare senza preavviso il backup di alcune ore, con la conseguenza che poi l'utente si arrabbia e tende ad interromperlo nuovamente.

È altresì altamente sconsigliato lavorare su un disco mentre si fa il backup, per una ovvia questione di consistenza tra copia salvata e copia attuale.

Il comando rdiff-backup

Come accennavo, rdiff-backup sebbene estremamente versatile, è sempre stato piuttosto ostico ed è questo il motivo per cui di solito è usato attraverso frontend grafici.

Vi sono decine di modi diversi con i quali si può ottenere esattamente quello che si vuole (sempre ammesso che lo si sappia).

Io di solito lo uso così :

/usr/bin/rdiff-backup --force --include-globbing-filelist <filelist> <backup-dir> <backup-dest>

dove <backup-dir>, è la cartella sulla quale di solito eseguo il backup.

Salvo soltanto /home perché uso degli stratagemmi per fare in modo che tutto risieda su home e che stia per altro in una partizione separata, ma riguarda strettamente la mia visione di Linux per desktop e sui server ovviamente c'è ben altro da memorizzare.

La <filelist> è la lista delle eccezioni che di fatto è semplice elenco dove si possono escludere ed includere cartelle, per esempio usando questa semplice lista  :

- /home/user/.mozilla/firefox/Profiles/euuiqw19823.default/Cache
- /home/user/.cache
- /home/user/.thumbnails
- /home/user/.adobe
- /home/user/.googleearth

che è interamente esclusiva (segno -), si escludono dalla home dell'utente, alcune cartelle con le cache che sono di solito migliaia di files inutili.

Non mettendo il segno meno, la cartella o la sottocartella si re-include nella lista. Quindi immaginiamo di non volere salvare la cartella chiamata useless tranne la sotto-cartella useful, possiamo scrivere :

- /home/user/useless
/home/user/useless/useful

Sono ammesse anche alcune espressioni regolari.
 
In questo modo avrete capito che potete benissimo gestire, anche la cartella / cioè tutto il disco, prima escludendo tutto e poi includendo solo le cartelle interessanti, qui trovate una completa descrizione dei comandi e i relativi esempi.

Infine <backup-dest> è la cartella locale o remota che ospita il backup, se è un disco USB sarà automaticamente montato o da montare manualmente, in qualche parte in una sotto-cartella di /media o /mnt .

Backoff

Nei server, il backup è generalmente eseguito durante le ore di basso utilizzo (se ve ne sono), per i server aziendali le procedure partono di solito a notte fonda mediante schedulazione temporale (cron).

Per un desktop, il momento ideale per eseguire un backup è quando si smette di lavorarci, istante che nel mondo Windows da qualche anno è chiamato "il magico momento delle patch".

Poiché come tanti, per tenere una copia dei dati, uso un disco esterno USB che lascio normalmente staccato dalla rete elettrica e dal computer, ho cercato di pensare ad un sistema automatico che rilevasse la presenza di questo disco allo spegnimento della macchina Linux e nel caso facesse in automatico il backup prima di spegnerla.

Quindi non so se è il termine più appropriato ma backoff è quello che mi è venuto in mente associando backup a poweroff.

Spegnimento 

Vediamo innanzi tutto, come modificare la procedura di shutdown.

Poiché è palese per coloro che gestiscono i server usare un apposito comando, occupiamoci di coloro che usano un desktop e cliccano su "spegni" e qui ovviamente la situazione cambia da interfaccia ad interfaccia, da sistema a sistema.

I comandi come quelli di spegnimento della macchina, non sono gestiti direttamente nello spazio utente, perché gli utenti normali non potrebbero spegnere la macchina, quindi di solito ci pensano i login manager grafici come kdm e gdm3.

Con KDE la cosa è estremamente semplice, perché immaginando di avere il comando backoff un /usr/local/sbin, possiamo aprire il System Settings, e accedere a Login Screen che è appunto il gestore di kdm :


come possiamo vedere è stato inserito nel campo Halt il comando /usr/local/sbin/backoff, che sarà eseguito come root ; ovviamente per evitare un buco di sicurezza notevole, per fare questa modifica è richiesta la password di super user (poi ovviamente anche le cartelle e il file del programma devono essere scrivibili solo da root altrimenti siamo da capo).

Il fatto che questo comando sia eseguito da un UID 0, ci dà numerosi vantaggi, in quanto il backup potrà avvenire anche su cartelle che all'utente normale sarebbero inaccessibili (attenzione che comunque finiscono in un backup leggibilissimo).

Se non usate KDE le cose sono più complesse per due motivi : primo perché non potete lanciare lo script da root senza eseguire il sudo, secondo perché è complesso a seconda dell'ambiente, trovare il modo di cambiare lo script di shutdown.

Il mio consiglio in questo caso è di creare un apposito comando tipo "backup" da mettere nei menu.

Giusto per dare una indicazione potete scrivere qualcosa tipo questo :

#!/bin/bash

function looping
{
while true
do
        echo "message:WARNING BACKUP IN PROGRESS"
        /bin/sleep 10
done
}

/usr/local/sbin/backoff &
(looping &) | /usr/bin/zenity --notification --listen
e lanciarlo con gksu.


Verifica del collegamento

La seconda fase è verificare che un particolare disco, sia connesso alla nostra macchina.

Questo disco come spiegato non deve avere requisiti particolari, io uso tranquillamente un pre-formattato ntfs da 1Tbyte. L'unica accortezza è creare una cartella che ho chiamato BACKUP, dove finirà il backup, giusto per poter poi usare il disco anche per altro, senza disturbare la procedura incrementale.

Questo si può fare grazie agli UUID , quindi occorre prima di tutto individuare quale è l'UUID del disco di backup eseguendo prima e dopo avere attaccato il disco  :

ls -l /dev/disk/by-uuid/

e verificare qual'è l'UUID del nuovo arrivato.

Poi nello script, controlleremo la sua "esistenza".

Lo Script

Lo script è un tipico programma da mettere in sbin, con dati in etc , per esempio /usr/local/sbin.

In questo caso, dobbiamo creare in /usr/local/etc (quindi da root) la cartella backoff e metterci i seguenti files :

  • /usr/local/etc/backoff/backup.lst , contenente la <filelist>.
  • /usr/local/etc/backoff/diskid , da echo "il diskid di prima" >/usr ...

Poi possiamo copiare il seguente script in /usr/local/sbin/backoff :


#!/bin/bash
DATAFOLDER=${0%%/sbin/*}/etc/backoff
DISKID=$(<$DATAFOLDER/diskid)
if [ -e /dev/disk/by-uuid/$DISKID ]
then
  TMPDIR=`/bin/mktemp -d -p /mnt`
  /bin/umount /dev/disk/by-uuid/$DISKID 2>/dev/null
  /bin/mount /dev/disk/by-uuid/$DISKID $TMPDIR
  /usr/bin/rdiff-backup --force --exclude-other-filesystems --include-globbing-filelist $DATAFOLDER/backup.lst /home $TMPDIR/BACKUP
  /bin/sync
  /bin/umount $TMPDIR
  /bin/rmdir $TMPDIR
fi
/sbin/shutdown -h -P now


Lanciando backoff, si analizzerà la presenza del disco, se quel particolare disco di backup non è connesso avverrà un semplice shutdown -h -P .

Se il disco è connesso invece, viene montato/rimontato correttamente su una cartella temporanea ed è eseguito il backup della cartella home con le modalità già viste, poi il disco si sincronizza, la cartella è smontata e rimossa e solo allora si procede allo shutdown definitivo della macchina.

Attenzione, che l'opzione "--exclude-other-filesystems" serve ad evitare che ogni file system eventualmente montato in /home o comunque nella cartella da salvare, sia incluso. Al di là del fatto che nel nostro caso la cartella temporanea è creata in /mnt, ciò evita tra l'altro il pericolo di tentare di salvare lo stesso volume di backup nel qual caso il sistema andrebbe in loop con nefaste conseguenze.

Se si mette come script di shutdown,  spegnendo il sistema con quel particolare disco staccato, si procederà normalmente mentre spegnendolo con quel disco attaccato, si potrà andare tranquillamente a dormire e lasciare che il sistema faccia il resto.

Restore

Giusto per accennarvi come funziona il restore di rdiff-backup, di cui potete trovare lunghe spiegazioni in altra sede, una volta che avete ripristinato il sistema primario, per ripristinare l'intero disco col comando che abbiamo dato (cioè salvando la /home direttamente in /BACKUP), basta scrivere :
rdiff-backup -r now <mount-point>/BACKUP /home
dove mount-point, è il punto dove montate il disco, e il sistema si ripristina all'ultima copia.

Se vi interessa invece un singolo file o una singola cartella, potete dare :
rdiff-backup -r now <mount-point>/BACKUP/<path> <new-path>
dove path è il percorso dalla home e new-path è la cartella dove il contenuto della cartella path sarà espanso.

Per un file specifico occorre indicare il nome del file sia in path che in new-path.

Ma vediamo un esempio con risvolti ancora più interessanti.

Immaginiamo per esempio di volere recuperare un documento mydoc.odt di tre mesi fa che avevamo cancellato, e che il documento fosse  /home/user/Documents, possiamo dare questo comando :
rdiff-backup -r 90D <mount-point>/BACKUP/user/Documents/mydoc.odt myolddocument.odt
dove 90D sta proprio per 90 giorni fa. Il documento è salvato nella cartella corrente col nuovo nome cioè myolddocument.odt.

Con un comando tipo :
rdiff-backup -r 2012-2-21 <mount-point>/BACKUP/user/Documents ./oldDocumentsFolder
possiamo estrarre l'intera cartella Documenti risalente a una data (prossima per difetto) al 21 febbraio 2012 e metterla in un nuovo folder per esempio per fare un confronto.

Per sapere quanti backup sono stati fatti di tale cartella, possiamo scrivere :
rdiff-backup -l <mount-point>/BACKUP/user/Documents
E ancora ... tutti gli ultimi documenti sono immediatamente raggiungibili come semplici files, nella cartella <mount-point>/BACKUP/user/Documents che è il famoso mirror fisico.

Che volete di più ?


martedì 12 giugno 2012

Akonadi e Nepomuk, il lato oscuro di KDE

Tendenzialmente non sono inutilmente critico su certe scelte degli ideatori e dei programmatori delle interfacce grafiche in circolazione.

Una caratteristica di quasi tutti i fondamentalisti, dall'ambito politico all'ambito tecnologico è che : tutti hanno idee molto precise e non sono mai le loro.

Personalmente ritengo più importante avere dubbi, e tornando all'argomento del post, ritengo che vincolare un semplice desktop con la dipendenza forzata da due diversi DB relazionali, per altro commerciali e rilasciati solo in parte in GPL, sia assolutamente inaccettabile.

Per quanto poi riguarda l'utilizzo sempre più "forzato" degli strumenti in oggetto, dopo che vi avrò spiegato a cosa servono, potrete comunque trarne le vostre adeguate conclusioni. 

NEPOMUK e le informazioni distribuite

Dopo le antiche glorie e dopo l'acquisto di Suse da parte di Novell, KDE ossia la piattaforma più diffusa a quei tempi nell'ambito desktop Linux,  è stata trasformata in una cavia, per effettuare i più atroci esperimenti.

Comprendo che le QT prima di Trolltech e ora della Nnnnn .... della Nnnnn... ... scusate non riesco a dirlo, sono profondamente mutate nel tempo e sono diventate una piattaforma assolutamente completa (in primis gestione grafica e multimediale).

Purtroppo l'evoluzione invece di portare ad una infrastruttura semplice, arricchita di elementi opzionali, ha preso subito la strada di una serie di dipendenze improponibili, del tutto integrate e obbligatorie, alla faccia della modularità di Linux e perché no ... anche degli standard.

Tutto ciò ha portato ad una migrazione dei programmatori della piattaforma originale, verso non si sa bene quali progetti, e a guerre intestine di varia natura.

La chiave della nuova filosofia KDE è quella legata al progetto Nepomuk, finanziato perfino dalla comunità europea e che ha subito un forte rallentamento e vari cambiamenti di direzione, quando i finanziamenti sono finiti nel 2008.

Analisi ontologiche

Nepomuk, è uno strumento in grado di eseguire una analisi ontologica dei singoli dati, allo scopo di delinearne profili di ricerca e di lavoro distribuiti.

Capisco che la cosa detta così possa sembrare difficile, talmente difficile che se chiedete lumi a kde vi risponde che loro lo sanno ma non ve lo possono spiegare.

Quindi vi fanno degli esempi che via via diventano più lugubri e sinistri, compreso quello del tizio che invia un contratto di lavoro ad un collega, e che per il solo fatto di riferirsi ad una una ragazza che è stata taggata in una foto privata e presente sul computer come "noiosa a letto", il nome e il tag relativo sono automaticamente inseriti nel contratto, compresa la copia destinata a questa persona e vi dicono anche che  faranno comunque di tutto per evitarlo (non si sa se agendo sul software o sul soggetto in questione).

Ok, per il popolo che passa l'intera vita a rincoglionirsi su Facebook, questi sono eventi all'ordine del giorno e questo giustifica almeno in parte la descrizione di Nepomuk, come qualcosa in grado di organizzare la nostra vita e le nostre attività meglio di come facciamo noi.

A chi si interessa di Intelligenza Artificiale e quindi di filosofia, posso spiegare brevemente che l'analisi ontologica è la ricerca dell'essere o meglio dell'essenza delle cose.

Il cervello funziona per associazioni di idee, quindi individuato un oggetto, lo analizza in modo da farsi una "idea" di che cosa è, tipo : "ha quattro gambe un pianale e una spalliera, mi ci siedo sopra e allora è probabilmente una ....".

In questo modo un qualsiasi documento a seconda della sua natura, dal testo ad un brano mp3, ad una fotografia, può essere analizzato in base ad una ontologia specifica per esempio : il luogo, la data, i soggetti inquadrati, chi ve l'ha mandata, le parole espresse nel soggetto del commento.

Una volta intersecati i dati in modo opportuno si ricostruisce il carattere di una "attività" specifica, le persone coinvolte, e la tipologia dei dati che si stanno cercando.

Se questi dati, invece di starsene su un singolo computer si diffondono all'interno di una LAN aziendale, il lavoro si distribuisce socialmente e se si viene destinati ad una attività per la quale i vostri colleghi usano particolari software o contattano particolari persone, per esempio il sistema potrebbe riordinare il menù o l'agenda di conseguenza.

Per chi ancora non avesse afferrato il punto, questi sono proprio i meccanismi intrinseci nei Social Network moderni e nei servizi online, come quelli di Facebook e Google.

Soprano, Virtuoso e Maria (DB)

Fose non tutti sanno che dopo l'annessione in Oracle di MySQL, hanno fatto partire un fork, chiamato MariaDB.

Cosa c'entri con Nepomuk, non lo so bene, però visto che MySQL è un requirements per Akonadi, che è uno dei tentacoli di Nepomuk, mentre Soprano e Virtuoso sono rispettivamente il sistema di accesso semantico e il database relazionale ad oggetti di Nepomuk, mi sembrava che tutto contribuisse quanto meno a dare un senso alle cose, anche se limitato alla lirica.

Ovviamente Virtuoso è un server commerciale di cui esiste una versione Open Source, che è quella che dovrebbe essere presente sul vostro computer (come per MySql).

L'interfaccia originale di Nepomuk e i relativi daemon, come progetto della Comunità Europea erano scritti in Java, con il risultato di un bel 100% fisso di CPU.

Oggi con le nuove interfacce il consumo è inferiore. Il daemon di indicizzazione, si chiama strigi e anche se vi sembrerà strano prima di KDE4 in versione sperimentale, funzionava benissimo anche senza Nepomuk e virutosismi vari ma ovviamente non era semantico né social.

Fate conto che quando parte tutta la baracca il compuer tende a "sedersi" un po` esattamente come quando parte l'indicizzatore, di Gnome che si chiama Tracker.

Come abbattere Nepomuk

Quale scopo, raccontarvi le meraviglie di Nepomuk, senza poi spiegarvi come farne a meno ?

Mi perdonerete se non ho saputo spiegarne gli utilizzi attuali, perché sinceramente non ne ho trovati molti e quelli che ci sono mi fanno ribrezzo (specie dopo le esperienze con oggettini simpatici tipo Google Desktop) .

Togliere Nepomuk, dal mio punto di vista è consigliabile ma visto che non si può, prima di tutto abbattiamo il server editando il file :

 ~/.kde/share/config/nepomukserverrc
e dopo avere fatto copia dell'esistente (se c'è ) scrivetevi semplicemente questo :

[Basic Settings]
Start Nepomuk=false

Se il file non ci fosse, questa operazione è comunque utile per evitare che il sistema vi ossessioni alla partenza con insulsi messaggi, sulla non partenza di Nepomuk.

Poi disabilitate il server Virtuoso : su distribuzioni come Debian potete anche rimouvere il pacchetto virtuoso-minimal che non dovrebbe comportare dipendenze, anzi sulla Testing  allo stato attuale non è nemmeno presente.

 

Akonadi

C'è un articolo poco prolisso su Akonadi ed è italiano, leggendolo si incontrano diversi dubbi, anche perché quanto scritto è abbastanza fuorviante.

Alla domanda : "Dove sono i miei dati ?", invece di rispondere "nella vostra home" come sarebbe logico, vi rimanda al blog di Andres Matias e questo mi è sembrato curioso.

Diciamo che Akonadi è in pratica il braccio armato di Nepomuk, e si occupa di fornire a questo demone, anime fresche da macinare ma fa anche tante cose più interessanti e innocenti.

Andres Matias, dice che :

To make it clear from the beginning: the Akonadi database is NOT your MAIN data storage. Even if it gets destroyed, removed, your data is still safe.

Ora che abbiamo chiarito il punto fondamentale, cerchiamo di capire allora a cosa serve, visto che non memorizza nulla e per fare questo usa pure MySQL.

Beh ecco ... Akonadi è una semplice interfaccia alla base dati. Tecnicamente si pensi a una classica agenda (che qui è Kontact), il calendario oppure allo stesso client di mail che tiene gli indici delle mbox eccetera : di solito queste informazioni sono memorizzate in file più o meno standard come i vcf se vi va bene.

Per esempio Thunderbird utilizza i suoi files di indicizzazione e ancora oggi l'agenda è scritta nel terrificante formato Mork , distruggendo l'equilibrio mentale di intere generazioni programmatori,  volti ad accedere a tali dati, indipendentemente dalle intricate librerie di sviluppo.

Per fortunal lighting usa SQLite, ma non gestisce l'agenda, solo il calendario.

Nell'ambito Gnome, tuto è memorizzato in files "standard" come i vcf.

In teoria anche KDE usa questa infrastruttura, ma quando poi tenta di far dialogare i vari programmi, come il client di posta che deve richiedere un indirizzo email dall'agenda, non obbliga per questo l'agenda ad essere integrata strettamente con la mail ma semplicemente lo chiede all'interfaccia Akonadi che poi accede alla propria base dati.

Il giudizio generale che si può dare su un simile atteggiamento è positivo ed è sicuramente un alto esempio di ingegnerizzazione, usare MySQL invece, a mio parere è quanto meno inappropriato per non dire ingiustificabile.

In realtà la giustificazione addotta è che sitemi client/server come MySQL o Postgresql sono gli unici a garantire un accesso concorrente corretto.

Il problema è che ci sono grandi cambiamenti in pentola e potrebbero ulteriormente peggiorare le cose.

Come farne a meno

Fare a meno di Akonadi è piuttosto difficile visto che è integrato con tutto, persino con widget dell'orologio calendario di sistema, che lo usa per memorizzare le feste.

In mezzo a tutti questi dati, già fin d'ora si infilano i meta-tag di nepomuk oltre che le informazioni di contorno, cosucce tipo il fatto che una mail sia stata letta, forwardata o meno.

Personalmente dopo anni in cui è stato il mio unico programma di posta, io ho abbandonato KMail, perché la mail per me è abbastanza importante e non posso lasciarla in mano a gente che cambia idea ogni quarto d'ora.

Comunque in ogni caso, giusto per non rendere completamente inutilizzabile tutto il resto del desktop, potete invece provare ciò che è sconsigliato, cioè usare SQlite che ora pare funzioni un po` meglio sulla gestione della concorrenza.

Personalmente, su Debian  non avendo altri motivi per tenermi MySql sul desktop, ho rimosso l'attuale versione di  mysql-server-core.

Questo mi ha disinstallato automaticamente akonadi-backend-mysql e installato akonadi-backend-sqlite non so cosa accade sulle altre distribuzioni e comunque i backend li potete togliere e mettere a mano.

La modifica da fare alla configurazione di Akonadi, andrebbe fatta in fase di installazione, perché altrimenti perderete il DB attuale, comunque è editare il file di configurazione :

~/.config/akonadi/akonadiserverrc

e metterci solo :

[%General]
Driver=QSQLITE

[Debug]
Tracer=null
il resto si completerà da se e il plugin inserirà il database nella vostra home come dovrebbe essere e non in var/lib.

Il "peso" di Akonadi è assolutamente irrilevante e anzi con SqLite è molto performante.

Spero

di esservi stato utile e di avere espresso giudizi coerenti, sennò pazienza, in fondo sono solo un obsoleto programmatore e ho le mie personali idee.

A parte i motori di indicizzazione che sono sempre molto utili e magari lo sarebbero di più se non indicizzassero mentre sto lavorando ad un progetto urgente (giusto per dare un consiglio), ritengo che tutto il resto sia un attimino sopra le righe, specie nell'epoca dei tablet, touch, pad, mobile ...  dove a volte per sconforto ci si rifugia tra le certezze di una cliccante tastiera di un vecchio e caro desktop.



giovedì 7 giugno 2012

Partizionare il disco

Dopo i recenti accadimenti e cambiamenti di umore da parte dei BIG delle distribuzioni Linux, con conseguenze di cui in futuro forse parleremo, ho deciso di partizionare correttamente il disco e quando dico correttamente, intendo in modo da dare un taglio netto alla infame connivenza tra dati e programmi che li usano.

Come è noto o forse anche no, Linux è un sistema piuttosto semplice da gestire, visto che tutto è sotto forma di entries nel file system, e queste entries sono completamente visibili all'utente, cioè sono proprio lì dove le vediamo e sono solo quelle,  concetto che non è invece altrettanto chiaro su sistemi diversi come Windows.

Così se in Windows il miglior modo per salvarsi i dati, è farsi un bella disk image e relative aberrazioni ( tipo disk image incrementale a blocchi ), in Linux si va di tape archiver cioè di tar e si fa tutto perfettamente e anche di questo probabilmente parleremo in futuro.

Il risultato è che dopo una installazione corretta di Linux, abbiamo la classica struttura logica e che può variare leggermente da distribuzione a distribuzione :



Se sapete come funziona, riconoscete sicuramente le magiche cartelle bin, sbin, etc e lib dove finiscono tutti i programmi standard.

Di solito al primo livello sotto la / (detta root)  ci sono i programmi necessari a far partire il sistema e ottenere qualcosa di funzionante, molti devices embedded si fermano lì. Nella usr ci sono i programmi distribuiti con la distribuzione e nella local, ci sono quelli compilati dagli utenti, prefisso adottano di default se non indicato diversamente.

Poi ci sono quelle rosse che possono essere create ed usate come area dati, dinamici come quelli nella var, o statici come quelli nella share che tipicamente si ripete nella local dove va la documentazione e i files ausiliari. Insieme a queste ci sono altre cartelle come la boot dove va il kernel e altre informazioni di startup.

Le cartelle in nero sono le "unbackupable", cioè quelle che o sono create dinamicamente dal sistema o contengono il mount delle partizioni. Ci ho messo anche la tmp per la sua irrilevanza.

Le cartelle che invece ho indicato blu sono quelle riservate agli utenti e considerando che l'utente root di solito è solo per manutenzione, ciò che interessa finisce tutto in home dove ci sono le cartelle coi nomi degli utenti.

Questa è la cartella che ci interessa e che vedremo di completare.

Partizionare

C'è una notevole differenza tra partizionare un disco vuoto e partizionare un disco già pieno.

Poiché la maggior parte dei computer domestici ospita sistemi operativi già preinstallati regolarmente pagati, inutilizzati e sempre più invadenti, a meno di scelte radicali opterete per la seconda opportunità. 
 
In questo caso, o installate una distribuzione come Ubuntu che abbia un buon sistema di partizionamento o prendete uno strumento di partizionamento esterno, ce ne sono tanti e bellissimi che non richiedono installazione.

Se l'altro sistema operativo è Windows 7, il partition manager lo avete già, ovviamente non vi installa Linux però permette di gestire il disco e i vari blocchi mentre il sistema operativo è in funzione (e vi garantisco che non è cosa facile).

Il guaio è che per un retaggio del passato, le partizioni definite primarie sono solo 4 e ormai e almeno due sono già occupate, quella di sistema e quella di recupero.

Tuttavia con il GRand Unified Bootloader, potete lanciare Linux anche da una partizione logica, il mio suggerimento è quindi di creare uno spazio per metterci Linux e quindi suddividerlo nelle TRE partizioni logiche :

  1. Uno spazio per il sistema vero e proprio, formattato in ext4 o simile e con mount point / . Tipicamente una installazione Linux richiede un disco da 8/10 Gb, se avete un disco grande usatene 20 che vi mettete al riparo per il futuro. 
  2. Uno spazio per lo SWAP, che sarà automaticamente classificato e formattato come tale. Per la dimensione dello SWAP consiglio sempre 2 * RAM o poco più, quindi su un computer con 4 GB di memoria 8192 Mbytes vanno bene.
  3. Il resto lo formatterete ext4 e lo userete per una home a parte.

Una casa a parte

Con Linux, a differenza di quanto avviene con altri sistemi, tutto ciò che è scritto e aggiunto dall'utente, finisce nella sua cartella utente in home, in files di varia natura di cui l'utente stesso è proprietario.

Quando dico tutto, intendo proprio tutto, compresi i files di configurazione nascosti del desktop e simili e con il sistema dei permessi del File System non potrebbe essere diversamente, quindi sembrerebbe tutto molto semplice.

Purtroppo se i dati sono gestiti da servizi centralizzati di sistema, come Database e/o Web Server  i dati non finiscono nella cartella utente ma nelle cartelle riservate a questi servizi che di solito sono in /var .
  
Comunque la prima cosa da considerare, se si vogliono separare i dati dal sistema, è di mantenere la home su una partizione a parte : poi sarà sufficiente eseguire il mount sul folder home vuoto, inserendolo in fstab e ritrovarsi tutta le cartelle utenti.

Benchè molte distribuzioni usino gparted che consente di indicare come montare le partizioni e dove, è utile capire come è fatto fstab.

Le nuove versioni di Linux utilizzano un disk-id, quindi volendo fare una cosa coerente bisogna innanzitutto diventare root con su o come piace fare a me con sudo bash, poi dare :


ls -la /dev/disk/by-uuid

e trovare così l'elenco delle associazioni tra UUID e partizioni e quindi aggiungere in /etc/fstab la riga :

UUID=<sequenza incredibile di numeri e trattini>    /home      ext4    noatime,errors=remount-ro    0    2

Se ovviamente avete un volume che non è ext4, metteteci il vostro file system preferito, ovviamente evitate file systems che non salvino correttamente i permessi , come fat ed ntfs.

Una interessante opzione che molti dimenticano è noatime, è utile metterla perché pensate che Linux, come retaggio dalla struttura del sistema Unix, non solo tiene traccia della data di ultima scrittura di un file ma anche dell'ultima lettura, quindi con atime inserito cercherà continuamente di aggiornare il file system anche se non stiamo scrivendo e ciò non è cosa buona, nè per noi nè per il disco.

E poi ?

E qui si fermano di solito gli altri blog, quando vi consigliano di partizionare in quel modo ma questo è Finestrella e non può certo lasciarvi così.

Infatti in questo modo non salvate per esempio quanto contenuto in /opt, in /var e in /usr/local.

Se volete reinstallare perderete quindi di colpo, tutti i dati dei servizi che dicevamo prima che stanno in /var con tutti i log, oltre a tutti i programmi che avete messo in /opt e tutte le cose che avrete con fatica recuperato e compilato e saranno finite in /usr/local.

Attenzione perché spesso quando si fanno i backup, ci si limita a copiare la propria home, anche perché di solito i backup si fanno con l'utente "normale" che potrebbe non avere accesso completo a certi files di queste cartelle. Così una volta ripristinato il sistema si saranno persi una buona parte dei programmi.

Come fare ?

Vi posso dire cosa faccio io : creo una cartella System, con la prima lettera maiuscola. Siccome gli utenti hanno home con il proprio nome che è minuscolo sono abbastanza tranquillo (anche perché di solito il mio sistema ha solo un utente che sono io e non mi chiamo System).

Divento quindi root e poi lancio cinque semplici comandi :

mkdir /home/System
mv /opt /home/System
mv /usr/local /home/System/usr.local
ln -s /home/System/usr.local /usr/local
ln -s /home/System/opt /opt

cioè uso dei semplici link simbolici.

Per quanto riguarda la var , la questione è più complicata, di solito della var si tende a conservare la lib, dove i database adorano mettere i propri dati ed eventualmente la log per salvare i log di sistema.
Nella var però risiedono sia files completamente inutili come quelle delle varie cache, sia il sistema di gestione dei pacchetti che non può essere sovrascritto cosi`impunemente da quelli della precedente installazione.

Se non usate i database, o il web server e se state installando un semplice laptop o desktop, di solito conviene lasciare perdere, se invece volete salvare i log e i dati di un database vi consiglio di usare gli strumenti classici che vi offre il sistema.

Ripristino 

Quando si reinstalla si può procedere con semplici rm e ln ricostruendo i link, non vi scrivo qui come fare perché se non siete in grado di farlo è meglio non rischiare di inserire comandi a caso ma spero che in linea di massima l'abbiate capito.

Altro da dichiarare ?

Si. In realtà c'è altro.

Questo altro sono le modifiche che facciamo al sistema in tutte le altre cartelle.
In questo caso non è che possiamo fare i link per esempio sulla etc, per evitare disastri di dimensioni bibliche.

Ricordate che ogni sistema deve partire con le proprie configurazioni anche perché ad ogni aggiornamento i files di configurazione tendono a cambiare.

Capita però per alcune esigenze che ci capiti di fare qualche cambiamento virtuoso, per esempio modificando il file rc.local che fa partire programmi allo startup, giochicchiando col resolv.conf , aggiustando a mano la grafica con un file xorg.conf o modificando occasionalmente link e simili.

Per ovviare a tali inconvenienti tengo nella famosa System di cui parlavo prima una semplice cartella chiamata main dove copio i files che mi interessano usando una semplice copia ... in che modo ?

Così :

cp -av --parent /<path completo del file o cartella> /home/System/main

il -a copia tutto con permessi e subfolder mentre il --parent ricostruisce l'intero path.

Il v qui serve a verificare che stiate copiando i files giusti.

Una volta reinstallato il sistema operativo si verifica di non fare pasticci, cioè che quello che si sta scrivendo effettivamente già non esiste o non è cambiato rispetto al default e poi si esegue :

cp -av /home/System/main/* /

e il gioco è fatto.

Il v a questo punto invece può servire a visualizzare i danni che avete fatto ma se il sistema è nuovo si può sempre rimediare.

Ovviamente evitate di copiare nella /home/System qualcosa che punti alla partizione home, perché sarebbe inutile e soprattutto irrimediabile.


Time Archive

Se siete abituati a sviluppare software, conoscerete sicuramente i vari strumenti di controllo della versione, RVS, CVS, SVN eccetera.

Un sistema di controllo della versione consente di lavorare in gruppo sullo stesso progetto, gestendo le versioni e mantenendo l'intero storico degli aggiornamenti.

Questi strumenti sono concepiti per programmatori e con scopi precisi, pertanto lavorano sulle modifiche ai sorgenti testuali e sono anche piuttosto difficili da gestire, visto che di solito si basano su strutture client/server, richiedono un setup eccetera.

Mi sono chiesto se è possibile implementare un sistema un po`più semplice che serva a scopi più generali.

Per esempio, se si mantiene ordinato il proprio lavoro, suddividendo i vari progetti in cartelle, aggiungendo documenti di varia natura, può essere interessante poter mantenere uno storico di ogni precedente situazione, gestire dei trunk o dei branch in modo intelligente e portabile.

Sia su MAC che nelle ultime versioni di Windows vi sono strumenti per recuperare vecchie versioni dello stesso documento e sono più che altro connesse al sistema di backup.

La mia idea però è più modesta, a me serve una specie di archiviatore, in grado di memorizzare in archivi standard, tutta la storia di una cartella, meglio se multi-piattaforma, in modo da poter trasferire facilmente l'intero storico copiandolo come un normale archivio, su una chiavetta o un disco.

Così ho scritto uno scriptino di bash che ho chiamato timerachive e che fa più o meno quello che ho detto.

Oltre che la bash, timearchive usa alcuni comandi tipici dei sistemi Unix like, oltre a tre componenti fondamentali, il tar, gzip e xdelta3.

Mentre dei primi due avrete probabilmente sentito parlare da qualche parte, xdelta3 è abbastanza sconosciuto ma in realtà è un moderno sistema di Patch binaria, ossia un programma in grado di eseguire la "delta encoding" cioè ricavare le differenze da due files binari A e B , e generare un file C, in modo che avendo B e C si possa riottenere A.

La caratteristica interessante di xdelta3 è quello di generare files in formato vcdiff che pur non essendo anch'esso molto noto, è uno standard descritto in rfc3284 .

Il comando timearchive 

Lo script timearchive  l'ho inserito in /usr/local/bin del mio sistema Linux , giusto perché è il posto più logico dove metterlo, così è a disposizione direttamente come ogni altro comando, lanciato da solo dà :

timearchive
Bad paramenter, please use U,T,R or X.

e quindi ci presenta 4 diverse modalità d'uso :
  1. Update
  2. Test
  3. Rollback
  4. eXtract
Vediamoli nel dettaglio e spieghiamo indicativamente cosa fanno.

Update

Immaginiamo di avere una cartella planning e di volerla archiviare con timearchive, possiamo lanciare il comando :

timearchive U planning.tar planning "Prima versione di test"

U è il comando, planning.tar, l'archivio da creare che è un tar appunto, planning è la cartella da memorizzare e poi segue una riga di testo per indicare il contenuto che ci può essere utile per fare i famosi branch o trunk. Con un tar tvf , vediamo il contenuto:

tar tvf planning.tar

-rw-r--r-- user/user    2020 2012-06-07 04:27 20120607042743.tar.gz
-rw-r--r-- user/user      23 2012-06-07 04:27 20120607042743.revision


Ebbene nel tar abbiamo due files, il primo è contenuto compresso che nel nostro caso è solo 2K (è una cartella molto piccola) e l'altra è la descrizione.

Entrambi i files sono registrati con quella strana sequenza di numeri, che in realtà è la data in formato ordinabile YYYYMMDDhhmmss e che è il nostro codice automatico di versione.

Interessante è aggiungere un piccolo file all'interno della cartella e rilanciare il comando identico :

timearchive U planning.tar planning "Aggiunto piccolo file"

tar tvf planning.tar
 
-rw-r--r-- user/user      23 2012-06-07 04:27 20120607042743.revision
-rw-r--r--
user/user      89 2012-06-07 04:32 20120607042743.vcdiff
-rw-r--r--
user/user    2193 2012-06-07 04:32 20120607043221.tar.gz
-rw-r--r--
user/user      22 2012-06-07 04:32 20120607043221.revision

In questo caso è partito xdelta3 che è stato applicato sulla versione decompressa (ma non scompattata) del file tar.gz e sul nuovo tar prodotto per l'occasione. Vediamo che il file che prima era tar.gz è divenuto vcdiff ed è diventato solo di 89 bytes, il vecchio tar.gz è stato rimosso ed è stato inserito al suo posto il nuovo contenuto.

Rimuovendo il file appena aggiunto ed eseguendo ancora lo stesso comando, eseguiamo lo stesso identico algoritmo dell'ultima volta e otteniamo :

timearchive U planning.tar planning "Tolto piccolo file"


tar tvf planning.tar

-rw-r--r-- user/user      23 2012-06-07 04:27 20120607042743.revision
-rw-r--r--
user/user      89 2012-06-07 04:32 20120607042743.vcdiff
-rw-r--r--
user/user      22 2012-06-07 04:32 20120607043221.revision
-rw-r--r--
user/user      58 2012-06-07 04:39 20120607043221.vcdiff
-rw-r--r--
user/user    2193 2012-06-07 04:39 20120607043911.tar.gz
-rw-r--r--
user/user      19 2012-06-07 04:39 20120607043911.revision

e così via.

Test

Il tar tvf è stato solo un sistema per farvi capire come funziona l'archiviazione e quanto pulito sia il risultato, tuttavia noi da quell'insieme di files inutili facciamo fatica a ricavarci qualcosa, per questo usiamo il semplicissimo comando di test che mette le cose sotto una luce completamente differente :

timearchive T planning.tar

20120607042743  Prima versione di test
20120607043221  Aggiunto piccolo file
20120607043911  Tolto piccolo file


Il codice della versione è quindi la data e in fianco la descrizione. Quel codice è comodo per il copia e incolla e lo useremo sia per eXtract che per Rollback.

eXtract

Vogliamo ricavare la versione a cui avevamo aggiunto quel famoso piccolo file, il comando di test ci dice che è la numero 20120607043221 , creiamo una cartella temporanea, giusto per non usare il . e quindi aggiungere i files alla planning corrente e diamo il comando :

timearchive X planning.tar temp 20120607043221

dove temp è ovviamente la cartella.

il risultato è che nella cartella temp, troveremo una cartella planning corredata anche del famoso piccolo file, nonostante l'avessimo cancellato, ma cosa è accaduto ?

Semplicemente è stato estratto il tar.gz , cioè 20120607043911.tar.gz e sono state applicate in sequenza tutte le patch fino ad arrivare a quella col codice corretto, risalendo quindi alla corretta versione. In questo l'unica patch era 20120607043221.vcdiff che ci ha riportato direttamente alla penultima versione, se fossimo stati alla decima versione e avessimo chiesto la seconda, sarebbero state applicate 8 patch.

In questo modo è possibile ripristinare qualsiasi documento intermedio.

Ovviamente l'archivio non è modificato durante l'estrazione, per farlo c'è Rollback.

Rollback

Rollback inizialmente non c'era e l'ho aggiunto in seguito perché in alcuni pacchetti avevo eseguito una serie di Update errati.

Siccome eXtract, non modifica in alcun modo l'archivio, per tornare indietro si può usare Rollback, quindi se vogliamo tornare alla versione col file aggiunto possiamo applicare allo stesso modo di eXtract, il comando :

timearchive R planning.tar 20120607043221 

Il risultato è un archivio così composto :

timearchive T planning.tar
 

20120607042743  Prima versione di test
20120607043221  Aggiunto piccolo file


In cui è scomparsa l'ultima versione.

Interessante è esaminarlo con tar tvf :

tar tvf planning.tar
-rw-r--r--
user/user      23 2012-06-07 04:27 20120607042743.revision
-rw-r--r--
user/user      89 2012-06-07 04:32 20120607042743.vcdiff
-rw-r--r--
user/user      22 2012-06-07 04:32 20120607043221.revision
-rw-r--r--
user/user    2174 2012-06-07 05:01 20120607043221.tar.gz

Il rollback lavora come l'extract cancellando di volta in volta i files e poi reinserisce il risultato patchato come ultimo update, sempre senza scompattare i tar ovviamente.

Lo script

Dopo avervi spiegato come funziona, e i comandi principali eccovi ovviamente l'intero script, se state usando un sistema tipo Posix,  inseritelo in un file di testo di nome timearchive, e rendetelo eseguibile, altrimenti inventatevi qualcosa.

Spero vi torni utile, divertitevi !
 
#!/bin/bash

function repatch
{
  fil1=`tempfile`
  fil2=`tempfile`
  fil3=`tempfile`
  while read l
  do
    t=${l#*.}
    if [ "$t" != "revision" ]
    then
      if [ "$t" == "tar.gz" ]
      then
        tar xf $1 $l -O | gzip -d > $fil1
      else
        tar xf $1 $l -O >$fil2
        xdelta3 -f -d -s $fil1 $fil2 $fil3
        cp $fil3 $fil1
      fi
      tr=${l%%.*}
      if [ "$tr" == "$3" ]
      then
         cd $2
         tar xfps $fil1
         break
      fi
    fi
  done
  rm $fil1
  rm $fil2
  rm $fil3
}

function rollback
{
  fil1=`tempfile`
  fil2=`tempfile`
  fil3=`tempfile`
  tmpdir=`mktemp -d`
  while read l
  do
    t=${l#*.}
    if [ "$t" != "revision" ]
    then
      if [ "$t" == "tar.gz" ]
      then
        tar xf $1 $l -O | gzip -d > $fil1
        tar --delete --file $1 $l
      else
        tar xf $1 $l -O >$fil2
        xdelta3 -f -d -s $fil1 $fil2 $fil3
        cp $fil3 $fil1
        tar --delete --file $1 $l
      fi
      tr=${l%%.*}
      if [ "$tr" == "$3" ]
      then
         cd $tmpdir
         gzip --best <$fil1 >$tr.tar.gz
         tar rf $1 $tr.tar.gz
         break
      fi
    else
      tar --delete --file $1 $l         
    fi
  done
  cd $2
  rm $tmpdir/*
  rmdir $tmpdir
  rm $fil1
  rm $fil2
  rm $fil3
}


function showcontent
{
  while read l
  do
    if [ ${l##*\.} != "revision" ]
    then
      echo -n ${l%%\.*}"  "
      tar xf $1 ${l%%\.*}.revision -O
    fi
  done
}


function intcontent
{
  while read l
  do
    if [ ${l##*\.} != "revision" ]
    then
      echo ${l%%\.*}
    fi
  done
}


case $1 in

U)
  dirfull=$3
  if [ "${dirfull:0:1}" != "/" ]
  then
    dirfull=`pwd`/$dirfull
  fi
  if [ ! -d  $dirfull ]
  then
    echo "$3 must be an existing directory"
    exit
  fi
  archfull=$2
  if [ "${archfull:0:1}" != "/" ]
  then
    archfull=`pwd`/$archfull
  fi

  if [ -e $archfull ]
  then
    last=`tar -tf $archfull | grep "\.tar.gz"`
    if [ -z "$last" ]
    then
      echo "The archive does not contain any tar.gz file"
      exit
    fi
    # Creates Working Directory
    tmpdir=`mktemp -d`
    # Get Current Date
    todate=`date +%Y%m%d%H%M%S`
    tar xf $archfull $last -O | gzip -d >$tmpdir/oldimage
    tar --delete --file $archfull $last
    # Create the new archive
    cd ${dirfull%/*}
    tar cfps $tmpdir/$todate.tar ${dirfull##*/}
    # Get Old DIFF name
    olddiff=${last%%.tar.gz}.vcdiff
    # Delta Analysis
    cd $tmpdir
    xdelta3 -S djw -s $todate.tar oldimage $olddiff
    tar rf $archfull $olddiff
    gzip --best $todate.tar
    tar rf $archfull $todate.tar.gz
    echo $4 >$tmpdir/$todate.revision
    tar -C $tmpdir -rf $archfull $todate.revision
    cd ..
    rm $tmpdir/*
    rmdir $tmpdir
  else
    # Creates Working Directory
    tmpdir=`mktemp -d`
    # Get Current Date
    todate=`date +%Y%m%d%H%M%S`
    cd ${dirfull%/*}
    tar cfps $tmpdir/$todate.tar ${dirfull##*/}
    cd $tmpdir
    gzip --best $todate.tar
    tar cf $archfull $todate.tar.gz
    echo $4 >$tmpdir/$todate.revision
    tar -C $tmpdir -rf $archfull $todate.revision
    cd ..
    rm $tmpdir/*
    rmdir $tmpdir
  fi

;;

X)
  dirfull=$3
  if [ "${dirfull:0:1}" != "/" ]
  then
    dirfull=`pwd`/$dirfull
  fi
  if [ ! -d  $dirfull ]
  then
    echo "$3 must be an existing directory"
    exit
  fi
  archfull=$2
  if [ "${archfull:0:1}" != "/" ]
  then
    archfull=`pwd`/$archfull
  fi
  if [ ! -e $archfull ]
  then
     echo "Archive not found"
     exit
  fi
  if [ -z "$4" ]
  then
    last=`tar tf $archfull | grep "\.tar.gz"`
    fil=`tempfile`
    tar xvf $archfull $last -O > $fil
    cd $dirfull
    tar xvzfps $fil
    rm $fil
  else
    testtar=`tar tf $archfull| intcontent | grep "^$4$" `
    if [ -z "$testtar" ]
    then
       echo "Record not found"
       exit
    fi
    tar tf $archfull | sort -r | repatch "$archfull" "$dirfull" $4
  fi
;;

R)
  archfull=$2
  dirfull=`pwd`
  if [ "${archfull:0:1}" != "/" ]
  then
    archfull=`pwd`/$archfull
  fi
  if [ ! -e $archfull ]
  then
     echo "Archive not found"
     exit
  fi
  if [ -z "$3" ]
  then
     echo "Missing rollback record"
     exit
  fi   
  testtar=`tar tf $archfull| intcontent | grep "^$3$" `
  if [ -z "$testtar" ]
  then
   echo "Record not found"
   exit
  fi
  tar tf $archfull | sort -r | rollback "$archfull" "$dirfull" $3
 
;;


T)
    tar tf $2 | sort | showcontent $2
;;

*)
  echo Bad paramenter, please use U,T,R or X.
;;
esac