giovedì 26 settembre 2013

Installare Pipelight su Fedora 19

Nonostante venga oramai da anni visto da molti come un software morto e senza futuro, Silverlight a tutt'oggi continua a godere in rete di una discreta diffusione. Gli utenti Linux non hanno però mai avuto vita facile con questa tecnologia: Microsoft non ha mai rilasciato alcuna versione ufficiale per il pinguino e Moonlight, un'implementazione opensource dell'ambiente di Silverlight per Linux, ha chiuso i battenti da oltre due anni.
Di recente è nato un nuovo progetto, Pipelight, che promette di far girare la versione di Silverlight per Windows su Linux, tramite una versione di Wine modificata ad hoc con una serie di patch, colmando così il vuoto venutosi a creare con l'arresto dello sviluppo di Moonlight.

Pipelight, nonostante la giovane età, si è comportato molto bene nelle prove eseguite (non sono sicuro della riproduzione di contenuti protetti da DRM, che non ho potuto testare a fondo)
Per facilitare l'installazione agli utenti di Fedora ho realizzato una serie di pacchetti rpm che potete prelevare da questo repository dedicato
Ovviamente il tutto (sia pipelight che i mie rpm) va considerato estremamente sperimentale!

Per provare pipelight occorre innanzitutto attivare il repo, dando in un terminale:
# wget https://dl.dropboxusercontent.com/u/7141888/home_darkhado_pipelight/19/darkhado_pipelight.repo -P /etc/yum.repos.d/
Installiamo quindi il pacchetto con:
# yum install pipelight 
Nota: Oltre a pipelight verrà installata la versione di wine patchata, che andrà a sostituire completamente quella eventualmente già presente nella vostra macchina!

Per far funzionare correttamente il programma sono richiesti inoltri alcuni font per Windows, che però dovremo installare manualmente, poiché redistribuirli all'interno di un pacchetto binario significherebbe violare i termini della licenza Microsoft.
Per semplificare un poco la procedura ho inserito nel repo anche il pacchetto sorgente di msttcorefonts (realizzato partendo dal file spec disponibile qui)
Compilando ed installando tale pacchetto avremo tutti i font necessari. Eseguiamo in un terminale le seguenti istruzioni:
$ yumdownloader --source msttcorefonts
$ rpm -ihv msttcorefonts-2.5-1.src.rpm
$ cd ~/rpmbuild/SPECS/
# yum-builddep msttcorefonts-2.5-1.spec
$ rpmbuild -bb msttcorefonts-2.5-1.spec
# yum install ../RPMS/noarch/msttcorefonts-2.5-1.noarch.rpm
 (Attenzione ai comandi da eseguire come user - $ - e quelli che invece richiedono i privilegi di root - # -)

Non ci resta che ora che aprire il nostro browser e verificare il comportamento di pipelight (personalmente consiglio di utilizzare Firefox che nelle mie prove ha risposto molto meglio rispetto a Chromium)

Alcuni link utili per fare qualche test:
http://www.microsoft.com/silverlight/iis-smooth-streaming/demo/
http://bubblemark.com/silverlight2.html
http://live.la7.it/dirette_tv/ 

EDIT:
Una cosa importantissima che avevo omesso è che è assolutamente essenziale non aver alcun browser aperto durante l'installazione di pipelight affinché questa possa concludersi con successo; in caso contrario ci ritroveremmo con il plugin non funzionante. 
É possibile comunque riparare facilmente l'installazione seguendo queste istruzioni

giovedì 19 settembre 2013

Installare Archlinux in una chroot su Fedora

Certamente saprete che esiste un gran varietà di soluzioni (VirtualBox, VMware, Boxes, etc) per installare ed eseguire una o più macchine virtuali all'interno del nostro sistema GNU/Linux.
Tutte però hanno gli svantaggi di essere avide di risorse e di offrire delle prestazioni per i i sistemi guest spesso tutt'altro che esaltanti.
In questo articolo vi illustrerò un metodo alternativo alla virtualizzazione "classica" che non fa ricorso a nessuno dei software citati sopra: installeremo il sistema guest non su un disco virtuale ma in una "chroot", ossia in una normalissima directory del nostro filesystem che all'occorrenza diventerà la root del nostro sistema virtuale.
I vantaggi più evidenti:
- sistema guest immediatamente disponibile, senza alcun tempo di caricamento aggiuntivo.
- prestazioni del guest pari a quelle dell'host.
- possibilità di eseguire all'interno del desktop del sistema host un applicativo del sistema guest, senza dover avviare un'ulteriore sessione grafica.

Vediamo ora come realizzare praticamente tutto questo installando, a titolo di esempio, Archlinux (guest) su una macchina Fedora (host).
L'uso dei termini "host" e "guest" vi risulterà forse un po' inappropriato, non trattandosi questa di una vera e propria virtualizzazione,  ma spero comunque che me lo concederete, un po' per comodità e un po' per la mancanza di vocaboli più consoni. :-)

