Ciascun dominio dovrebbe avere una propria struttura di directory.
Dal momento che si sta usando chroot bisognerà inserirvi
un duplicato di tutti i file necessari, come librerie condivise, file
binari, file di configurazione eccetera. Io utilizzo /virtual/domain1.com
per ciascun dominio che creo.
Tutto ciò occupa dello spazio su disco, ma è comunque meno costoso di una nuova macchina con tanto di schede di rete. Se è veramente necessario risparmiare spazio su disco, si possono collegare insieme tutte le copie dei file con degli hard link, in modo che esista effettivamente solo una copia di ogni file binario. Il filesystem che utilizzo io occupa poco più di 2Mbyte. Comunque lo script che segue tenta di copiare tutti i file dal filesystem principale in modo da essere il più generico possibile.
Ecco un esempio di semplice script virtfs:
#!/bin/sh
echo '$Revision: 1.49 $'
echo -n "Inserisci il nome di dominio: "
read domain
if [ "$domain" = "" ]
then
echo Non è stato inserito niente: esecuzione interrotta
exit 0
fi
leadingdir=/virtual
echo -n "Inserire la directory principale: (Scelta predefinita: $leadingdir): "
read ans
if [ "$ans" != "" ]
then
leadingdir=$ans
fi
newdir=$leadingdir/$domain
if [ -d "$newdir" ]
then
echo La nuova directory: $newdir: è già esistente
exit 0
else
echo La nuova directory è: $newdir
fi
echo Crea $newdir
mkdir -p $newdir
echo Crea bin
cp -pdR /bin $newdir
echo Crea dev
cp -pdR /dev $newdir
echo Crea dev/log
ln -f /virtual/log $newdir/dev/log
echo Crea etc
mkdir -p $newdir/etc
for i in /etc/*
do
if [ -d "$i" ]
then
continue
fi
cp -pd $i $newdir/etc
done
echo Crea etc/skel
mkdir -p $newdir/etc/skel
echo Crea home
for i in a b c d e f g h i j k l m n o p q r s t u v w x y z
do
mkdir -p $newdir/home/$i
done
echo Crea home/c/crc
mkdir -p $newdir/home/c/crc
chown crc.users $newdir/home/c/crc
echo Crea lib
mkdir -p $newdir/lib
for i in /lib/*
do
if [ -d "$i" ]
then
continue
fi
cp -pd $i $newdir/lib
done
echo Crea proc
mkdir -p $newdir/proc
echo Crea sbin
cp -pdR /sbin $newdir
echo Crea tmp
mkdir -p -m 0777 $newdir/tmp
chmod +t $newdir/tmp
echo Crea usr
mkdir -p $newdir/usr
echo Crea usr/bin
cp -pdR /usr/bin $newdir/usr
echo Crea usr/lib
mkdir -p $newdir/usr/lib
echo Crea usr/lib/locale
cp -pdR /usr/lib/locale $newdir/usr/lib
echo Crea usr/lib/terminfo
cp -pdR /usr/lib/terminfo $newdir/usr/lib
echo Crea usr/lib/zoneinfo
cp -pdR /usr/lib/zoneinfo $newdir/usr/lib
echo Crea usr/lib/\*.so\*
cp -pdR /usr/lib/*.so* $newdir/usr/lib
echo Crea usr/sbin
cp -pdR /usr/sbin $newdir/usr
echo Fa un link a usr/tmp
ln -s /tmp $newdir/usr/tmp
echo Crea var
mkdir -p $newdir/var
echo Crea var/lock
cp -pdR /var/lock $newdir/var
echo Crea var/log
mkdir -p $newdir/var/log
echo Crea var/log/wtmp
cp /dev/null $newdir/var/log/wtmp
echo Crea var/run
cp -pdR /var/run $newdir/var
echo Crea var/run/utmp
cp /dev/null $newdir/var/run/utmp
echo Crea var/spool
cp -pdR /var/spool $newdir/var
echo Fa un link a var/tmp
ln -s /tmp $newdir/var/tmp
echo Crea var/www/html
mkdir -p $newdir/var/www/html
chown webmast.www $newdir/var/www/html
chmod g+s $newdir/var/www/html
echo Crea var/www/master
mkdir -p $newdir/var/www/master
chown webmast.www $newdir/var/www/master
echo Crea var/www/server
mkdir -p $newdir/var/www/server
chown webmast.www $newdir/var/www/server
exit 0
Per poter eseguire dei comandi in un ambiente virtuale bisogna prima fare
chroot nella directory prefissata e poi eseguire il comando.
Ho scritto un apposito script di shell chiamato virtexec che fa questo per
un qualsiasi comando:
#!/bin/sh
echo '$Revision: 1.49 $'
BNAME=`basename $0`
FIRST4CHAR=`echo $BNAME | cut -c1-4`
REALBNAME=`echo $BNAME | cut -c5-`
if [ "$BNAME" = "virtexec" ]
then
echo Non si può eseguire direttamente virtexec: è NECESSARIO un link simbolico
exit 0
fi
if [ "$FIRST4CHAR" != "virt" ]
then
echo Il link simbolico non è a una funzione virt
exit 0
fi
list=""
num=1
for i in /virtual/*
do
if [ ! -d "$i" ]
then
continue
fi
if [ "$i" = "/virtual/lost+found" ]
then
continue
fi
list="$list $i $num"
num=`expr $num + 1`
done
if [ "$list" = "" ]
then
echo Non esistono ambienti virtuali
exit 0
fi
dialog --clear --title 'Virtexec' --menu Pick 20 70 12 $list 2> /tmp/menu.$$
if [ "$?" = "0" ]
then
newdir=`cat /tmp/menu.$$`
else
newdir=""
fi
tput clear
rm -f /tmp/menu.$$
echo '$Revision: 1.49 $'
if [ ! -d "$newdir" ]
then
echo La nuova directory: $newdir: NON ESISTE
exit 0
else
echo Nuova directory: $newdir
fi
echo bname: $BNAME
echo realbname: $REALBNAME
if [ "$*" = "" ]
then
echo args: none
else
echo args: $*
fi
echo Spostamento in $newdir
cd $newdir
echo Esecuzione del programma $REALBNAME
chroot $newdir $REALBNAME $*
exit 0
Si prega di notare che lo script funziona solo se si ha installato sul
proprio sistema il programma dialog. Per usare virtexec basta
collegare con un link simbolico un programma a virtexec. Ad esempio:
ln -s /usr/local/bin/virtexec /usr/local/bin/virtpasswd ln -s /usr/local/bin/virtexec /usr/local/bin/virtvi ln -s /usr/local/bin/virtexec /usr/local/bin/virtpico ln -s /usr/local/bin/virtexec /usr/local/bin/virtemacs ln -s /usr/local/bin/virtexec /usr/local/bin/virtmailq
In questo modo quando si digiterà virtvi o virtpasswd o virtmailq si potrà editare un file con vi, cambiare la password di un utente o controllare la coda di posta sul proprio sistema virtuale. Si possono creare tanti link simbolici a virtexec quanti occorrono. Da notare che, se il programma richiede una libreria condivisa, essa deve trovarsi nel filesystem virtuale, così come il file binario stesso.
Di solito io installo tutti gli script in /usr/local/bin. Tutto ciò che non voglio compaia nel filesystem virtuale lo metto in /usr/local. Lo script non copia alcun file di /usr/local nel filesystem virtuale. È importante che ogni file che non deve trovarsi in tutti i filesystem virtuali venga rimosso. Ad esempio, sul mio sistema è installato ssh ed io non voglio che la chiave privata per il server sia disponibile su tutti i filesystem virtuali, così lo cancello da ciascun filesystem virtuale dopo aver lanciato virtfs. Oltre a questo, cambio anche resolv.conf e rimuovo per ragioni legali tutto ciò che contiene un riferimento ad un altro dominio. Ad esempio, /etc/hosts /etc/HOSTNAME.
Questi sono i programmi che ho collegato con un link simbolico a virtexec: