Visualizzazione post con etichetta tutorials. Mostra tutti i post
Visualizzazione post con etichetta tutorials. Mostra tutti i post

14 novembre, 2007

Guitar Rig perfettamente funzionante su linux! E' possibile?

Sono un linuxaro convinto e lo uso praticamente per tutto. Una cosa ancora mi lega al dual boot con windows: i software audio! In questi giorni però ho fatto un grande passo avanti per colmare questa lacuna. Grazie a wine e a wineasio una estensione per wine che ho scoperto da poco, uno dei software ai quali tengo di più, gira perfettamente sulla mia Ubuntu Gutsy. Ho deciso quindi di postare un breve tutorial per mostrare come ottenere l'ambito risultato.
I passi da seguire sono i seguenti:

  1. Installare il software necessario alla compilazione di wineasio
  2. Scaricare e compilare wineasio
  3. Configurare wine
  4. Installare Guitar Rig
  5. Suonare con la bava alla bocca godendo come un porco nel vedere il Guitar Rig sulla nostra Ubuntu box
  6. Ripetere periodicamente il passo 5 :)
Per compilare wineasio abbiamo bisogno dei pacchetti di sviluppo di wine e di jack che sono rispettivamente, wine-dev e libjack-dev. Dopo aver installato questi pacchetti preleviamo l'ultima versione dei sorgenti di wineasio da http://people.jacklab.net/edogawa/files/wineasio/
Estraiamo i pacchetti in una directory temporanea a digitiamo il comando make. Se la compilazione non da errori possiamo installare il pacchetto con il comando:
sudo make install
Ora dobbiamo configurare wine in modo che utilizzi i driver corretti per l'audio. Prima di tutto eseguire il comando:
regsvr32 wineasio.dll

Lanciamo il comando winecfg e impostiamo i parametri per l'audio in questo modo:


Bisogna selezionare il driver jack e quello alsa. Ora avviamo jack. Quindi non ci rimane che installare il Guitar Rig e impostare come driver audio wineasio. Per ottenere migliori prestazioni è conveniente installare il kernel realtime (linux-image-rt in Gutsy).

16 settembre, 2007

Come compilare una release candidate del kernel

Ho da qualche giorno installato la gutsy aggiornando la mia perfettamente funzionante feisty e purtroppo il kernel 2.6.22 fornito con la gutsy mi ha dato qualche noia di non poco conto. Per qualche strano motivo, avviando il pc usando questa versione del kernel dopo qualche minuto la macchina si spegne "violentemente" come se venisse a mancare tutto ad un tratto l'alimentazione. Il problema sembra sia causato dalla gestione dell'acpi nel kernel. Infatti passando il paramentro acpi=off al boot, il problema non si pone. Ma disattivare l'acpi significa rinunciare ad alcune importanti funzionalità come ad esempio la gestione dello scaling della frequenza della cpu, funzionalità fondamentale per il mio laptop. In ogni modo ho segnalato il bug su launchpad nella speranza che venga risolto prima della release ufficiale della gutsy.

Comunque tornando all'oggetto del titolo del post, per verificare se il problema è stato risolto nella versione di sviluppo del kernel ho deciso di compilare la versione di sviluppo corrente (nel momento in cui scivo la 2.6.23rc6).

Di cosa ho bisogno?

Prima di iniziare assicurarsi di aver installato i pacchetti bulid-essential, kernel-package e fakeroot. Il primo è necessario alla compilazione vera e propria mentre gli altri due serviranno a renderci la vita un po più semplice. A questo punto occorre scaricare l'ultima versione stabile del kernel e la patch per la versione di sviluppo. Nel mio caso l'ultima versione stabile è la 2.6.22.

N.B.
La patch può essere applicata solo al ramo principale! In pratica non può essere usata ad esempio la versione 2.6.22.6 ma solo la 2.6.22.

La versione corretta da scaricare e sulla quale applicare la patch è in genere linkata a destra della patch con la lettera B.

Quindi procediamo e scarichiamo il file linux-2.6.22.tar.bz2 e la patch cioè il file patch-2.6.23-rc6.bz2

Come procedo per la compilazione?

Prima di tutto occorre estrarre l'archivio con i sorgenti del kernel e applicare la patch. Creiamo una directory nella nostra home che chiameremo tmp e estraiamo i sorgenti del kernel. A questo punto avremo la directory ~/tmp/linux-2.6.22. Decomprimiamo la patch e copiamola all'interno di ~/tmp/linux-2.6.22. Applichiamo la patch con:

patch -p1 < patch-2.6.23-rc6  
A questo punto è fortemente consigliato importare la configurazione del kernel correntemente in uso o dell'ultima versione installata. Per farlo basta copiare il file

cp /boot/config-2.6.22-11-generic ~/tmp/linux-2.6.22/.config
Nel vostro caso la versione potrebbe essere differente.

A questo punto basta usare il comando:

make-kpkg --rootcmd fakeroot kernel_image

Probabilmente nella release candidate del kernel saranno state aggiunte nuove opzioni di configurazione non presenti nel file che abbiamo copiato dalla directory /boot. Per queste nuove opzioni vi verranno poste delle domande. In genere se non si hanno esigenze particolari è conveniente mantenere i valori di default.

Se tutto va a buon fine al termine dell'esecuzione del comando dovreste ritrovarvi un file .deb con il nuovo kernel pronto ad essere installato.

Nel mio caso purtroppo il problema non è stato risolto :( Non mi resta che confidare nei valorosi sviluppatori di Ubuntu.

Buona sperimentazione ;)

P.S.
Dopo aver installato il kernel è necessario generare l'immagine del disco ram iniziale con il
comando:

update-initramfs -c -k 2.6.23-rc6

e quindi aggiornare la voce relativa nel file di configurazione di grub in /boot/grub/menu.lst

In realtà quest'ultima operazione avrebbe dovuto essere automatica ma evidentemente per qualche motivo non ha funzionato.

14 maggio, 2007

Python Cairo e le glass window

Chi non conosce il lavoro di njpatel? Ormai i suoi avant window navigator e affinity sono noti ai più. Le sue idee sono innovative è apprezzate da molti bloggers. In questo post non voglio solo esaltare le sue produzioni (anche perché arriverei molto in ritardo in questo) ma voglio spingermi un po oltre per spiegare il modo di operare per ottenere risultati visivi simili ma utilizzando il nostro amato pitone.

A chi non sapesse a cosa mi riferisco, rimando a questo post sul blog di njpatel. Notate le trasperenze della finestra e gli altri widget inseriti normalmente al suo interno.

Come faccio ad ottenere un risultato simile in python?


#!/usr/bin/env python

import gtk
import cairo

if gtk.pygtk_version < (2, 10, 0):
print 'Questo esempio ha bisogno delle PyGtk >= 2.10'
raise SystemExit

def hex2float(hex):
ret = []
for i in range(4):
ic = int(hex[i])
ret.append( ic / 255.0 )
return ret


class TransparentWindow(gtk.Window):
__gsignals__ = {
'expose-event': 'override',
'screen-changed': 'override',
}

def __init__(self):
gtk.Window.__init__(self)

# Indichiamo alle GTK che vogliammo disegnare noi lo sfondo.
self.set_app_paintable(True)

# non vogliamo le decorazioni del window manager
self.set_decorated(False)

# usiamo il segnale button-press-event per permettere
# il "click e trascina" sulla finestra. Ricordiamo
# che non stiamo utilizzando i classici decoratori
# del window manager e non gestendo qeusto segnale
# non sarebbe possibile spostare la finestra
self.add_events(gtk.gdk.BUTTON_PRESS_MASK)
self.connect('button-press-event', self.on_button_press)

# Inizializziamo lo schermo
self.do_screen_changed()

def on_button_press(self, widget, event):
self.begin_move_drag(
event.button,
int(event.x_root),
int(event.y_root),
event.time)

def render_rect(self, cr, x, y, w, h, o):
# Crea un rettangolo con i bordi arrotondati
x0 = x
y0 = y
rect_width = w
rect_height = h
radius = 10 + o

x1 = x0 + rect_width
y1 = y0 + rect_height
cr.move_to(x0, y0 + radius)
cr.curve_to(x0, y0, x0, y0, x0 + radius, y0)
cr.line_to(x1 - radius, y0)
cr.curve_to(x1, y0, x1, y0, x1, y0 + radius)
cr.line_to(x1 , y1)
cr.line_to (x0 , y1)
cr.close_path()

def do_expose_event(self, event):
cr = self.window.cairo_create()

if self.supports_alpha:
cr.set_source_rgba(1.0, 1.0, 1.0, 0.0)
else:
cr.set_source_rgb(1.0, 1.0, 1.0)

cr.set_operator(cairo.OPERATOR_SOURCE)
cr.paint()


(width, height) = self.get_size()
cr.move_to(0, 0)
cr.set_line_width(1.0)

cr.set_operator(cairo.OPERATOR_OVER)

pat = cairo.LinearGradient(0.0, 0.0, 0.0, height)

ex_list = [0xA1, 0xA8, 0xBB, 0xEC]
col = hex2float(ex_list)
pat.add_color_stop_rgba(0.0, col[0], col[1], col[2], col[3])

ex_list = [0x14, 0x1E, 0x3C, 0xF3]
col = hex2float(ex_list)
pat.add_color_stop_rgba(1.0, col[0], col[1], col[2], col[3])

self.render_rect(cr, 0, 0, width, height, 10)
cr.set_source(pat)
cr.fill()

# bordo luminoso
ex_list = [0xFF, 0xFF, 0xFF, 0x4e]
col = hex2float(ex_list)
cr.set_source_rgba(col[0], col[1], col[2], col[3])
self.render_rect(cr, 1.5, 1.5, width - 3 , height - 3, 10)
cr.stroke()

# bordo
ex_list = [0x00, 0x15, 0x1F, 0xe0]
col = hex2float(ex_list)
cr.set_source_rgba(col[0], col[1], col[2], col[3])
self.render_rect(cr, 0.5, 0.5, width - 1 , height - 1, 10)
cr.stroke()

ex_list = [0xFF, 0xFF, 0xFF, 0xFF]
col = hex2float(ex_list)
cr.set_source_rgba(col[0], col[1], col[2], col[3])
self.render_rect(cr, 0, 0, width , height, 10)
cr.stroke()

pat = cairo.LinearGradient(0.0, 0.0, 0.0, height)
cr.set_source(pat)
ex_list = [0xFF, 0xFF, 0xFF, 0xbb]
col = hex2float(ex_list)
pat.add_color_stop_rgba(0.0, col[0], col[1], col[2], col[3])

ex_list = [0x00, 0x00, 0x10, 0xaa]
col = hex2float(ex_list)
pat.add_color_stop_rgba(0.2, col[0], col[1], col[2], col[3])
self.render_rect(cr, 0, 0, width, 20, 10)
cr.fill()

# chiediamo esplicitamente ai figli di disegnarsi
# Se non lo facessimo non sarebbero visualizzati
# i widgets aggiunti alla TransparentWindow
children = self.get_children()
for c in children:
self.propagate_expose(c, event)

def do_screen_changed(self, old_screen=None):
screen = self.get_screen()
if self.is_composited():
print 'Il tuo schermo supporta il canale alpha!'
colormap = screen.get_rgba_colormap()
self.supports_alpha = True
else:
print 'Il tuo schermo non supporta il canale alpha! Il composite\
manager e\' attivo?'
colormap = screen.get_rgb_colormap()
self.supports_alpha = False
self.set_colormap(colormap)

class CoolAlpha:
def __init__(self):
window = TransparentWindow()
window.resize(400, 400)
eb = gtk.EventBox()
eb.set_visible_window(False)
eb.set_border_width(12)
window.add(eb)

main_box = gtk.VBox(False, 12)
eb.add(main_box)

hbox = gtk.HBox(False, 6)
main_box.pack_start(hbox, False)

button = gtk.Button()
button.set_relief(gtk.RELIEF_NONE)
button.connect("clicked", gtk.main_quit)
icon_box = gtk.HBox(False, 0)

image = gtk.Image()
image.set_from_stock(gtk.STOCK_CLOSE,
gtk.ICON_SIZE_MENU)
icon_box.pack_start(image, False)
button.add(icon_box)
hbox.pack_end(button, False)

sw = gtk.ScrolledWindow()
sw.set_property("border-width", 20)
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.textview = gtk.TextView()
self.textview.set_editable(False)
self.textview.set_cursor_visible(False)
sw.add(self.textview)
main_box.pack_start(sw, True)

window.show_all()

def set_text(self, text):
buf = self.textview.get_buffer()
buf.set_text(text)

if __name__ == '__main__':
a = CoolAlpha()
a.set_text("prova")
gtk.main()

Questo esempio è in gran parte una traduzione del codice in linguaggio c di affinity di njpatel con qualche piccolo ritocco da parte mia come l'inclusione del pulsante di chiusura in alto a destra e la textview centrale. Eseguendo l'esempio otterrete:

In genere le gtk non vengono usate per costruire finestre troppo "esotiche" e c'è un buon motivo per questo, ovvero mantenere la consistenza delle applicazioni sul desktop. Quindi nonostante queste finestre possono apparire molto belle a vedersi, il mio consiglio e di non abusarne ma utilizzarle in modo da ottenere una buona integrazione con il resto del desktop per non fare apparire la nostra applicazione come un "alieno".

13 maggio, 2007

Vmware Server su Ubuntu Feisty

Vi piace provare le nuove distro magari in beta o volete fare sperimentazioni di programmazione in rete ma non avete a disposizione i pc per farlo? La soluzione c'è e si chiama virtualizzazione. Vmware server è un software gratuito (non open source purtroppo) che dalla versione feisty è impacchettato e disponibile nei repository di software commerciale di canonical.

Installazione
Per installare vmware server è necessario prima di tutto abilitare i repository "non liberi" di canonical:

deb http://archive.canonical.com/ubuntu feisty-commercial main"
Per farlo è possibile utilizzare synaptic o editare manualmente il file /etc/apt/sources.list
A questo punto è possibile installare il software usanto il comando:
sudo apt-get install vmware-server
L'installazione vi richiederà un codice di attivazione che potete ottenere gratuitamente sul sito di vmware

18 aprile, 2007

Un processore di effetti di chitarra su Ubuntu