Iniziamo con il prelevare l'ultima iso di Archlinux disponibile sul sito ufficiale (alla data in cui scrivo archlinux-2013.09.01-dual.iso)
Terminato il download, montiamo l'immagine in una directory di nostra scelta, ad esempio:
# mount archlinux-2013.09.01-dual.iso -o loop /mnt/img/
In base alla versione di Archlinux che desideriamo installare ci sposteremo nella directory i686 o x86_64
all'interno della iso montata.
32 bit:
$ cd /mnt/img/arch/i686/
64 bit:
$ cd /mnt/img/arch/x86_64/
Nelle directory troviamo un file root-image.fs.sfs, compresso con squashfs, che contiene l'immagine di una installazione Archlinux.
Scompattiamo il file in una directory a nostro piacere, ad esempio:
# unsquashfs -d /squashfs root-image.fs.sfs
(Nota: la destinazione, indicata con l'opzione -d, non deve essere già presente nel filesystem, altrimenti il comando fallirà)
Montiamo ora l'immagine presente nella directory appena creata:
# mount /squashfs/root-image.fs -o loop /mnt/arch/
Se diamo un:
 $ ls /mnt/arch/
possiamo verificare la presenza della struttura classica delle directory di un sistema GNU/Linux.
bin   dev  home  lost+found  opt   root  sbin  sys  usr
boot  etc  lib   mnt         proc  run   srv   tmp  var
Siamo pronti per completare l'installazione di Archlinux all'interno della nostra Fedora:
# mkdir /arch
# cp -a /mnt/arch/* /arch/
Prima di "avviare" Archlinux smontiamo le immagini e rimuoviamo tutto ciò che non ci serve più:
# rm -rf /squashfs/
# umount /mnt/img
# umonut /mnt/arch
Verifichiamo ora di avere svolto tutto correttamente; avviamo la chroot:
 # chroot /arch/
Proviamo a dare qualche comando esclusivo di Archlinux come:
# pacman -Q
o semplicemente un:
# cat /etc/issue 
 che ci restituirà:
Arch Linux \r (\l)
Non c'è dubbio, stiamo ora utilizzando Archlinux!! :-)
Il nostro lavoro tuttavia non è ancora finito, per rendere pienamente utilizzabile il sistema guest dovremo dedicarci ancora un po' alla sua configurazione.
Innanzitutto dovremo creare un utente con lo stesso id del nostro utente Fedora; questo ci servirà per eseguire correttamente applicazione grafiche e pulseaudio nella chroot.
Con tutta probabilità l'id dell'utente Fedora è 1000 (come da impostazione predefinita); verifichiamolo eseguendo in un nuovo terminale:
$ id -u
Nella chroot esiste già un utente con id 1000 (utente arch), ragion per cui dovremo innanzitutto eliminarlo prima di poter procedere alla creazione di un nuovo utente con questo id.
Rimuoviamo quindi l'utente arch:
# userdel arch
# rm -r /home/arch/
Creiamo ora un nuovo utente con lo stesso nome e lo stesso id dell'utente Fedora; ipotizzando di avere l'utente simone con id 1000 diamo:
# useradd -M -u 1000 -U simone
e assegniamo la password all'utente simone con:
# passwd simone
Anche l'utente root non ha ancora alcuna password, rimediamo con:
# passwd 
Usciamo temporaneamente dalla chroot semplicemente dando:
# exit
Per rientrare in Archlinux non useremo più semplicemente il comando chroot come abbiamo fatto in precedenza, ma lanceremo questo script:
 #/bin/sh
mount -t proc none /arch/proc
mount -t sysfs none /arch/sys
mount -o bind /dev /arch/dev
mount -o bind /dev/pts /arch/dev/pts
mount -o bind /var/run /arch/var/run
mount -o bind /var/lib/dbus /arch/var/lib/dbus
mount -o bind /tmp /arch/tmp
mount -o bind /home /arch/home
mount -o bind /dev/shm /arch/dev/shm
cp -Lf /etc/resolv.conf /arch/etc
chroot /arch
Questo è necessario per passare al sistema guest fondamentali informazioni circa l'hardware della nostra macchina, le partizioni, ecc., senza le quali nessun os Linux potrebbe funzionare correttamente.
In particolare l'opzione bind di mount serve in pratica proprio a condividere determinati mountpoint tra host e guest.
Salviamo lo script dandogli come nome start_chroot.sh dopodiché lanciamolo, sempre da root:
# start_chroot.sh
Rientrati nella chroot, dovremmo essere ora in grado di sfruttare finalmente appieno la nostra Archlinux!
Iniziamo con il mettere a punto pacman, il package manager di Archlinux.
# pacman-key --init
# pacman-key --populate archlinux
Proviamo quindi a lanciare un aggiornamento di sistema con:
# pacman -Syu
L'operazione dovrebbe andare a buon fine, segno che il package manager di Archlinux funziona a dovere.
Possiamo a questo punto installare nuovi pacchetti e personalizzare l'installazione a nostro piacimento.
Proviamo infine ad eseguire un applicazione grafica; switchate all'utente creato in precedenza ("simone" nel nostro esempio)
# su  simone
Come test eseguiamo magari un gioco o riproduciamo semplicemente un stream video da YouTube così da verificare che anche l'audio nella chroot funzioni a dovere.

Concludo l'articolo ricordando che per uscire in ogni momento dalla chroot basta digitare "exit" nel terminale.
Lo script che abbiamo visto in precedenza (start_chroot.sh) va lanciato unicamente al primo accesso alla chroot dopo il boot della macchina; i montaggi eseguiti dallo script restano infatti sempre attivi fino allo spegnimento. Per tutti i successivi utilizzi della chroot basterá dare:
# chroot /arch/
EDIT:
Se desiderate uno script più completo che sia anche in grado di smontare le directory condivise una volta terminato di lavorare nella chroot, potete utilizzare questo (realizzato modificando quello presente in questa pagina del wiki di Archlinux)
 #!/bin/bash
MOUNTPOINT=/arch
PIDFILE=/run/arch_chroot
case $1 in
  start)
    mount -t proc none $MOUNTPOINT/proc
    mount -t sysfs none $MOUNTPOINT/sys
    dirs=(/dev /dev/pts /dev/shm /var/run /var/lib/dbus /tmp /home )
    for d in "${dirs[@]}"; do
      mount -o bind $d $MOUNTPOINT$d
    done
    cp -Lf /etc/resolv.conf /arch/etc
    touch $PIDFILE
    ;;
  stop)
    dirs=(/dev/pts /dev/shm /dev /var/run /var/lib/dbus /tmp /home)
    umount $MOUNTPOINT/{sys,proc}
    for d in "${dirs[@]}"; do
      umount -l "$MOUNTPOINT$d"
    done
    rm -f $PIDFILE
    ;;
  *)
    echo "usage: $0 (start|stop)"
    exit 1
esac
Salviamo lo script con il nome arch_chroot, quindi per inizializzare la chroot daremo:
# arch_chroot start
Poi per entrare in Archlinux eseguiremo il solito
# chroot /arch
Una volta usciti dalla chroot con
# exit
Potremo smontare i mounpoint condivisi tra host e guest con:
# arch_chroot stop

mercoledì 4 settembre 2013

Ottimizzare la compilazione su Fedora con distcc e ccache

In questa guida vedremo come installare e configurare distcc e ccache, due strumenti che permettono di abbreviare (e anche di parecchio) i tempi di compilazione.
Distcc è un programma ideato per distribuire i processi di compilazione tra più host all'interno di una rete; è quindi ovviamente necessario disporre di almeno due o più macchine della stessa architettura per potere usufruire dei benefici di questo strumento. In mancanza di questo requisito distcc diventa perfettamente inutile e non ha alcune senso installarlo.
Ccache invece (come riporta wikipedia nell'abbozzo dedicato al programma) "memorizza l'output della compilazione di un programma scritto in C/C++ così che la volta successiva la medesima compilazione possa essere evitata. Questo metodo velocizza di gran lunga il tempo di compilazione."

Vediamo ora come installarli e configurarli in modo da farli lavorare congiuntamente.
Partiamo da ccache:
# yum install ccache
$ source /etc/profile.d/ccache.sh
Se ora provate ad esempio a dare:
ll $(which g++)
lrwxrwxrwx. 1 root root 16  7 lug 23.04 /usr/lib64/ccache/g++ -> ../../bin/ccache
potete notare come il path di g++ (default /usr/bin/g++) sia stato cambiato e punti ora all'eseguibile di ccache. Questo ci garantisce che ogni processo di compilazione verrà gestito dal programma il quale stabilirà di volta in volta se andare a "pescare" i dati dalla sua cache o passare i sorgenti ai compilatori della GNU Compiler Collection.
Non occorrono ulteriori configurazione per usufruire dei vantaggi di ccache, semplicemente lanciate le vostre compilazioni nello stesso identico modo che seguivate prima dell'installazione del programma.

Passiamo all'installazione di distcc (qui le cose si complicano un pochino). Su tutte le macchine della nostra rete che vogliamo utilizzare per le compilazioni "condivise" iniziamo con il dare:
# yum install distcc-server
quindi editiamo la configurazione aprendo il file /etc/sysconfig/distccd.
Ipotizzando di disporre di due macchine con indirizzi 192.168.1.1 e 192.168.1.2 modificheremo il file in questo modo:
OPTIONS="--allow 192.168.1.0/24 --log-file=/var/tmp/distccd.log"
USER="nobody"
--allow 192.168.1.0/24 abilita tutti gli host appartenenti alla rete 192.168.1.x a connettersi al demone distccd.
--log-file abilita la creazione di un file di log. Senza questa opzione distccd invierà i suoi output esclusivamente al file /var/log/messages. Se desiderate che il log memorizzi esclusivamente eventuali messaggi di errore aggiungete l'opzione --log-level error.
USER="nobody" indica invece che il demone girerà con i privilegi dell'utente "nobody", il che dovrebbe garantirci un buon livello di sicurezza.
Se non specificato diversamente distccd girerà sulla porta 3632 (default). Potete indicare una porta differente con l'opzione --port. Dovrete però ricordavi anche di aggiornare opportunamente la configurazione del client (come vedremo più avanti)

Completiamo la configurazione di distcc lato server aprendo la porta 3632 nel firewall (ricordiamoci anche in questo caso di eseguire l'operazione su tutti gli host). Senza bisogno di ricorrere a firewall-config possiamo comodamente aggiornare le impostazioni di firewalld con un'unica istruzione:
# firewall-cmd --permanent --zone=$(firewall-cmd --get-default-zone) --add-port=3632/tcp
controlliamo che la porta 3632 sia stata effettivamente aggiunta all'elenco delle porte aperte:
 # firewall-cmd --permanent --zone=$(firewall-cmd --get-default-zone) --list-ports
Avviamo il demone distccd con:
# systemctl enable distccd
# systemctl start distccd
Il demone creerà una serie di sottoprocessi (di default pari al doppio delle cpu/core del sistema più uno) corrispondenti al numero massimo di compilazioni che possono essere eseguite parallelamente (quindi su un singole core avremo tre processi, su un dual core saranno invece cinque e così via). Possiamo verificarlo con:
$ ps -ef | grep distccd
nobody    3417     1  0 21:09 ?        00:00:00 /usr/bin/distccd --verbose --no-detach --daemon --allow 192.168.1.0/24 --log-file=/var/tmp/distccd.log
nobody    3418  3417  0 21:09 ?        00:00:00 /usr/bin/distccd --verbose --no-detach --daemon --allow 192.168.1.0/24 --log-file=/var/tmp/distccd.log
nobody    3419  3417  0 21:09 ?        00:00:00 /usr/bin/distccd --verbose --no-detach --daemon --allow 192.168.1.0/24 --log-file=/var/tmp/distccd.log
nobody    3420  3417  0 21:09 ?        00:00:00 /usr/bin/distccd --verbose --no-detach --daemon --allow 192.168.1.0/24 --log-file=/var/tmp/distccd.log
nobody    3421  3417  0 21:09 ?        00:00:00 /usr/bin/distccd --verbose --no-detach --daemon --allow 192.168.1.0/24 --log-file=/var/tmp/distccd.log
L'output riporta cinque demoni distccd, valore corretto per un macchina dual core. Possiamo anche forzare la creazione di un numero arbitrario di processi con l'opzione --jobs sempre nel file /etc/sysconfig/distccd.

Installiamo ora il client di distcc su una o più macchine che useremo per lanciare le attività di compilazione (ovvero il (o i) computer su cui eseguiremo i vari "make", "rpmbuild",ecc.). Da un terminale diamo:
# yum install distcc
Fatto questo dobbiamo far sapere a distcc quali sono gli host tra i quali distribuire i lavori di compilazione; per far questo è sufficiente indicare nel file /etc/distcc/hosts i relativi indirizzi ip. Continuando con il nostro esempio il nostro file hosts sarebbe così composto:
192.168.1.1 192.168.1.2
Non occorre specificare la porta se i nostri server girano su quella di default; in caso contrario è invece necessario specificarla con la sintassi [host]:[port], ad esempio:
192.168.1.1:1234 192.168.1.2:1234
All'interno sempre dello stesso file è inoltre possibile indicare alcune opzioni che permettono di modificare il comportamento di distcc. La più interessante è a mio avviso lzo (per le altre opzioni vi rimando direttamente alla lettura di man distcc) che, come intuibile, fa sì che tutti i dati vengano compressi prima di essere trasferiti da un host all'altro. Nel mio caso ho verificato che tale opzione permette un'ulteriore riduzione dei tempi di compilazione tutt'altro che trascurabile. Per attivare la compressione lzo, modificheremo il file hosts in questo modo:
192.168.1.1,lzo 192.168.1.2,lzo
Abbiamo praticamente terminato la nostra configurazione, l'unica cosa che ancora manca è quella di "legare" insieme distcc e ccache per creare un ambiente di compilazione ottimale; per far ciò ci basta la seguente istruzione:
 $ export CCACHE_PREFIX="distcc"
Vi consiglio di aggiungerla al vostro .bashrc in modo che venga eseguita automaticamente ad ogni login.
Non ci resta ora che effettuare qualche test per vedere come il nostro setup si comporta sul campo. Per misurare i tempi di compilazione possiamo usare il comando bash time:
$ time make
$ time rpmbuild -ba file.spec
Se usiamo make (come spesso avviene) per compilare un programma, è bene, per sfruttare al massimo le capacità di distcc, passare come numero di jobs la somma di tutti i demoni distccd della nostra rete. Cerco di spiegarmi meglio: abbiamo due host A e B; A è un singol core quindi può gestire al massimo n.3 processi di compilazione simultaneamente. B è invece un dual core quindi può arrivare a n.5 processi. Il valore quindi da passare a make è di 8 (3+5):
$ make -j 8
Utilizzare un numero superiore (in questo caso) ad 8 non avrebbe alcun senso, distcc automaticamente bloccherebbe le richieste eccedenti le capacità dei server.

Compilare più volte lo stesso programma provando opzioni differenti vi aiuterà a trovare la configurazione migliore per le vostre macchine. Prima di ogni test è però necessario pulire la cache di ccache, altrimenti i risultati dei vostri test risulterebbero completamente falsati.
Ccache permette infatti di ricompilare in maniere estremamente rapida un pacchetto compilato almeno già una volta, grazie alla sua capacità di memorizzazione dei risultati delle compilazioni precedenti. Questa feature utilissima va però "disattivata" in questo caso, pena avere dei risultati del tutto inaffidabili.
Ci basterà prima di ogni compilazione azzerare la cache con:
 $ ccache -C
Per monitorare in tempo reale l'avanzamento della compilazione e i trasferimenti dati tra le macchine possiamo lanciare distccmon-gnome o distccmon-text dall'host client.

Edit: alcuni tips&tricks
Nel file .rpmmacros nella vostra home è possibile impostare il numero di jobs predefinito che rpmbuild dovrà usare nella creazione dei pacchetti rpm: è sufficiente inserire il valore desiderato in corrispondenza del campo %_smp_mflags, ad esempio:
%_topdir %(echo $HOME)/rpmbuild
%_smp_mflags    -j12
...
Se desiderate eseguire una particolare compilazione senza l'uso di distcc vi basta "annullare" la variabile CCACHE_PREFIX impostata in precedenza:
$ env -u CCACHE_PREFIX rpmbuild -ba file.spec