30 novembre, 2006

Samba: condividere files senza password

Come si fa a condividere files con samba senza password? Cioè fare in modo, ad esempio, che ad un utente windows quando prova ad accedere ai files condivisi non gli venga chiesto uno username ed una password?

La risposta è semplice. Bisogna editare il file di configurazione di samba /etc/samba/smb.conf, cercare l'opzione security ed impostarla a share

A questo punto basta condividere i files con il tool messo a disposizione da Ubuntu (cioè cliccando con il tasto destro su una cartella e scegliendo l'opzione Condividi cartella, oppure dal menu del pannello Sistema->Amministrazione->Cartelle condivise)
e quindi riavviare samba

Se vogliamo procedere a manina, sempre dal file di configurazione di samba possiamo aggiungere le varie sezioni. Esempio:

[shared]
path = /home/shared
guest ok = yes


28 novembre, 2006

Threads e gui pygtk: Soluzione definitiva

Se avete letto questo post vi avevo spiegato come usare
gtk.gdk.threads_init(), gtk.gdk.threads_enter() e
gtk.gdk.threads_leave().
Nel post successivo vi ho spiegato che quell'approccio però
penalizza la portabilità su windows. Ora per rendere il nostro codice
portabile potremmo utilizzare due diverse soluzioni. La prima che vi
propongo la mostro solo per completezza ma la sconsiglio e poi vi
spiegherò perché. La seconda è invece la più sicura ed è garanzia
di funzionamento anche in situazioni con più threads attivi.
Allora la prima soluzione consiste nell'eseguire le funzioni che danno
problemi con una gobject.idle_add() e "circondare" il main
con gtk.gdk.threads_enter() e gtk.gdk.threads_leave()
Il codice diventa (date uno sguardo qui per capire le differenze):


import threading
import time
import gtk
import gobject


gtk.gdk.threads_init()



class MyThread(threading.Thread):
def __init__(self, pbar):
self.pbar = pbar
self.stop = False
threading.Thread.__init__(self)

def run(self):
t = 0
while not self.stop :
gtk.gdk.threads_enter()
# uso la idle_add
gobject.idle_add(self.pbar.set_fraction, t)
gtk.gdk.threads_leave()

t = t + 0.1
if t > 1.0:
t = 0.0

time.sleep(0.5)


def exit(arg):
th.stop = True
gtk.main_quit()

window = gtk.Window()
pbar = gtk.ProgressBar()
window.add(pbar)
window.show_all()

window.connect('destroy', exit)


th = MyThread(pbar)
th.start()

gtk.gdk.threads_enter()
gtk.main()
gtk.gdk.threads_leave()

Questo codice funziona anche su windows ma se i threads iniziano a diventare tanti ( ma non solo ) spesso si hanno dei problemi. Quindi se non volete impazzire vi consiglio vivamente questa seconda soluzione che consiste nell'evitare come la morte le varie threads_enter, threads_leave e init_threads e fare in modo che tutte le operazioni che hanno a che fare con le gtk vengano eseguite dallo stesso thread. L'esempio precedente può essere riscritto in questo modo:

import threading
import time
import gtk


class MyThread(threading.Thread):
def __init__(self, main):
self.main = main
threading.Thread.__init__(self)

def run(self):
while not self.main.stop :
self.main.pbar_fraction += 0.1
if self.main.pbar_fraction > 1.0:
self.main.pbar_fraction = 0.0

time.sleep(0.5)

class Main:
def __init__(self):
self.pbar_fraction = 0
self.stop = False

window = gtk.Window()
self.pbar = gtk.ProgressBar()
window.add(self.pbar)
window.show_all()
window.connect('destroy', self.exit)

th = MyThread(self)
th.start()

self.main_loop()

def exit(self, arg):
self.stop = True

def main_loop(self):
while not self.stop:
self.pbar.set_fraction(self.pbar_fraction)
while gtk.events_pending():
gtk.main_iteration()
time.sleep(0.01)

Main()

Come vedete non abbiamo usato neppure il gtk.main() e
il gtk.main_quit() ma facciamo tutto da noi ;)
Questo codice è portabile, funzionante e non vi farà imprecare :)

27 novembre, 2006

Problema con gtk.gdk.threads_init()

Purtroppo la descrizione dell'utilizzo di questa funzione che ho fatto precedentemente sul blog sembra non funzionare sulla versione windows di python e delle pygtk.Il problema è che non appena si incontra la funzione gtk.gdk.threads_init(), il programma su windows si blocca e non c'è verso di farlo continuare. Purtroppo così i programmi scritti in pygtk perdono la loro caratteristica di portabilità.

Aggiornamento: qui propongo una soluzione

23 novembre, 2006

Threads e gui pygtk in python

Se vi è capitato di programmare con le gtk in python (e non solo) utilizzando i threads, vi sarete accorti che spesso vengono fuori problemi.

Perchè quel maledetto thread non riesce ad aggiornare la gui?

Facciamo un semplice esempio per capirci meglio.


import threading
import time
import gtk

class MyThread(threading.Thread):
def __init__(self, pbar):
self.pbar = pbar
self.stop = False
threading.Thread.__init__(self)

def run(self):
t = 0
while not self.stop :
self.pbar.set_fraction(t)

t = t + 0.1
if t > 1.0:
t = 0.0

time.sleep(0.5)


def exit(arg):
th.stop = True
gtk.main_quit()

window = gtk.Window()
pbar = gtk.ProgressBar()
window.add(pbar)
window.show_all()

window.connect('destroy', exit)

th = MyThread(pbar)
th.start()

gtk.main()


Questo semplice programma non fa altro che creare una finestra gtk, aggiungergli un widget progressbar e creare un thread che aggiorna il progresso ogni mezzo secondo. Beh se provate ad eseguirlo, la finestra con la progress bar verrà creata ma non ci sarà alcun aggiornamento.

Il problema sta nel fatto che il thread, prova ad operare sull'oggetto gtk. Per fare ciò le librerie gtk prevedono una procedura particolare.
Prima di tutto va richiamata la funzione gtk.gdk.threads_init() prima della chiamata a gtk.main(). Poi ogni volta che si vuole accedere ad un oggetto gtk vanno usate le due funzioni:
gtk.gdk.threads_enter()
gtk.gdk.threads_leave()
Il codice corretto quindi è:

import threading
import time
import gtk

# chiamo threads_init()
gtk.gdk.threads_init()

class MyThread(threading.Thread):
def __init__(self, pbar):
self.pbar = pbar
self.stop = False
threading.Thread.__init__(self)

def run(self):
t = 0
while not self.stop:
# threads_enter
gtk.gdk.threads_enter()
self.pbar.set_fraction(t)
# threads_leave
gtk.gdk.threads_leave()

t = t + 0.1
if t > 1.0:
t = 0.0

time.sleep(0.5)


def exit(arg):
th.stop = True
gtk.main_quit()

window = gtk.Window()
pbar = gtk.ProgressBar()
window.add(pbar)
window.show_all()

window.connect('destroy', exit)

th = MyThread(pbar)
th.start()

gtk.main()


Se lo eseguite vedrete la nostra progress bar finalmente in funzione!

21 novembre, 2006

Invio file su socket in python

In questo post spiegherò come è possibile inviare un file attraverso
la rete utilizzando i socket python. Quello che andremo a costruire
è un piccolo server che rimarrà in ascolto per ricevere un file che
verrà inviato da un client il quale lo preleverà dal disco rigido e lo
invierà via socket.
Ecco il codice del serverino che chiamiamo receive.py


#! /usr/bin/env/python

import socket
import sys

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', 9900))
sock.listen(1)

filename = sys.argv[1]

s, addr = sock.accept()
file = open(filename, 'wb')
while 1:
data = s.recv(1024)
if not data: break
file.write(data)
file.close()
s.close()

In pratica non fa altro che mettersi in ascolto sulla porta 9900 ed
aspettare la connessione da parte del client. Non appena il client
si connette, crea un file con il nome che gli è stato passato come
parametro e ci scrive dentro i dati inviatigli.

Vediamo ora il codice del client che chiamiamo send.py:

#! /usr/bin/env/python

import sys
import socket

filename = sys.argv[1]
host = sys.argv[2]

file = open(filename, 'rb')
sock = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
sock.connect((host, 9900))

while 1:
data = file.read(1024)
if not data: break
sock.sendall(data)
file.close()
sock.close()


Il client apre il file passatogli come primo parametro e lo invia al
server (secondo parametro).
Come si può vedere si usa una normale sendall.
La documentazione python a riguardo potrebbe essere fuorviante.
Infatti viene indicato come sendall(string[, flags])
Cioè il primo parametro viene indicato come string mentre noi
vogliamo inviare un file binario generico. In realtà il metodo
funziona comunque perché la stringa in questo caso è intesa
un po come un array di char ovvero un array di bytes ;)

20 novembre, 2006

dvd e codecs su Ubuntu Edgy Eft

Come avrete notato non è presente nativamente in Ubuntu Edgy il
supporto alla visione dei dvd criptati e ne quello per i codecs
multimediali. Ne è possibile aggiungerlo dai repository ufficiali.
Per farlo bisogna seguire questi passi:
prima di tutto accertarsi di avere installato il pacchetto totem-xine
Poi installate il pacchetto libdvdread3 da synaptic e dopo
la libreria libdvdcss con il comando:

sudo /usr/share/doc/libdvdread3/install-css.sh


Infine scaricate i codecs con:
wget -c http://www.debian-multimedia.org/pool/main/
w/w32codecs/w32codecs_20061022-0.0_i386.deb

Il codice precedente va ricomposto su un'unica linea.
Installateli con:
sudo dpkg -i w32codecs_20061022-0.0_i386.deb

17 novembre, 2006

generare html con sintassi colorata

Ho scoperto un'altra cosa sul mio editor preferito :)
Volete generare html con sintassi colorata come in questo post?
E' molto semplice. In ubuntu basta installare vim-gnome con

sudo apt-get install vim-gnome

A questo punto scrivete il vostro file nell'editor e quando avete
finito procedete da Sintassi->Converti ad HTML

Non so ancora se è possibile fare la stessa cosa con il vim classico
(quello da console).
Ne sapete qualcosa?

Aggiornamento: Si è possibile farlo anche con il vim da console usando il comando :TO
Ringrazio l'anonimo che lo ha suggerito in un commento a questo post

15 novembre, 2006

Parametri script shell

Come si gestiscono le opzioni passate ad uno script shell?
Be prima di tutto distinguiamo tra opzioni senza parametro
e opzioni con parametro.
Esempio:

opzioni senza parametro

./script -a -b

opzioni con parametro

./script -c ciao -d ok

Un metodo per processare queste opzioni è il seguente:

#! /bin/sh

A=false
B=false
C=""
D=""
while true; do
case "$1" in
-a)
A=true
shift
;;
-b)
B=true
shift
;;
-c)
C=$2
shift 2
;;
-d)
D=$2
shift 2
;;

*)
break
;;
esac
done


In questo caso se richiamiamo ad esempio lo script in
questo modo:

./script -a -c prova


avremo che la variabile A sarà true B sarà false C prova e D la stringa
vuota.

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 :)

09 novembre, 2006

Le novità di upstart

Come saprete la nuova ubuntu edgy eft non utilizza più il vecchio
modello di avvio del sistema ma il nuovo upstart.
Upstart è un modello giovane basato sugli eventi, dinamico, adatto
alle esigenze di un desktop moderno.
Per ora in edgy l'unico vantaggio che ho notato derivato da upsart
è il fatto che il sistema si avvia più velocemente rispetto a prima.
Per il resto upstart utilizza fortemente la compatibilità con
il vecchio system-v.
Infatti quando il computer si avvia viene generato un
evento "startup". Questo evento fa scattare il gestore che si
trova in /etc/event.d/rcS il quale richiama i vecchi scripts in /etc/init.d/
Non esiste più il vecchio inittab. Se avete aggiornato da dapper
lo ritroverete ancora in /etc ma potete tranquillamente rimuoverlo.
Non mi sembra d'altro canto che ci sia un modo semplice
di impostare il runlevel di default se non editando manualmente
lo script /etc/event.d/rc-default

Purtroppo per ora la documentazione è ancora molto scarsa
e l'integrazione nel sistema allo stato primordiale, però upstart
promette bene. Credo che vedremo qualcosa di più interessante
nella prossima Feisty Fown :)

08 novembre, 2006

Il comando watch

Ho scoperto un comando che potrebbe tornare utile. Ogni tanto
capita che girando tra i forum o semplicemente dando un'occhiata
alle directory bin ci si accorge di un comando a noi sconosciuto.
watch non fa altro che eseguire il comando passatogli come
parametro periodicamente, con un periodo impostabile.

Può essere utile ad esempio per i programmi che fanno lo scan
di qualcosa. Ad esempio il comando

iwlist eth1 scan


che da come risultato le reti wireless a disposizione con relativa
potenza del segnale. eth1 naturalmente è una scheda wireless.


E' molto comodo usare watch con questo comando:

watch iwlist eth1 scan

il quale fa lo scanning periodicamente ogni 2 secondi di default.
Volendo cambiare il periodo basta aggiungere il parametro -n.
Ad esempio:

watch -n 1 iwlist eth1 scan

fa lo scanning ogni secondo.

06 novembre, 2006

Un semplice port scanner

In questo post vedremo come costruire un semplice port scanner.

Cos'è un port scanner?

E' un programmino che
controlla se ci sono delle porte aperte su un certo indirizzo ip
e se si le riporta come tali.

A cosa potrebbe servirmi un port scanner?

Ad esempio potrebbe essere un metodo veloce per scoprire
quali porte sono aperte sul nostro pc ;)

In genere una porta è associata ad un servizio e solitamente i servizi
comuni hanno delle porte standard.
Ad esempio apache porta 80, ssh porta 22 etc.
Ma come si fa per vedere se una porta è aperta?
Semplicemente si può tentare di stabilire una connessione, se si
ha successo la porta è aperta.
Per stabilire una connessione in pratica apriamo un socket tcp
su una certa porta e proviamo a conneterci.
Un numero soltanto potrebbe dirci poco o niente, quindi cerchiamo
di associare un nome di servizio al numero. Per farlo su linux ci viene
incontro il file /etc/services il quale associa ad un numero di porta
un nome di servizio. Quindi non appena riusciamo a stabilire una
connessione, andiamo a ricercare su /etc/services per vedere a
quale servizio corrisponde. Se non troviamo niente vuol dire che non
si tratta di una porta standard.
A questo punto non resta che dare uno sguardo al codice che
troverete linkato in basso a destra.

03 novembre, 2006

Ancora perplessità su sudo

Nel post precedente ho scritto di un dubbio sulla ragionevolezza della
scelta di sudo su Ubuntu e della impossibilità di loggarsi come root.
Il dubbio diventa più grande perché spunta fuori un altro problema.
Immaginiamo la configurazione seguente (che è poi la stessa
dell'altro post):

  1. una installazione di ubuntu server su una macchina che chiameremo ubuntu-server
  2. una installazione di ubuntu desktop su un
    altra macchina che chiameremo ubuntu-desktop

Vogliamo amministrare il nostro sever in remoto (per necessità
ad esempio). Sul server abbiamo alcuni files leggibili solo dall'utente
root (per motivi di sicurezza ad esempio) ma abbiamo necessità
di trasferirli sulla nostra macchina desktop per un motivo qualsiasi.

Bene! Uso scp.

Non posso! Perché dovrei dare questo comando:
scp root@ubuntu-server:nomefiledacopiare \\
percorso_su_ubuntu_desktop
il quale mi richiederebbe la password di root che non esiste! Anche
se io sono l'amministratore scp non sa che deve usare sudo!
Ora le soluzioni ci sarebbero comunque ma sono "sporche"!
Non sarebbe forse più ragionevole utilizzare sudo per
l'amminatrazione del desktop e un normale account di root
per il server?
Si lo so che è possibile attivare l'account di root su una installazione
ubuntu ma non sarebbe meglio averlo di default su una installazione
server?

02 novembre, 2006

ubuntu come server?

Quando tempo fa iniziai ad usare ubuntu, rimasi un po perplesso
della scelta di avere l'account di root disabilitato di default ma con
il passare del tempo mi sono abituato all'idea e l'ho trovata persino
ragionevole e comoda. Tutto fino a ieri quando mi è sorto un dubbio.
Chi ha letto i posts precedenti si sarà accorto che in questi giorni
sto smanettanto su vmware e ieri ho intallato la versione server di
edgy su una macchina virtuale. Configuro la rete ed installo un
server ssh. Quindi passo all'host e mi loggo sulla macchina virtuale.
Divento root con sudo su e mi si accende una lampadina in testa:
e se io creo il file /etc/nologin e perdo per un motivo qualsiasi la
connessione o dimentico di eliminarlo prima di sloggarmi?
Per chi non lo sapesse, creare il file nologin in etc serve per impedire
a chiunque se non root di loggarsi e lo si usa per svolgere compiti
amministrativi. Se non si ha accesso fisico al server non c'è modo
di riparare al guaio che io sappia. Inoltre, pur avendo l'accesso fisico,
non si può nemmeno fare un reboot o uno shutdown ma bisogna
spegnere in modo crudo.

Sbaglio qualcosa io o il dilemma esiste?