Oltre ad essere un utente ubuntu sono anche un discreto chitarrista. Una delle cose che di più mi manca su Ubuntu è un programma di emulazione di amplificatori in grado di permettermi di sfruttare la mia M-Audio Fast Track (lo so che c'è di meglio ma per divertirsi va più che bene) perfettamente riconsciuta da Ubuntu.

Stasera ho deciso di vedere che cosa è in grado di fare la mia linux box nell'ambito dell'effettistica realtime.

Installiamo il necessario
Prima di tutto ho installato il kernel a bassa latenza presente nei repository Ubuntu (linux-image-2.6.20-15-lowlatency). Quando si parla di audio su linux viene subito da pensare al server audio jackd. Questo server per poter avere buone prestazioni in realtime, ha bisogno di alcuni accorgimenti particolari. Infatti è necessario compilare un apposito modulo per il kernel: non lasciatevi intimidire, non è poi cosi difficile. Vediamo come fare. Prima di tutto vi consiglio di installare il pacchetto module-assitant che vi risparmierà un sacco di noie e alla fine produrrà un bel pacchetto deb con ciò di cui abbiamo bisogno.
Prima di procedere è consigliabile riavviare con il kernel lowlatency.

Quindi installiamo il pacchetto realtime-lsm.
A questo punto andiamo a compilare il nostro modulo (assicuratevi di essere ancora connessi ad internet):

$ sudo m-a a-i realtime-lsm
Questo comando scaricherà dalla rete tutto ciò di cui avrà bisogno per compilare il modulo e per costruire il pacchetto .deb. Alla fine dell'operazione installerà automaticamente il pacchetto con il modulo.
E' arrivato il momento di testare il modulo realtime:
$ sudo modprobe realtime any=1
Se il comando dovesse dare degli errori durante il caricamento provate a riavviare (a me è successo e riavviando ho risolto).

Se l'operazione è andata a buon fine possiamo procedere ad installare gli altri pacchetti: jackd, jack-rack, qjackctl, caps.

Siamo finalmente pronti a testare il nostro processore di effetti.
Lanciamo qjackctl ed impostiamo i parametri per il demone jackd (non dimentichiamoci di attivare l'opzione realtime naturalmente). Quindi lanciamo jack-rack e dopo aver fatto le opportune connessioni attraverso qjackctl possiamo caricare gli effetti. I simulatori di amplificatori, di cabinets, di preamplificatori etc si trovano dal pulsante Aggiungi->Uncategorised->C di jack-rack.

Impressioni d'uso
Giocando con le varie impostazioni si riescono ad ottenere alcuni suoni che non sono malaccio anche se non posso dire che siano pienamente soddisfacenti. Altra nota dolente è che sul mio centrino a 1.5 Ghz non riesco a caricare più di 3 o 4 moduli contemporaneamente in jack-rack. In ogni modo mi sento di consigliarvi di provarli anche solo per il gusto di vedere la vostra chitarra processata da software open source :)

03 aprile, 2007

Catturiamo il SIGTERM con python

Scrivendo una applicazione a volte è necessario compiere delle operazioni di "pulizia" prima che questa venga chiusa. A volte è necessario compierle anche se l'applicazione viene uccisa con kill.

Il comando kill

Il comando Kill serve per inviare dei segnali ad un processo. Utilizzato senza opzioni e con parametro un pid di un processo (che possiamo trovare utilizzando il comando ps), kill invia a tale processo il segnale SIGTERM che in genere indica al processo di terminare le sue operazioni. Esistono molti altri segnali ma in questo post ci occuperemo solo del SIGTERM.

Il modulo signal

Per la gestione dei segnali python mette a disposizione il modulo signal. Una delle funzioni più importanti presenti in questo modulo è la signal(). Questa funzione permette di registrare un handler per un particolare segnale.

Esempio


import signal
import sys
import time

def sigterm_handler(signum, frame):
print "SIGTERM catturato"
sys.exit(0)

signal.signal(signal.SIGTERM, sigterm_handler)

while (1):
sys.stdout.write(".")
sys.stdout.flush()
time.sleep(1)

Questo esempio continua a stampare "." fin quando non cattura il segnale SIGTERM inviato con una kill pid. A questo punto stampa il messaggio che indica che il segnale è stato catturato ed esce

11 marzo, 2007

Una classe per le notifiche con python e dbus

Ogni tanto trovo un minuto per migliorare il mio progetto planimo ed imparo qualcosa di nuovo su python e le varie estensioni. In un prossimo post vi annuncerò le grandi novità del progetto ma per ora vi voglio presentare un metodo semplice per far apparire le notifiche sul nostro desktop (solo unixes, no Windows). La notifica sarà simile a questa:


La notifica apparirà in basso a destra sul desktop per un periodo di tempo impostabile.
Dbus è un sistema per la comunicazione tra processi. In pratica si sfrutterà dbus per comunicare con il demone delle notifiche.

Il codice python



import dbus

ICON = "file:///home/redgun/python/planimo/data/icons/planimo48.png"

class Notifier:
def __init__(self):
self.session_bus = dbus.SessionBus()
obj = self.session_bus.get_object("org.freedesktop.Notifications",
"/org/freedesktop/Notifications")
self.notif = dbus.Interface(obj, "org.freedesktop.Notifications")

def notify(self, title, message, iconfile = ICON, time = 3000):
try:
self.notif.Notify("Notification",
dbus.UInt32(0), iconfile, title, message,
[], [], dbus.Int32(time), dbus.UInt32(0))
except:
try:
self.notif.Notify("Notification",
dbus.UInt32(0), iconfile, title, message,
[], [], dbus.Int32(time))
except Exception, detail:
print detail

if __name__ == "__main__":
n = Notifier()
n.notify("Titolo", "messaggio stile bold", time=5000)


Per far funzionare questo codice è necessario che il pacchetto python-dbus sia installato sul vostro sistema (Ubuntu lo installa per default). Il metodo notify prova ad invocare il metodo self.notif.Notify in due modi diversi a causa di una modifica delle api della libnotify (vedi qui per maggiori info). Il primo metodo infatti funziona su Ubuntu Edgy, il secondo sulla Feisty. Il parametro time server per impostare la durata in millisecondi della notifica.

07 marzo, 2007

Comunicazioni sicure: Il tunnell ssh e l'X Forwarding

Molte applicazioni che utilizzano il protocollo TCP per le connessioni, possono essere canalizzate in un tunnel sicuro grazie all'ausilio di OpenSSH.
Ciò significa che tutto il traffico di rete generato da queste applicazioni verrà crittografato e quindi reso sicuro dagli strumenti di OpenSSH. Affinché ciò sia possibile è necessario che sull'host remoto sia in esecuzione il servizio ssh. Su ubuntu basta installare il pacchetto openss-server.

Esempi di connessioni che possono essere canalizzate sono http, smtp, pop3 ed in particolare le connessioni agli X servers.


Esempi

Connessione sicura ad un server di database postgresql

Per default il servizio postgre è in ascolto sulla porta 5432. Supponiamo che il servizio risieda sull'host pippo e che l'utente tizio abbia un account sulla macchina pippo.
Allora è possibile creare un tunnel sicuro in questo modo:

$ ssh -L 5500:pippo:5432 tizio@pippo
$ psql -h localhost -p 5500 utente_postgres

Il primo comando crea il tunnell ssh associando la porta remota 5432 alla porta locale (scelta da noi a piacimento) 5500 utilizzando l'account tizio per effettuare il login sulla macchina pippo. A questo punto si usa il secondo comando per connettersi alla estremità locale del tunnell. psql è il client testuale fornito con l'installazione di postgreSQL.

Connessione remota e X Forwarding

Un altro uso molto utile del tunnell ssh è l'X Forwarding.
L'X Forwarding è un meccanismo che permette di visualizzare una applicazione grafica eseguita su un server remoto, in locale. Per abilitarlo è necessario utilizzare l'opzione -X per ssh. Ad esempio:

$ ssh -X tizio@pippo
$ firefox

Il primo comando ci permette di loggarci sull'host pippo tramite l'account tizio abilitando l'X Forwarding. Il secondo comando lancia il browser firefox che sarà eseguito sull'host pippo ma apparirà sul nostro display come se lo avessimo eseguito in locale.
Attenzione che l'opzione ForwardX11 non sia impostata a no nel file di configurazione del demone ssh sul server remoto (/etc/ssh/ssh_config) altrimenti l'X Forwarding non funzionerà!

03 marzo, 2007

Condividere la connesione ad internet con linux

In molti mi chiedono come si fa a condividere la connessione internet del proprio pc linux con altri computer sulla rete locale. L'operazione non è complessa. Si possono scegliere più strade diverse:

1) Installare firestarter un tool per la gestione del firewell che ha tra le sue impostazioni una opzione per condividere la connessione ad internet

