<- PW: Intro C/C++ - Indice Generale - Copertina - PW: GTK2 -> |
PlutoWare
di Avi Alkalay, IBM Linux Impact Team
Traduzione di Germano Rizzo
© 2002, Avi Alkalay
L'articoloLinux sta diventando sempre più popolare, e sempre più produttori di software stanno convertendo i loro prodotti da altre piattaforme. Questo articolo prova a chiarificare alcuni punti oscuri, e dà qualche consiglio su come creare applicazioni Linux altamente integrate per quanto riguarda il sistema operativo, la sicurezza e la facilità d'uso. Gli esempi si applicano specificatamente a RedHat Linux, ma dovrebbero essere compatibili con altre distribuzioni basate su di essa (Conectiva, Turbolinux, Caldera, PLD, Mandrake, etc). |
Il concetto di user-friendly è spesso erroneamente associato ad una buona GUI (ossia Graphical User Interface, l'interfaccia grafica). Nei fatti, è molto più di questo. In sistemi come Linux (con caratteristiche più "da server"), l'utente giudica quanto è semplice un software principalmente nell'installazione e nella configurazione iniziale. Può dimenticarsi di quanto fosse facile installare ed usare un certo prodotto, ma non dimenticherà mai se un pacchetto aveva una configurazione ed un processo d'installazione particolarmente ostici. Una migrazione o una nuova installazione saranno allora un incubo, perciò l'utente li eviterà di sicuro, per il futuro.
Immaginate di dover installare quel costosissimo prodotto che la vostra compagnia ha comprato dalla ACME, quando vi rendete conto di dover compiere i seguenti passi:
Suona familiare? Chi non ha mai affrontato questa triste situazione, che induce l'utente a sicuri errori? Se la procedura d'installazione del vostro prodotto suona tipo "scompatta-copia-configura-configura un altro po'-usa", come in questo caso, avete un problema, e all'utente questo non piacerà.
Agli utenti piace avvertire che il Prodotto si integra bene con il sistema operativo. Non si dovrebbe richiedere che sia il sistema operativo a doversi adattare al Prodotto (modificare variabili d'ambiente, etc.). Si deve far sì che l'utente "Installi-e-Usi".
La perfezione dell'"Installa-e-Usa" può essere raggiunta facilmente seguendo una ricetta con tre soli ingredienti:
Vedremo assieme ora cosa sono questi ingredienti, e come implementarli.
L'insieme dei file di qualsiasi applicazione -- grafica, server-side, commerciale, open/free, monolitica, eccetera -- ha sempre quattro parti:
1: Il Software in sé -- il corpo
Gli eseguibili, le librerie, i file di dati, gli esempi, i manuali e la documentazione, eccetera. Gli utenti normali dovranno avere accesso in sola lettura a questi file. Essi devono essere modificati solo quando l'amministratore aggiorna questo software.
2: I file di configurazione -- l'anima
Questi sono i file che definiscono come il software funzionerà, come usare i contenuti, amministrare la sicurezza, ottimizzare le prestazioni, ecc. Senza di essi, il programma da solo è normalmente inutile.
A seconda del software, specifici utenti privilegiati potranno modificare questi file, per far sì che il software si comporti come vogliono.
E' importantissimo fornire documentazione sui file di configurazione.
3: I contenuti
Questo è ciò che riceverà tutta l'attenzione dell'utente. E' quello che l'utilizzatore ha delegato il vostro software ad amministrare. E' quello che farà gettar via il vostro prodotto dall'utente, e adottare quello della concorrenza, se conterrà difetti: le tabelle di un database, i documenti per un editor di testo, le immagini e le pagine HTML per un server web, le servlet e gli EJB di un Application Server, etc.
4: Log, dump, ecc.
I software di server usano questi file come log di accessi, registri, per scovare i problemi, come file temporanei, ecc. Anche altri tipi di software utilizzano questi file, ma è meno comune.
Proprio quest'ultima classe di file rappresenta il maggiore problema per l'amministratore di sistema, perché il loro volume può superare addirittura le capacità di immagazzinamento. Per questo fatto, è importante stabilire alcune metodologie per prevedere queste eventualità, mentre si è nella fase di progettazione.
Vediamo quanto universale è questo concetto analizzando alcuni tipi di software:
Tabella 1. Universalità delle Quattro Parti
Applicazione | Software in sè | Configurazione | Contenuti | Log, Dump, ecc. |
---|---|---|---|---|
Server Database | Binari, librerie, documentazione. | File che definiscono la directory dei file dati. Per questo tipo di software, i rimanenti file di configurazione normalmente risiederanno in speciali tabelle all'interno del database stesso. | File di tabella, file di indice, etc. Questi software di solito prevedono alberi interi di file dentro alla stessa directory. La loro locazione nel sistema sarà definita dalla configurazione. | Per i DB, ci sono i backup, generati giornalmente; inoltre, i log sono usati dall'amministratore per definire la strategia di indicizzazione. La loro locazione nel sistema sarà anche in questo caso definita dalla configurazione. |
Editor di testi | Lo stesso, più i modelli, i filtri per i file di diverso formato, ecc. | Essendo software orientato all'utente, la sua configurazione dovrà essere posta nella directory $HOME di ogni utente, e consisterà di file che definiscono i font e le tabulazioni standard, ecc. | I documenti vengono generati dall'utente, e andranno posti da qualche parte nella sua $HOME. | Si manifestano come file temporanei che possono essere anche parecchio grossi. l'utente potrà definire la loro locazione mediante una finestra di dialogo user-friendly (che salverà i risultati in un file di configurazione). |
Generatore di MP3 | Lo stesso, più i filtri per i formati audio. | Ogni utente avrà i suoi file di configurazione nella $HOME, e conterranno le preferenze sul bit rate, ecc. | Simile al Text Editor | Simile al Text Editor |
Server Web | Simile al Database | File che definiscono la directory con i contenuti, i parametri della rete e delle prestazioni, la sicurezza, ecc. | Le directory dove il webmaster deposita la sua creatività. Di nuovo, andranno definite nella configurazione. | I preziosissimi log di accesso, vitali ai fini del marketing, che saranno generati in una locazione ed un formato definiti dalla configurazione. |
Server di e-Mail | Simile al Database e Web-Server | File che definiscono come accedere al database dell'utente, le regole di routing delle mail, ecc. | Le preziose mailbox dell'utente. Di nuovo, saranno definite nella configurazione. | I log di trasferimento, di intercettazione dei virus, ecc. Ancora, definiti nella configurazione. |
Notate che la categoria "Software in sè" contiene tutta la business logic del prodotto, che potrebbe essere inutile se non si avrà una configurazione che definisce come lavorare con certi dati, definita dall'utente. Le configurazioni sono ciò che connette il tuo prodotto con l'utente.
Potremmo usare la metafora di uno Scultore (business logic), a cui viene fornito Bronzo (il contenuto) e un Tema o una Ispirazione (configurazione) da un Mecenate (utente), per produrre un'opera d'Arte (contenuto). Egli annota nel suo Diario (i log) le sue attività giornaliere, per riferirne al suo Mecenate (utente).
Ok, siamo più pratici. Il fatto è che, se usiamo correttamente il concetto delle parti universali, miglioreremo di molto la qualità del nostro prodotto. Lo faremo semplicemente separando, incapsulando ognuna di queste parti in differenti directory di sistema (avere semplicemente file differenti per ogni parte non è sufficiente). C'è uno standard detto FHS che definisce le directory di Linux appropriate ad ogni parte; lo discuteremo più avanti.
Ora, vediamo il valore di questa separazione per l'utente:
Vediamo ora un esercizio sulla separazione, usando come esempio un sistema chiamato "MySoftware", nel quale la business logic è in Esempio 1 e la configurazione in Esempio 2.
Esempio 1. Un programma di Shell che fa riferimento a un file di configurazione esterno.
#!/bin/sh
#########################################
##
## /usr/bin/MySoftware
##
## Business logic del sistema MyProgram.
## Non cambiare nulla in questo file. Tutte le configurazioni possono essere
## fatte in /etc/MySoftware.conf
##
## Non forniremo supporto per alcuna modifica fatta qui.
##
# File di configurazione predefinito. 1
CONF=/etc/MySoftware.conf
# Cartella con i contenuti minimi 2
MIN_CONTENT_PATH=/var/www:/var/MySoftware/www
if [ -r "$CONF"]; then
. "$CONF" 3
fi
# I contenuti di cui sarò server sono i "minimi" più quelli forniti
# dall'utente nel file di configurazione $CONF
CONTENT_PATH=$MIN_CONTENT_PATH:$CONF_CONTENT_PATH 4
NOTE:
1 Definizione del nome del file di configurazione.
2 Definizione di alcuni parametri statici.
3 La configurazione è letta da un file esterno, se esiste.
4 Dopo aver letto il file di configurazione, tutte le directory coi contenuti -- quelli forniti dall'utente più quelli forniti dal prodotto -- andranno a finire insieme nel $CONTENT_PATH che sarà usato d'ora in avanti.
Esempio 2. File che contiene solo le configurazioni di MySoftware
#######################################
## /etc/MySoftware.conf
##
## Parametri di configurazione per MySoftware.
## Cambia ciò che vuoi.
##
# Directory dei contenuti.
# Una lista di directory separate da ':' dove cercare i contenuti.
# Le directory /var/www e /var/MySofware sono già lì, perciò
# includi qui solo quelle speciali, se ce ne sono.
CONF_CONTENT_PATH=/var/NewInstance:/var/NewInstance2 *
# Il tuo indirizzo e-mail, per ev. notifiche.
EMAIL=john@mycompany.com *
# Directory dei log
LOG_DIR=/var/log/myInstance*
* Questi sono i parametri definiti dall'utente.
Quando ero amministratore di sistema per i servizi di Hosting e-business di IBM, ero affascinato dalla flessibilità di Apache nel permetterci di fare cose del genere:
bash# /usr/sbin/httpd &
bash# /usr/sbin/httpd -f /etc/httpd/dom1.com.br.conf &
bash# /usr/sbin/httpd -f /etc/httpd/dom2.com.br.conf &
bash# /usr/sbin/httpd -f /etc/httpd/dom3.com.br.conf &
Se non passiamo alcun parametro, come nel primo esempio, Apache carica il suo file di configurazione di default, codificato nel programma stesso per essere /etc/httpd/conf/httpd.conf. Ci siamo poi costruiti altre configurazioni, una per ciascun utente, con una struttura completamente differente, diversi indirizzi IP, moduli caricati, directory per i contenuti, password, domini, strategie di log, eccetera.
Questo stesso concetto è usato da un editor di testi su un sistema operativo multiutente (come Linux). Quando il codice viene caricato, cerca un file di configurazione nella $HOME dell'utente, e a seconda di chi l'ha invocato (utente A piuttosto che B), il suo aspetto sarà differente perché ogni utente ha la sua personale configurazione.
La conclusione ovvia è che il corpo del software (la logica di business) è puramente e completamente orientato dallo spirito (configurazione) del suo utilizzatore. Ma il vantaggio competitivo risiede in quanto facilmente possiamo passare da uno "spirito" ad un altro, come nell'esempio di Apache. E' molto utile fornire questa possibilità all'utente. Gli permetterai di creare uno spirito di intimità, fiducia e comfort con il tuo prodotto.
Abbiamo usato questo approccio con molti software diversi durante il mio periodo all'e-business Hosting, ed era estremamente utile per la manutenzione, etc. In una migrazione di versione potevamo avere controllo totale su dove fosse ognuna delle sue parti, e fare l'upgrade o il downgrade senza perdite di tempo, con ovvio successo.
C'erano però molti prodotti che si rifiutavano di funzionare in questo modo. Avevano così tanti parametri codificati nel codice che non riuscivamo a vedere cosa dividesse il corpo dallo spirito (o altre parti). Queste applicazioni erano marchiate come "ragazzacci", e scartate o rimpiazzate il più presto possibile.
Abbiamo concluso che i "bravi ragazzi" traevano giovamento dalla capacità di visione delle quattro parti da parte dei loro programmatori. E ci semplificavano la vita. Nei fatti, fu allora che formulammo questa teoria, che continua a dar prova di sè.
Preferisci installare ragazzacci o bravi ragazzi?
Finora, la nostra discussione è stata indipendente dal sistema operativo. In Linux, la teoria delle Quattro Parti è espressa nella sua struttura delle directory, che è classificata e documentata nel Filesystem Hierarchy Standard. Il FHS è parte dell'LSB (Linux Standard Base), il che è una buona cosa visto che tutta l'industria di Linux si sta muovendo verso di esso, e dovrebbe essere nella mente di tutte le distribuzioni. FHS definisce in che directory deve risiedere ogni pezzo di Apache, Samba, Mozilla, KDE... e del vostro software. Questa sarebbe già una ragione sufficiente per usarlo, ma ce ne sono altre:
FHS è uno standard, e senza standard avremmo il caos;
questa è l'organizzazione basilare del sistema operativo, riguardo ai livelli di accesso e alla sicurezza; qui gli utenti possono rintracciare ogni file intuitivamente;
semplifica la vita agli utenti.
Quest'ultimo motivo è sufficiente a giustificare l'adozione di FHS, perciò siate sempre guidati dal FHS!
Riassumiamo ora cosa ha da dire FHS riguardo alle directory di Linux:
directory di sistema di Linux
/usr/bin
Directory per gli eseguibili che sono accessibili da parte di tutti gli utenti (ognuno ha questa directory nel suo $PATH). I file principali del vostro software risiederanno probabilmente qui. Non si dovrebbe mai creare una sottodirectory di questa directory.
/bin
Come /usr/bin, ma qui troverete solo eseguibili che sono vitali per il processo di boot, piccoli e semplici. Il vostro software (essendo ad alto livello) non ha nulla da installare qui.
/usr/sbin
Come /usr/bin, ma contiene gli eseguibili che devono essere acceduti solo dall'amministratore di sistema (root). Gli utenti regolari non dovrebbero mai avere questa directory nel loro $PATH. Se il vostro software gira come demone, questa sarà la directory per alcuni degli eseguibili.
/sbin
Come /usr/sbin, ma solo per gli eseguibili vitali per il processo di boot, e per alcuni che saranno utilizzati dall'amministratore per la manutenzione del sistema. Qui si trovano comandi come fsck (check del filesystem), init (il padre di tutti gli altri processi), ifconfig (configurazione della rete), mount, etc. E' la directory più vitale per il sistema, sotto molti aspetti.
/usr/lib
Contiene le librerie dinamiche e i file statici di supporto per gli eseguibili in /usr/bin e /usr/sbin. Si può creare una sottodirectory come /usr/lib/mioprodotto per contenere tutti i file di supporto o le librerie che saranno accedute solo dal software, senza alcun intervento dell'utente. Una sottodirectory potrebbe ad esempio essere utilizzata per plugin ed estensioni.
/lib
Come /usr/lib, ma contiene librerie necessarie al processo di boot. Non troverete mai un eseguibile in /bin o /sbin che necessiti di librerie all'esterno di questa directory. I moduli del kernel (device driver) sono sotto /lib.
/etc
Contiene i file di configurazione. Se il software usa diversi file, metteteli in una sottodirectory come /etc/mioprodotto.
/var
Il nome deriva da "variable" (variabile), perché tutto ciò che è sotto questa directory cambia frequentemente. Spesso, /var è montata in una partizione separata, ad alte performance. I file di log "crescono" in /var/log. Per i contenuti del web, usiamo /var/www, e così via.
/home
Contiene le directory home degli utenti (intesi come reali esseri umani). Il vostro software non dovrebbe mai porre file qui, durante l'installazione. Se la logica di business richiede la creazione di un utente UNIX speciale (non un essere umano), dovreste assegnargli una directory home sotto /var o da qualche altra parte all'esterno di /home. Non dimenticatelo!
/usr/share/doc, /usr/share/man
La parola "share" (condividi) è usata perché tutto ciò che è sotto /usr/share è indipendente dalla piattaforma e può essere condiviso tra varie macchine attraverso un filesystem di rete. Pertanto questo è il luogo per manuali, documentazione, esempi, ecc.
/usr/local, /opt
Queste cartelle sono obsolete. Quando UNIX non aveva un sistema di pacchetti (come RPM), gli amministratori avevano bisogno di separare un'applicazione opzionale (local) dal sistema operativo principale. Queste erano le directory usate per questo scopo.
Potreste pensare che rompere il software in più pezzi, al posto di tenerlo tutto in una sola cartella auto-contenuta, sia una cattiva idea. Tuttavia, ogni sistema di pacchetti (come RPM) ha un database che gestisce tutto questo per voi in maniera molto professionale, prendendosi cura dei file di configurazione, delle directory e così via. Inoltre, se distribuite il software tra le directory usando FHS, oltre a renderlo molto più user-friendly, aiuterete l'amministratore di sistema a configurarlo bene, con migliori performance e sicurezza.
Ora che conosciamo dove deve essere installata ciascuna parte del nostro software, vediamo la Tabella Universale delle Parti applicata alla FHS.
Tabella 2. Stesso Software, applicando FHS
Applicazione | Software in sè | Configurazione | Contenuti | Log, Dump, ecc. |
---|---|---|---|---|
Server Database | /usr/bin/, /usr/lib/, /usr/share/doc/mydb/, /usr/share/doc/mydb/examples/ | /etc/mydb/ | /var/db/instance1/, /var/db/instance2/, etc | /var/db/instance1/transactions/, /var/log/db/access-instance1.log, /var/log/db/access-instance2.log |
Editor di testi | /usr/bin/, /usr/lib/, /usr/lib/myeditor/plugins/, /usr/share/myeditor/templates/, /usr/share/doc/myeditor/ | $HOME/.myeditor.conf | $HOME/Docs/ | $HOME/.myeditor-tmp/ |
Generatore di MP3 | /usr/bin/, /usr/lib/, /usr/lib/mymp3/plugins/, /usr/share/doc/mymp3/ | $HOME/.mymp3.conf | $HOME/Music/ | $HOME/.mymp3-tmp/ |
Server Web | /usr/sbin/, /usr/bin/, /usr/lib/httpd-modules/, /usr/share/doc/httpd/, /usr/share/doc/httpd/examples/ | /etc/httpd/, /etc/httpd/instance1/, /etc/httpd/instance2/ | /var/www/, /var/www/instance1/, /var/www/instance2/ | /var/logs/httpd/, /var/logs/httpd/instance1/, /var/logs/httpd/instance2/ |
Server E-Mail | /usr/sbin/, /usr/bin/, /usr/lib/, /usr/share/doc/mymail/ | /etc/mail/, /etc/mailserver.cf | /var/mail/ | /var/spool/mailqueue/, /var/logs/mail.log |
Questo è un argomento molto polemico, perciò questa è la sezione più importante di questo documento. Dopo circa 10 anni di esperienza in UNIX sono in grado di confutare ogni argomentazione favorevole a /usr/local. Proverò ad organizzare qui alcune idee.
E' molto importante per l'evoluzione e la popolarizzazione di Linux (soprattutto nel campo di battaglia dei desktop) che gli sviluppatori smettano di usare queste directory, e comincino ad usare la FHS. Dopo aver letto questa sezione, se penserete ancora che queste directory siano cosa buona e giusta, mandatemi un'email.
I prodotti installati completamente in una sola directory usano un approccio di "auto-completamento", che ha svariati problemi:
Costringe gli utenti a cambiare variabili di ambiente come $PATH e $LD_LIBRARY_PATH per usare il tuo prodotto senza diventare matti.
Mette i file in locazioni non standard, complicando l'integrazione del sistema e future installazioni delle estensioni al prodotto.
L'amministratore probabilmente non ha previsto molto spazio vuoto in queste partizioni, il che può generare problemi all'installazione.
E' un approccio accettabile solo per applicazioni puramente grafiche, senza concetto di linea di comando. Questo è il motivo per cui è ben accetto in Windows. Ma...
...anche usando questo approccio, non si può evitare di installare o cambiare file in locazioni standard, ad esempio per far apparire le icone nel desktop dell'utente.
Queste directory esistono per ragioni storiche, e per compatibilità con altri UNIX, dall'epoca in cui non avevamo un sistema di gestione dei pacchetti. In quel caso l'amministratore aveva bisogno di segregare i prodotti per averne il controllo. E l'ultimo punto ci dimostra che anche se ci si prova, non si è in grado di segregare completamente un applicazione. La rendereste solo distante e scomoda per l'utente.
Non si deve temere di distribuire i file tra le cartelle previste dalla FHS, perché RPM li terrà d'occhio per voi.
Molti sviluppatori credono che l'approccio di "auto-contenimento" permetta loro di lavorare con versioni diverse dello stesso prodotto, per scopi di test o qualsiasi altro motivo. Sì, sentitevi liberi di essere d'accordo con questo o qualsiasi altro buon motivo del mondo. Ma ricordate che l'obiettivo di un Software di Alta Qualità (o un Software di Livello Commerciale) è di essere pratico per l'utente finale, anche se ciò lo rende scomodo per il programmatore o il tester. Autoinvitatevi da un utente senza nessuna esperienza (ma potenziale acquirente) e guardatelo mentre installa il tuo software.
Se avete bisogno che l'utente lavori con più versioni del vostro software contemporaneamente (o avete altre necessità simili), create un pacchetto rilocabile (relocatable package), come descritto nel libro Maximum RPM. Considerate anche le implicazioni di usare questa tecnica, descritte nello stesso libro.
Nota che distribuzioni come RedHat e derivati usano sempre la FHS, al posto di /opt e /usr/local. Leggete quanto RedHat dice sull'argomento, e pensateci.
I makefile di un programma open source che voglia essere portabile ad altri UNIX devono prevedere l'installazione di default in /usr/local per motivi di compatibilità. Ma devono anche offrire la possibilità di creare il pacchetto usando le specifiche FHS, ed incoraggiare l'utente a farlo.
Probabilmente permetterete che altri produttori di software producano estensioni all'applicativo. Poiché voi siete gli autori del pacchetto iniziale, è vostra responsabilità organizzarlo in modo che l'utente possa semplicemente installare l'RPM con l'estensione e usarlo, senza forzarlo a modificare alcun file di configurazione. E' di nuovo il famoso concetto di "Installa-e-usa", che garantisce la facilità d'utilizzo.
Un'estensione non consiste in altro che alcuni file nel formato appropriato (DLL che implementano alcune API che il tuo software specifica), posti nella directory appropriata (dove il tuo software li cerca). Si vedono molte applicazioni che richiedono all'utente di cambiare il file di configurazione per "dichiarare" la presenza di un nuovo plugin.
La cosa più importante da considerare nella vostra architettura a plugin è di non condividere file tra i plugin e il software. Dovreste fornire un'architettura in cui i plugin si installino e disinstallino semplicemente aggiungendo e rimuovendo file in cartelle specifiche, documentate dal programma. Buoni candidati sono /usr/lib/mioprodotto/plugins/ come directory per i plugin, ed /etc/mioprodotto/plugins/ per i file di configurazione. Il software e le sue estensioni devono essere sufficientemente intelligenti da sapere come trovare i file, specialmente quelli di configurazione, in queste directory. Usando questo approccio, nessuna procedura post-installazione è richiesta da parte dell'utente o del fornitore del plugin.
Vorrei chiudere l'argomento invitandovi a considerare come qualsiasi programma possa essere pensato come estensione di un programma più a basso livello. Nello stesso modo in cui un plugin di una terza parte è un'estensione del vostro software, il vostro software è un'estensione del sistema operativo (più basso livello). Qui risiede la magia dell'Integrazione (dal titolo di questo documento). Perciò possiamo applicare tutti i concetti di facilità d'uso visti finora alla progettazione dell'architettura a plugin del vostro software.
Questo è molto importante per più motivi:
Facilità d'uso. Questa è sempre la motivazione principale.
Automazione di alcuni task che devono essere svolti prima e dopo l'installazione del vostro software. Il che di nuovo ha implicazioni con la facilità d'uso.
Gestione intelligente dei file di configurazione, documentazione, ecc, in modo da fornire maggior controllo sui processi di upgrade.
Gestione delle interdipendenze con altri pacchetti e versioni, garanzia di una buona funzionalità.
Supporto alla distribuzione di software con la firma digitale della vostra compagnia, e checksum (md5) su ogni file. Questo garantisce l'integrità, e permette di rilevare modifiche non autorizzate a file.
Supporto per strumenti che permettono all'amministratore di interagire con l'installer grafico.
Un buon pacchetto non vuol però dire solo mettere i vostri file in un RPM. La FHS deve essere rispettata, i file di configurazione e documentazione devono essere marcati come tali, e gli script di pre e post installazione devono essere consistenti, in modo da non danneggiare il sistema (ricordate che i processi d'installazione sono eseguiti da root).
Familiarizzate con RPM (NdMano: argomento di un prossimo articolo del PJ :-) in modo approfondito, perché significa molta più potenza e comodità per voi e per l'utente. C'è molta documentazione disponibile su RPM su Internet:
Il libro Maximum RPM, disponibile anche on line e in formato PostScript.
L'RPM-HOWTO, più piccolo e diretto.
Dovreste permettere all'utente di installare solo le parti del software che realmente desidera. Immaginate che l'applicazione abbia una parte client ed una server, con file e librerie in comune. Dovreste romperla in tre RPM. Per esempio, poniamo che il nome del prodotto sia MyDB; fornirete allora tre pacchetti:
MyDB-common-1.0-3.i386.rpm
MyDB-server-1.0-3.i386.rpm
MyDB-client-1.0-3.i386.rpm
Gli ultimi due dipendono dal primo. Se l'utente sta installando un profilo cliente, userà:
MyDB-common-1.0-3.i386.rpm
MyDB-client-1.0-3.i386.rpm
Se un server:
MyDB-common-1.0-3.i386.rpm
MyDB-server-1.0-3.i386.rpm
Questo approccio aiuterà l'utente a risparmiare spazio su disco, ed essere conscio di come è organizzato il software.
In una prospettiva molto generale, sicurezza è sinonimo di mantenere l'ordine, il controllo. E insicuro è tutto ciò che va contro questo concetto. Perciò, lasciando da parte porte aperte o crittografie deboli (che vanno oltre gli scopi di questo documento), applicazioni che richiedano che l'utente agisca solo come root, o che modifichino file in locazioni protette, sono da considerare insicure. Possiamo dire lo stesso di applicazioni che riempiono indiscriminatamente un filesystem vitale per il sistema operativo.
Alcune buone pratiche di programmazione, sperimentate per molto tempo e su cui c'è grande esperienza, hanno portato alla definizione di parecchi standard in materia di sicurezza. Perciò, dovreste conoscerli ed utilizzarli quando distribuite il vostro software, perché sono la chiave per raggiungere un buon livello di organizzazione. Cioè, di sicurezza.
Tutti amano le interfacce grafiche. Molte volte rendono le nostre vite più facili, ed in questo senso aiutano a rendere popolare il software, perché la curva di apprendimento si appiattisce. Tuttavia, per la vita di tutti i giorni, un comando di console che abbia molte opzioni ben fatte ed un buon manuale risultano molto più pratici, rendendo semplici gli script, permettendo l'accesso da remoto, etc. Il suggerimento perciò è quello di fornire, quando possibile, entrambe le interfacce: grafica per i principianti, ed una potente riga di comando per gli esperti.
KDE, GNOME, Java o Motif?
Meglio di una semplice interfaccia grafica è un desktop integrato. E i desktop di Linuxlandia sono, oggi, KDE e GNOME. Cercate sempre di supportarne uno, od entrambi.
KDE è il più maturo, e offre un desktop molto consistente, flessibilità, e una architettura molto elegante che impiega tra le altre cose componenti ed intercomunicazione tra processi. E' in costante evoluzione, è sviluppato in C++, e le sue applicazioni si giovano di un look-and-feel molto familiare ed integrato.
GNOME utilizza anch'esso un concetto di desktop integrato, ma è lontano dalla maturità e facilità di utilizzo di KDE. D'altra parte, è molto ben supportato dalla comunità, e miglioramenti sostanziali sono alle porte (NdMano: è di questi tempi l'uscita di GNOME 2, e pare proprio che abbia fatto grossi passi avanti).
Motif non è un desktop integrato. E' una libreria di widget (bottoni, scrollbar, ecc) più che un window-manager. E' nato come prodotto commerciale, è maturo, ed è popolare nelle applicazioni commerciali. Motif è però considerato obsoleto alla luce di KDE e GNOME, che integrano un desktop al loro interno. Il codice di Motif è stato reso open dall'OpenGroup e rinominato OpenMotif.
Java viene utilizzato sempre più per le interfacce grafiche, specialmente in software per server, dove la grafica è solo un aiuto per la configurazione ed amministrazione.
Interfacce Web: accesso da ogni luogo
Al giorno d'oggi, ogni desktop è provvisto di un browser, e se il vostro prodotto è un'applicazione server, un'interfaccia web è la scelta migliore, perché permette all'amministratore di gestire l'applicazione anche da remoto. Tenete però in considerazione la sicurezza e l'organizzazione dei vostri CGI (o script PHP, o servlet Java, ecc.), perché possono diventare ingressi privilegiati per cracker. La programmazione di interfacce web (CGI o altro) è un paradigma completamente differente. Provate a comprenderlo dapprima concettualmente, partendo da "come funziona un server web", "cos'è un URL", ecc., per evitare di compromettere tutta la sicurezza del vostro prodotto.
Wizard ed installer grafici
Specialmente se è un prodotto commerciale, l'applicazione dovrebbe prevedere un installer grafico. Credetemi, fanno molta impressione in una dimostrazione, e gli amministratori delegati li adorano!
Più che semplicemente supervisionare l'installazione, un wizard (o druid, per dirla alla GNOME) aiuta nella configurazione iniziale del prodotto, raccoglie informazioni come le chiavi di attivazione, e mostra le licenze.
Un wizard non dovrebbe fare altro che questo:
Chiedere quali moduli installare, e presentarli all'utente come checkbox.
Ottenere le informazioni necessarie a costruire la configurazione iniziale (l'anima) del software.
Installare i moduli selezionati, che sono in pratica file RPM. Ogni checkbox rappresenterà uno o più RPM, poiché ogni RPM è una porzione indivisibile (atomica) del software.
Dopo che gli RPM sono stati installati, cambiare la configurazione (contrassegnata come tale negli RPM) del software (lo spirito), basandosi sui dati che l'utente ha fornito al wizard.
Quindi, il wizard nasconde l'installazione degli RPM ed opera la personalizzazione iniziale. RPM è ancora responsabile di mettere tutti i file del vostro software nei posti corretti. Questo ruolo non dovrebbe mai ricadere sull'installer. Pensate sempre che un utente esperto (ce ne sono molti nel mondo di Linux) dovrebbe essere in grado di riprodurre l'installazione del prodotto senza l'aiuto grafico, solo con i comandi di RPM. Nei fatti, nei grandi centri dati dove la gente fa installazioni di massa, un installer grafico è solo un ostacolo.
RPM fornisce strumenti che aiutano il vostro installer grafico ad interagire con esso, come il visualizzatore di avanzamento dell'installazione. La documentazione per il loro utilizzo si può trovare nel manuale di RPM (man rpm) e nel libro Maximum RPM.
Il modo in cui Linux avvia (e arresta) tutti i suoi sottosistemi è molto semplice e modulare. Permette di definire l'ordine di inizializzazione, i runlevel, e così via.
Dal BIOS ai sottosistemi
Vediamo cosa accade quando avviamo Linux:
Il BIOS o un boot loader (lilo, zlilo, grub, ecc.) carica il kernel di Linux dal disco alla memoria, con alcuni parametri definiti nella sua configurazione. Possiamo accorgerci di questo processo osservando i punti che appaiono sullo schermo. Il file del kernel risiede nella directory /boot, ed è acceduto solo in questo momento.
In memoria, il codice del kernel si avvia, riconosce una serie di dispositivi vitali, le partizioni dei dischi, etc.
Una delle ultime cose che fa è montare il filesystem di root (/), che deve contenere obbligatoriamente le directory /etc, /sbin, /bin e /lib.
Subito dopo, richiama il programma init (/sbin/init) e gli passa il controllo.
Esso legge il suo file di configurazione (/etc/inittab) che definisce il runlevel del sistema ed alcuni script della shell da avviare.
Questi script continuano il setup dell'infrastruttura minima del sistema, montando gli altri filesystem (secondo /etc/fstab), attivando lo spazio di swap (memoria virtuale), etc.
L'ultimo passo, più interessante per voi, è l'esecuzione di uno speciale script, /etc/rc.d/rc, che inizializza i sottosistemi secondo i dati contenuti nella directory /etc/rc.d. Il nome rc deriva da "run commands" (comandi d'avvio).
I runlevel
Il meccanismo dei runlevel permette a Linux di inizializzarsi in diversi modi. Inoltre, ci permette di passare da un profilo (runlevel) ad un altro senza riavviare il sistema.
Il runlevel di default è definito in /etc/inittab con una riga del genere:
Esempio 3. Runlevel di default (3, in questo caso), riga in /etc/inittab
id:3:initdefault:
I runlevel sono numeri da 0 a 6, ed ognuno di essi segue questo standard:
Runlevel | Note |
0 | Arresta il sistema. Passando a questo runlevel, tutti i sottosistemi vengono disattivati prima dell'arresto. Non va usato nella linea initdefault di /etc/inittab. |
1 | Modo monoutente. Sono inizializzati solo i sottosistemi vitali, perché è usato per la manutenzione del sistema. Nessuna autenticazione (login) è richiesta in questo runlevel. Viene restituita all'utente direttamente una riga di comando. |
2 | Storicamente simile a 3, ma senza NFS. |
3 | Usato quando un sistema è in piena produzione. Consideralo il runlevel a cui funzionerà il tuo software. |
4 | Inutilizzato. Puoi definirlo come vuoi, ma non è comune farlo. |
5 | Come 3, più un login grafico. E' l'ideale per una workstation desktop. Usa 3 se la macchina sarà utilizzata come server, per sicurezza e ragioni di performance. |
6 | Come il runlevel 0, ma dopo lo stop completo, la macchina è riavviata. Non va usato nella linea initdefault di /etc/inittab. |
Si può passare da un runlevel ad un altro usando il comando telinit. E si può vedere il runlevel corrente e l'ultimo con il comando runlevel. Vedere qui sotto come si passa dal runlevel 3 a 5:
bash# runlevel bN 3 bbash# telinit 5 bbash# runlevel b3 5 bbash#
I sottosistemi
Alcuni esempi di sottosistema sono un web server, un server di database, un layer di rete del sistema operativo, ecc. Non considereremo sottosistema le applicazioni orientate all'utente (come un editor di testo).
Linux fornisce un metodo elegante e modulare per organizzare l'inizializzazione dei sottosistemi. Un importante fatto su cui porre l'attenzione è la loro interdipendenza. Per esempio, non ha senso avviare un server web prima che il sottosistema base della rete (network) sia attivo.
I sottosistemi sono organizzati sotto le directory /etc/init.d e /etc/rc.d/rcN.d:
/etc/init.d
Tutti i sottosistemi installati pongono in questa directory un programma di controllo, in altre parole uno script che segue un semplice standard descritto più sotto. Questo è un listato semplificato di questa directory:
Esempio 4. Sottosistemi installati in /etc/init.d
bash:/etc/init.d# ls -l
-rwxr-xr-x 1 root root 9284 Aug 13 2001 functions
-rwxr-xr-x 1 root root 4984 Sep 5 00:18 halt
-rwxr-xr-x 1 root root 5528 Nov 5 09:44 firewall
-rwxr-xr-x 1 root root 1277 Sep 5 21:09 keytable
-rwxr-xr-x 1 root root 487 Jan 30 2001 killall
-rwxr-xr-x 1 root root 7958 Aug 15 17:20 network
-rwxr-xr-x 1 root root 1490 Sep 5 07:54 ntpd
-rwxr-xr-x 1 root root 2295 Jan 30 2001 rawdevices
-rwxr-xr-x 1 root root 1830 Aug 31 09:29 httpd
-rwxr-xr-x 1 root root 1311 Aug 15 14:18 syslog
/etc/rc.d/rcN.d (N è l'indicatore del runlevel)
Queste directory devono contenere solo link simbolici speciali verso gli script in /etc/init.d. Questo è come appare:
Esempio 5. listato di /etc/rc3.d
bash:/etc/rc3.d# ls -l
lrwxrwxrwx 1 root root 18 Jan 14 11:59 K92firewall -> ../init.d/firewall
lrwxrwxrwx 1 root root 17 Jan 14 11:59 S10network -> ../init.d/network
lrwxrwxrwx 1 root root 16 Jan 14 11:59 S12syslog -> ../init.d/syslog
lrwxrwxrwx 1 root root 18 Jan 14 11:59 S17keytable -> ../init.d/keytable
lrwxrwxrwx 1 root root 20 Jan 14 11:59 S56rawdevices -> ../init.d/rawdevices
lrwxrwxrwx 1 root root 16 Jan 14 11:59 S56xinetd -> ../init.d/xinetd
lrwxrwxrwx 1 root root 18 Jan 14 11:59 S75httpd -> ../init.d/httpd
lrwxrwxrwx 1 root root 11 Jan 13 21:45 S99local -> ../rc.local
Notare che tutti i nomi dei link hanno un prefisso che inizia con la lettera K (da Kill, disattivare) o S (da Start, attivare), e un numero di 2 cifre che definisce la priorità di attivazione al boot. Nel nostro esempio abbiamo HTTPd (priorità 75) che si avvierà dopo il sottosistema Network (priorità 10). Il sottosistema di Firewall sarà disattivato (K) in questo runlevel.
Perciò, per far sì che il software parta automaticamente al processo di boot, esso dev'essere un sottosistema. Vedremo come renderlo tale nella prossima sezione.
Trasformare il vostro software in un sottosistema
I file del vostro software saranno sparsi in tutto il filesystem, ma sarebbe meglio fornire una interfaccia semplice e consistente per permettere che l'utente almeno possa avviarlo e interromperlo. L'architettura dei sottosistemi promuove questa facilità d'uso, fornendo anche un modo perché sia automaticamente avviato all'inizializzazione del sistema. Si deve semplicemente creare lo script per /etc/init.d seguendo uno standard per renderlo funzionale. Date un'occhiata agli script già esistenti per farvi un'idea.
I metodi di un ipotetico sottosistema mysystem saranno richiamati dall'utente con il comando service, come in questo esempio:
Esempio 6. utilizzo del comando service
bash# service mysystem start
Starting MySystem: [ OK ]
bash# service mysystem status
Subsysten MySystem is active with pid 1234
bash# service mysystem reload
Reloading MySystem: [ OK ]
bash# service mysystem stop
Stopping MySystem: [ OK ]
bash#
Non vi dovete preoccupare di amministrare i link simbolici in /etc/rc.d/rcN.d. Il comando chkconfig lo farà per voi, sulla base dei commenti di controllo che avrete definito all'inizio del vostro script.
Esempio 7. Utilizzo del comando chkconfig
bash# chkconfig --add mysystem
bash# chkconfig --del mysystem
Leggete la pagina man di chkconfig per sapere cos'altro può fare per voi.
Gestire i vostri script con un sistema a pacchetti
Quando create un RPM, mettete lo script del vostro sottosistema in /etc/init.d , ma non includete alcun link in /etc/rc.d/rcNr.d, perché è una decisione che spetta all'utente se automatizzare il vostro sottosistema o meno. Se ne includete, e l'utente effettua qualche cambiamento, l'archivio del file RPM diventerà disallineato con la situazione del filesystem.
I link simbolici devono essere creati e rimossi dinamicamente dai processi di post-installazione e pre-disinstallazione del pacchetto, utilizzando il comando chkconfig. Questo approccio garantisce al 100% la consistenza del filesystem.
A. Red Hat, About the Filesystem Structure
NdMano: questa sezione, appartenendo a una fonte esterna all'articolo, non è tradotta. Riferirsi eventualmente alle traduzioni ufficiali di RedHat
This text was taken from The Official Red Hat Linux Reference Guide
Why Share a Common Structure?
An operating system's filesystem structure is its most basic level of organization. Almost all of the ways an operating system interacts with its users, applications, and security model are dependent upon the way it stores its files on a primary storage device (normally a hard disk drive). It is crucial for a variety of reasons that users, as well as programs at the time of installation and beyond, be able to refer to a common guideline to know where to read and write their binary, configuration, log, and other necessary files.
A filesystem can be seen in terms of two different logical categories of files:
Shareable vs. unshareable files
Variable vs. static files
Shareable files are those that can be accessed by various hosts; unshareable files are not available to any other hosts. Variable files can change at any time without system administrator intervention (whether active or passive); static files, such as documentation and binaries, do not change without an action from the system administrator or an agent that the system administrator has placed in motion to accomplish that task.
The reason for looking at files in this way has to do with the type of permissions given to the directory that holds them. The way in which the operating system and its users need to utilize the files determines the directory where those files should be placed, whether the directory is mounted read-only or read-write, and the level of access allowed on each file. The top level of this organization (/ directory)is crucial, as the access to the underlying directories can be restricted or security problems may manifest themselves if the top level is left disorganized (security=organization) or without a widely-utilized structure.
However, simply having a structure does not mean very much unless it is a standard. Competing structures can actually cause more problems than they fix. Because of this, Red Hat has chosen the the most widely-used filesystem structure and extended it only slightly to accommodate special files used within Red Hat Linux.
B. Su questo documento
Questo documento è distribuito nei termini della GNU Free Documentation License, il che lo rende sufficientemente libero. Tutti sono invitati a contribuire al suo contenuto e alle sue idee.
Copyright 2002, Avi Alkalay.
La versione originale di questo documento può essere reperita online su http://avi.alkalay.net/linux/docs/HighQuality/.
E' stato scritto originariamente in portoghese brasiliano, quindi tradotto in inglese (NdMano: e in italiano). Sono stati utilizzati SGML ed il più-che-incredibile DocBook, il che ha reso possibile distribuire questo documento nei vari formati disponibili nel sito.
E' stato terminato (portoghese+inglese) alla metà di Marzo 2002. Tutti i cambiamenti dopo questa data sono solo cosmetici.
L'ho scritto per aiutare le ditte e gli sviluppatori di Open-Source a scrivere software plug-and-play e facile da usare per Linux, e migliorare in questo modo la sua usabilità e popolarità.
Tutti i concetti qui esposti (da un punto di vista di alto livello) possono essere utilizzati in ogni *NIX, e perfino in altri sistemi operativi, come Windows. Forse un giorno scriverò uno di questi documenti per Windows... o Mac....
<- PW: Intro C/C++ - Indice Generale - Copertina - PW: GTK2 -> |