2) Procedere manulamente con i tools messi a disposizione dalla distribuzione.

Io sconsiglio la prima soluzione perché si impara poco ed inoltre installare un intero programma solo per condividere la connessione ad internet non è molto conveniente.

Procediamo quindi per la seconda via. Supponiamo che il nostro pc che è connesso ad
internet abbia due interfacce di rete (o comunque una interfaccia ethernet ed una interfaccia PPP che rappresenta la connessione ad internet): la prima eth0 connessa ad internet e la seconda eth1 connessa alla rete locale. Consideriamo sulla eth1 un indirizzo ip 192.168.100.1. (Per impostare questo indirizzo basta usare il comando

$ sudo ifconfig eth1 192.168.100.1 up

)

Per condividere la connessione ad internet è necessario abilitare il forwarding ed il masquerading sull'interfaccia di rete in questo modo:


$ sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
$ sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"

Naturalmente eth0 va sostituito con il nome dell'interfaccia connessa ad internet.
Ora non resta che aggiungere alla tabella di routing dei clients (gli altri pc della rete che devono accedere ad internet tramite la connessione del computer che abbiamo appena configurato) come default gateway il pc connesso a interntet. Per farlo bisogna usare
i seguenti comandi:

$ sudo ifconfig eth0 192.168.100.x
$ sudo route add default gw 192.168.100.1

Il primo comando assegna un indirizzo ip alla scheda di rete (sostituite la x con un numero diverso su ogni client). Il secondo aggiunge alla tabella di routing l'indirizzo del server come gateway.
Naturalemte i valori potete sostituirli con quelli della vostra rete ;)
Rimane ora solo da aggiungere sui clients gli ip dei server DNS. Potete usare quelli
che ci sono sul server e aggiungerli al file /etc/resolv.conf

24 febbraio, 2007

ssh: autenticazione tramite chiave pubblica

ssh (secure shell) offre vari metodi di autenticazione. La classica è quella via password ma se siete stanchi di dover immettere ogni volta che vi loggate in remoto la vostra password, un altro metodo esiste ed è pure preferibile: l'autenticazione a chiave pubblica.

In pratica basta generare una propria chiave pubblica da inserire sull'host remoto nella lista delle chiavi autorizzate ad effettuare il login.

Per generare la propria chiave pubblica basta utilizzare il comando

ssh-keygen

Questo comando genererà i due files id_rsa.pub e id_rsa nella directory .ssh nella nostra home. A questo punto basta loggarsi tramite ssh in remoto e creare il file

.ssh/authorized_keys

nella nostra home remota. In questo file bisogna copiare (o aggiungere) il contenuto del file id_rsa.pub

A questo punto possiamo loggarci senza dover inserire la password :)

03 febbraio, 2007

LaTeX e i caratteri accentati

Finalmente mi sono deciso: sto imparando LaTeX. Io e i word processor come Microsoft Word o OpenOffice Writer non siamo mai andati molto d'accordo. Ho un intimo bisogno che il pc segua le regole che io gli impongo e questi programmi di solito hanno la tendenza e la presunzione di lavorare secondo delle proprie filosofie che spesso non condivido. Così dopo qualche esitazione mi son deciso ad affrontare il mostro (che poi per fortuna tanto mostro non è, anzi ...).

Uno dei primi problemi che mi son trovato ad affrontare sono le lettere accentate (le simpatiche è é ò ù ì à etc) E si perché LaTeX se non gli si da qualche dritta non sa come gestirle (o meglio le gestisce ma bisogna usare cose del tipo \`e per fare una è).

In rete si trovano vari tutorial per principianti (anche in italiano) ma purtroppo quelli che ho trovato io non tengono in considerazione che la maggior parte dei sistemi operativi moderni seri, usa la codifica utf-8 per i file di testo, che a differenza della codifica ASCII, utilizza due bytes per rappresentare un carattere e non uno. Il succo del discorso è che le soluzioni proposte nei tutorials per far "piacere" i fatidici caratteri a LaTeX non funzionano.

Vi posto qui la soluzione funzionante sulla mia ubuntu edgy:


\documentclass[12pt,a4paper,oneside,italian]{book}


\usepackage[utf8]{inputenc}
\usepackage[italian]{babel}

\begin{document}

Adesso possiamo usare tutti i caratteri accentati
èéòàìù

\end{document}
Salvate il file ad esempio come test.tex, compilate con latex test.tex ed ecco le vostre lettere accentate felicemente stampate sul file dvi :)
P.S. Imparate LaTeX se dovete scrivere qualcosa di serio, non ve ne pentirete!

29 gennaio, 2007

Demoni in python

In questo post voglio proporvi un metodo più o meno standard per scrivere processi demoni in python. Un processo demone (per chi non lo sapesse), è un processo che di solito è in esecuzione nel sistema per fornire dei servizi su richiesta all'utente o ad altri processi. Il metodo standard per demonizzare un processo, consiste nell'usare due fork (si legge in giro che due fork garantiscono la correttezza del funzionamento su tutti i sistemi unix). La fork è una chiamata di sistema unix che crea in memoria una copia esatta del processo chiamante e restituisce il pid (process id) del nuovo processo al "genitore" e zero al figlio. Andiamo a vedere il codice:


import os
import sys

class Log:
def __init__(self, logfile):
self.logfile = logfile

def write(self, data):
self.logfile.write(data)
self.logfile.flush()

def daemonize(logfile):
"""
Questa funzione fara' diventare demone il processo che la richiamera'
e redirigera' il suo standard output e standard error sul file logfile
"""
# La maschera' con la quale verranno creati gli eventuali nuovi
# files
UMASK = 0

try:
pid = os.fork()
except OSError, e:
raise Exception, "la prima fork e' fallita: %d (%s)" % \
(e.errno, e.strerror)

if (pid == 0):
os.setsid()
try:
pid = os.fork()
except OSError, e:
raise Exception, "la seconda fork e' fallita: %d (%s)" % \
(e.errno, e.strerror)

if (pid == 0):
os.chdir('/')
os.umask(UMASK)
else:
os._exit(0)
else:
os._exit(0)

sys.stdin.close()
# Redirigo standard output ed error sul log file
try:
sys.stdout = sys.stderr = Log(open(logfile, 'a+'))
except IOError, details:
raise IOError, details

return 0

Un paio di punti da notare:
  • Il secondo figlio imposta come sua directory corrente la root ("/")
  • Lo stdin viene chiuso

Per quanto riguarda il primo punto, ciò viene fatto per prevenire situazioni anomale nelle quali un filesystem non può essere smontato in quanto c'è un processo che lo impedisce. Infatti avrete notato che se apriamo una shell e ci spostiamo con il comando cd in una directory sotto un filesystem montato quest'ultimo non potrà essere smontato finché la nostra shell non "smette" di impegnarlo. Il secondo punto è un po più ovvio: un demone non deve ricevere dati dallo standard input. Probabilmente se dovrà ricevere dati userà metodi differenti, come ad esempio i sockets.

Esempio d'uso


Possiamo salvare il codice appena visto in un modulo python che chiamiamo ad esempio daemon.py per poi richiamarlo in questo modo:

from daemon import daemonize

daemonize("/var/log/mylog.log")

import time
i = 0
while 1:
print i
time.sleep(1)
i = i + 1

Se salviamo questo semplice script in, ad esempio, test.py e lo eseguiamo (da root se vogliamo usare /var/log/mylog.log oppure possiamo cambiare file di log e usare un percorso scrivibile dall'utente non privilegiato, ad esempio la nostra home), quello che otterremo sarà un bel demone in esecuzione in background che ogni secondo andrà a scrivere sul nostro file di log il valore della variabile i. Il demone rimarrà in esecuzione fin quando non lo andremo a uccidere. Per farlo dobbiamo scoprire il suo pid con ps x (l'opzione x è necessaria per vedere i parametri passati ai processi), troviamo qualcosa di simile a 65100 python test.py e lo uccidiamo con kill 65100 (sostituire 65100 con il vostro pid.

24 gennaio, 2007

Thin Clients: Periferiche locali

Come ho già spiegato in posts precedenti qui e qui con ubuntu è molto semplice installare un terminal server. Utilizzando una installazione base però non è possibile utilizzare sui thin clients le periferiche locali. Ciò significa che ad esempio se inseriamo una pennina nella porta usb del thin client o un cd non possiamo utilizzarli. Per aggiungere questo supporto è necessario seguire queste istruzioni:

  • Installare sul terminal server il pacchetto ltspfs
  • caricare il modulo fuse con sudo modprobe fuse (aggiungerlo al file /etc/modules per far si che venga caricato ad ogni avvio del server)
  • Abilitare ltspfsd sui terminali aggiungendo LOCAL_STORAGE = Y al file di configurazione dei thin clients lts.conf

Se questo file non esiste in /opt/ltsp/i386/etc, ammesso che l'ambiente chroot dei thin clients si trovi in /opt/ltsp/i386, provvedere a crearlo manualmente con questo contenuto:

[default]
LOCALDEV=Y

Come funziona?

I thin clients a questo punto avranno in esecuzione il demone ltspfsd che si occuperà di esportare al server le periferiche che vengono inserite localmente. Non appena una periferica viene inserita, udev (sul thin clients) avvierà lo script /lib/udev/add_fstab_entry nell'ambiente chroot il quale richiama a sua volta /usr/sbin/ltspfsmounter sul server tramite ssh. Quest'ultimo si preoccuperà di montare il filesystem esportato da ltspfsd, nell'ambiente chroot in modo da renderlo disponibile ai thin clients.

09 gennaio, 2007

Python: Udp broadcasting

Oggi voglio riportarvi un esempio di come funziona e come si implementa il broadcast dei pacchetti in python. Prima di iniziare, ricordo a chi non lo sapesse che oltre ai socket TCP (SOCK_STREAM) i quali garantiscono (usando il protocollo tcp) che i dati che vengono trasmessi arrivano correttamente a destinazione, esistono i socket udp (SOCK_DGRAM) i quali non danno nessuna garanzia (esistono anche altri tipi di socket di cui non ci preoccuperemo in questo post). I socket tcp non permettono il broadcast in quanto sono socket basati sulla connessione. Quelli udp invece consentono il broadcast perché sono connection-less. Vi riporto ora un esempio davvero semplice di un broadcast server e di un client che riceve informazioni dal server.

#server

PORT = 50000

import sys, time
from socket import *

s = socket(AF_INET, SOCK_DGRAM)
s.bind(('', 0))
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)

while 1:
try:
data = repr(time.time())
# non funziona se non c'e' un default
# routing

#s.sendto(data, ('<broadcast>', PORT))

# se invece specifico un indirizzo di
# broadcast funziona
s.sendto(data, ('192.168.0.255', PORT))

time.sleep(2)
except KeyboardInterrupt:
sys.exit(0)


Come potete vedere il codice del server è molto banale. In pratica non fa altro che mandare in broadcast ogni 2 secondi il tempo misurato dal sistema. Notiamo che stiamo usando i datagram sockets e li abbiamo messi in modalità broadcast con
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)

A questo punto notate il commento sull'istruzione che usa <> come indirizzo al quale inviare i dati. Sul manuale di python questo non è specificato ma è così. Se vogliamo che i dati vengano ricevuti dal client dobbiamo specificare l'indirizzo di broadcast corretto.
Vediamo ora il codice del client:

import sys
from socket import *

PORT = 50000

s = socket(AF_INET, SOCK_DGRAM)
s.bind(('', PORT))
while 1:
try:
data, fromaddr = s.recvfrom(1024)
print (data, fromaddr)
except KeyboardInterrupt:
sys.exit(0)
Come possiamo notare il client non conosce a priori l'indirizzo del server ma riceve semplicemente i dati. Ricordiamoci comunque che il protocollo udp non garantisce nulla sulla consegna degli stessi. Quindi è possibile che ciò che invia il server non arrivi correttamente a destinazione

21 dicembre, 2006

Ltsp 4.2

Ltsp (linux terminal server project) è un progetto che permette di utilizzare vecchi computer anche senza disco e con poca ram come terminali in grado di connettersi ad un server (terminal server) e di avviarsi via rete. Il server compie tutte le operazioni "costose " in termini di processore e di ram ed il client semplicemene visualizza il risultato. E' possibile avviare intere sessioni di X compreso gnome, openoffice, firefox e tutto il resto utilizzando questo sistema. In questo post spiegherò passo passo come fare ad installare un terminal server utilizzando la versione 4.2 di ltsp. In un prossimo post vi spiegherò come installare la nuova versione presente anche nei repository ubuntu e le differenze con la 4.2.

Di cosa ho bisogno?

Prima di procedere è necessario scaricare dal sito ufficiale di ltsp http://wiki.ltsp.org/twiki/bin/view/Ltsp/LTSP-42 il pacchetto ltsp-utils_0.25_all.deb che è l'ultima versione nel momento in cui sto scrivendo questo post. Installiamo il pacchetto con:

sudo dpkg -i ltsp-utils_0.25_all.deb
Quindi installiamo tutti gli altri pacchetti necessari direttamente dal repository ubuntu:
  • dhcp3-server
  • dhcp3-common
  • tftpd-hpa
  • nfs-kernel-server
  • xinetd
  • libwww-perl

Installazione

Dopo aver installato tutti i pacchetti necessari, lanciamo da root il comando ltspadmin Seguiamo il wizard fino alla fine. Un altro comando utile è ltspcfg che ci permette do controllare lo stato dei servizi necessari e di impostare la configurazione di base. Assicuriamoci che le impostazioni della rete e i percorsi siano corretti nel file di configurazione del server dhcp /etc/dhcp3/dhcpd.conf. A questo punto dobbiamo assicurarci che tutti i servizi siano attivi. Quindi attiviamo il server dhcp, il servizio portmap necessario ad nfs, nfs. Per abilitare il servizio tftp creiamo il file /etc/xinet.d/tftp con questo contenuto:
service tftp
{
disable = no
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -s /tftpboot
}

e riaviamo il servizio xinet.
Dobbiamo abilitare inoltre il servizio xdmcp. Per farlo se usiamo gdm dobbiamo editare il file /etc/gdm/gdm.conf cercare la sezione [xdmcp] e impostare enable su true. Quindi riavviamo gdm.

Come avviene il boot?

Di seguito spiegherò come avviene il boot usando il PXEclient della scheda di rete. Il client cerca un server dhcp nella rete. Il server dhcp oltre a fornire un ip al client, gli fornisce alcuni parametri necessari per effettuare il boot. Tra questi c'è un root-path che vedremo dopo a cosa serve, e il percorso al linux loader pxelinux. A questo punto il client carica il piccolo loader il quale a sua volta carica il kernel linux. I parametri del loader si trovano nel file /tftpboot/lts/[versione-kernel]/pxelinux.cfg/default Tra i parametri abbiamo root=/dev/ram0 e initrd=initramfs.gz. Ciò significa che non appena il kernel ha finito di avviarsi carica il il file initramfs.gz in ram, lo decomprime (è un archivio cpio compresso con gzip) e lancia il file linuxrc o init. In questo caso non essendo presente il file linuxrc lancia init che è uno script shell. Per vedere il contenuto di questo script bisogna decomprimere l'archivio in questo modo:
* gunzip initramfs.gz
* cpio -i -d -I initramfs
L'ultimo comando ricostrurà un albero delle directory stile unix. Lo script init presente nella radice dell'albero oltre ad altre operazioni, cerca per vedere se l'opzione root-path è stata fornita dal server dhcp, dando un errore altrimenti. Se l'opzione è presente e sia ad esempio:
option root-path              "192.168.50.1:/opt/ltsp/i386";
il percorso specificato verrà montato via nfs e dopo qualche altro comando, la directory sulla quale è stato montato diventerà la nuova root.

A questo punto il file importante è /opt/ltsp/i386/etc/lts.conf che nel mio caso è sotto la forma:
[Default]
SERVER = 192.168.50.1
XSERVER = auto
X_MOUSE_PROTOCOL = "PS/2"
X_MOUSE_DEVICE = "/dev/psaux"
X_MOUSE_RESOLUTION = 400
X_MOUSE_BUTTONS = 3
USE_XFS = N
SCREEN_01 = startx
SCREEN_02 = shell
In pratica questo file viene utilizzato dallo script /opt/ltsp/i386/etc/rc.sysinit per lanciare il server X (client per l'xdmcp che gira sul terminal server) o una sessione telnet o altro. Nel mio caso ho aggiunto la variabile SCREEN_02 = shell che lancia una shell (busybox) direttamente sul thin client (non associata in alcun modo al terminal server). In questo modo su un terminale virutale ho la shell e sull'altro il server x
I valori associati alle variabili SCREEN sono degli script presenti nella directory /opt/ltsp/i386/etc/screen.d/

13 novembre, 2006

Bridge di rete

Mi è capitata la seguente situazione:

  1. 2 desktop con una scheda di rete ethernet ciascuno che chiameremo
    desk1 e desk2
  2. 1 desktop con 2 schede di rete rispettivamnete desk3.
I pc devono essere tutti e tre collegati in rete. Non avevo
a disposizione un hub ma solo un cavo incrociato.

Soluzione

E' possibile usare un bridge di rete.
Colleghiamo il desk1 e desk2 a desk3 con la connessione ethernet.
A questo punto la situazione è la seguente:

+--------------------+
| |
| desk1 |
| |
+--------------------+
| eth0
|
|
| eth0
+--------------------+
| |
| desk3 |
| |
+--------------------+
| eth1
|
|
| eth0
+--------------------+
| |
| desk2 |
| |
+--------------------+

Non ci resta che creare il bridge ed assegnare gli indirizzi ip.
Prima di procedere verificate di avere installato il pacchetto
bridge-utils.

Da eseguire su desk3

creo l'interfaccia del bridge
sudo brctl addbr br0

aggiungo al bridge le due interfacce di rete
sudo brctl addif br0 eth0
sudo brctl addif br0 eth1

azzero gli ip delle interfacce del bridge
sudo ifconfig eth0 down
sudo ifconfig eth1 down
sudo ifconfig eth0 0.0.0.0 up
sudo ifconfig eth1 0.0.0.0 up

assegno un indirizzo ip all'interfaccia del bridge
sudo ifconfig br0 192.168.60.1

Il bridge ora è impostato è dovrebbe essere funzionante.
Naturalmente potete utilizzare un altro indirizzo ip per il vostro
bridge ;)
Non ci rimane che assegnare un indirizzo ip ai pc desk1 e lap2.

Da eseguire su desk1

sudo ifconfig eth0 192.168.60.10

Ora desk1 è ok. Rimane da impostare desk2:

Da eseguire su desk2

sudo ifconfig eth0 192.168.60.20

A questo punto dovrebbe essere possibile pingare uno dei pc
da qualsiasi altro :)

23 ottobre, 2006

Reti wireless Ad-Hoc (da computer a computer)

Supponiamo di voler creare una rete wireless tra due o più

pc senza un access point in Ubuntu Edgy Eft (vale anche per Dapper).
Avendo installato Network-Manager mi aspetterei di poterlo
fare cliccando sull'icona sul pannello di gnome e selezionando
Crea nuova rete wireless ma purtroppo almeno nel mio caso
la procedura sembra non andare a buon fine.

Spulciando tra i manuali delle wireless utilities ho trovato il modo
di procedere manualmente.

Allora prima di ogni altra cosa bisogna impostare la nostra
schedadi rete wireless in modalità ad-hoc (la modalità in
cui si trova all'avvio, di solito è managed che serve per
connettersi ad un access point)

Nei comandi che seguono eth1 va sostituito con la vostra
scheda di rete wireless. Se non sapete qual'è, lanciate iwconfig
senza opzioni, sarà quella con le estensioni wireless ;)

Impostiamo la scheda in modalità ad-hoc

sudo iwconfig eth1 mode ad-hoc


A questo punto impostiamo il nome della rete wireless
Se la rete la state creando voi, potete sceglierne uno a vostro
piacimento. Per impostarlo

sudo iwconfig eth1 essid nome-scelto-da-me


se vogliamo un po di sicurezza in più (consigliato vivamente)
possiamo abilitare la crittografia sul traffico di rete in questo modo:

sudo iwconfig eth1 key on
sudo iwconfig eth1 key s:0123456789ABC


Il secondo comando assegna una password in ascii.
La password è ciò che segue s:
Deve essere di 13 caratteri. Per ulteriori opzioni si rimanda
al manuale di iwconfig.

Nel mio caso ho riscontrato problemi se non assegnavo anche un
canale wireless quindi

sudo iwconfig eth1 channel 1


A questo punto la rete dovrebbe essere attiva e funzionante.
Non rimane che assegnare un ip alla scheda di rete

sudo ifconfig eth1 192.168.0.1 netmask 255.255.255.0 up