Le blog de Jean David TECHER, un Réunionnais à Saint-Priest/Lyon

Aller au contenu | Aller au menu | Aller à la recherche


< 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 >

lundi 8 janvier 2007

Sécurité avec PostgreSQL - Stunnel

Introduction

Pour protéger ses données lors d'une connexion entre un serveur et un client avec PostgreSQL, il existe plusieurs façons de faire. Soit en utilisant PostgreSQL compilé avec OpenSSL en natif, uriliser un tunnel SSH avec redirection de Port ect...Un des moyens que j'aime bien et d'utiliser Stunnel/OpenSSL.

Stunnel est une enveloppe SSL, permettant donc d'étendre les fonctionnalités de SSL à un démon qui à l'origine n'est pas prévu pour être une couche de sécurité. On peut donc par exemple créer une connexion sécurisée entre vers une base de données, consolidant ainsi la connexion du système,

Un autre intérêt de l'installation avec Stunnel est qu'il peut-être installé en tant que service (automatiquement relancé au démarrage de la machine). Ce que ne propose pas une redirection par SSH. Je ne propose pas ici l'installation de stunnel avec xinetd, trop contrariant à mon sens.

1. Pré-requis

Je pars du principe ici que les configurations réseaux avec PostgreSQL sont acquises par le lecteur. Pour les test ici, nous aurons besoin de deux machines. Sur mon réseau domestique, j'ai deux machines dont les noms sont respectivement jenna et bremko:

  • jenna dont l'IP est 192.168.0.5 fera office de serveur. Je lui ai installé un serveur PostgreSQL 8.1.5;
  • bremko dont l'IP est 192.168.0.4 fera office de client PostgreSQL 8.1.5 pour lequel je n'aurais besoin que de psql fourni par la 8.1.5 de PostgreSQL;

Pour vérifier que les données sont bien chiffrées où non, nous avons besoin d'installer un sniffer comme nast ou etherreal (...) entre jenna et bremko! J'opte ici pour NAST (Network Analize Sniffer Tool/http://nast.berlios.de/) que j'installe en faisant - en tant que root - sur bremko

apt-get install nast

Pour les besoins de mes tests, je crée un super-utilisateur damien sur jenna dont le mot de passe sera 'morphine'

root@jenna:/root$ su postgres
postgres@jenna:/root$createuser -sEPe damien
Entrez le mot de passe pour le nouvel rôle :
Entrez-le de nouveau :
CREATE ROLE damien ENCRYPTED PASSWORD 'morphine' SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN;
CREATE ROLE

Remarques: mes machines sont ici toutes les deux sous Ubuntu Dapper. Pour de plus amples informations sur nast, n'oubliez pas de faire man nast

2. Motivations: sniffer une connexion non sécurisée avec NAST, limites d'une connexion par mot de passe en md5!

2.1 Test sans mot de passe

Commençons donc par vérifier que si je laisse le mot de passe par défaut sur à 'password' sur le réseau on arrive quand même à le récupérer. Pour celà, dans le pg_hba.conf de jenna, je fais la modification suivante

host 192.168.0.4 255.255.255.255 password

et je redémarre ensuite mon serveur

/etc/init.d/postgresql restart

Sur bremko, dans un terminal pour sniffer les connexion je fais

nast -i eth0 -pd -f "dst 192.168.0.5" -f  "port 5432"

Dans un autre terminal (toujous depuis bremko), j'ouvre ma connexion à jenna en faisant

psql -h jenna -U damien template1

Dans le terminal que contient le processus actif de nast, je vois a un moment passé le message

---[ TCP Data ]------------------------------------------------------

   (    user damien database template1
---[ TCP ]-----------------------------------------------------------
192.168.0.5:5432(postgresql) -> 192.168.0.4:50884(unknown)
TTL: 64         Window: 1448    Version: 4      Lenght: 61
FLAGS: ---PA--  SEQ: 1495197601 - ACK: 923679297
Packet Number: 26

---[ TCP Data ]------------------------------------------------------

R
---[ TCP ]-----------------------------------------------------------
192.168.0.4:50884(unknown) -> 192.168.0.5:5432(postgresql)
TTL: 64         Window: 1460    Version: 4      Lenght: 66
FLAGS: ---PA--  SEQ: 923679297 - ACK: 1495197610
Packet Number: 27

---[ TCP Data ]------------------------------------------------------

morphine
---[ TCP ]-----------------------------------------------------------

preuve que ça ne suffit pas!

2.2 Test avec MD5

Allons donc! Changeons donc le mot-clé 'password' par 'md5' dans le fichier pg_hba.conf de jenna,

host 192.168.0.4 255.255.255.255 md5

et redémarrons le serveur (/etc/init.d/postgresql restart). Relançons donc une connexion au serveur depusi bremko. Maintenant depuis nast, j'obtiens

---[ TCP Data ]------------------------------------------------------

   (    user damien database template1
---[ TCP ]-----------------------------------------------------------
192.168.0.5:5432(postgresql) -> 192.168.0.4:45585(unknown)
TTL: 64         Window: 1448    Version: 4      Lenght: 65
FLAGS: ---PA--  SEQ: 1852264915 - ACK: 1258303094
Packet Number: 85

---[ TCP Data ]------------------------------------------------------

R         +F
---[ TCP ]-----------------------------------------------------------
192.168.0.4:45585(unknown) -> 192.168.0.5:5432(postgresql)
TTL: 64         Window: 1460    Version: 4      Lenght: 93
FLAGS: ---PA--  SEQ: 1258303094 - ACK: 1852264928
Packet Number: 86

---[ TCP Data ]------------------------------------------------------

p   (md5063971165646bb85c855953e66c01196
---[ TCP ]-----------------------------------------------------------

Gagné ! Enfin ne nous réjouisson pas trop vite car si je tape une requête depuis le client je vois apparaître par exemple

---[ TCP Data ]------------------------------------------------------

Q   %select * from geometry_columns ;
---[ TCP ]-----------------------------------------------------------
192.168.0.5:5432(postgresql) -> 192.168.0.4:48508(unknown)
TTL: 64         Window: 6091    Version: 4      Lenght: 52
FLAGS: ----A--  SEQ: 2056534420 - ACK: 1484467451
Packet Number: 161

---[ TCP ]-----------------------------------------------------------
192.168.0.5:5432(postgresql) -> 192.168.0.4:48508(unknown)
TTL: 64         Window: 6091    Version: 4      Lenght: 1500
FLAGS: ----A--  SEQ: 2056534420 - ACK: 1484467451
Packet Number: 162

---[ TCP Data ]------------------------------------------------------

T      f_table_catalog                   f_table_schema                   f_table_name                   f_geometry_column                  
 coord_dimension                   srid                   type                "  D   E          public    apb_lr    the_geom    2   
 -1    MULTIPOLYGOND   U          public   a_cours_d_eau_n2_v3    the_geom    2    -1    MULTILINESTRING

Oups!

Première conclusion Bon md5 protège bien mon mot de passe mais pas mes requêtes ainsi que les résultats renvoyés par le serveur! Et c'est là justement qu'intervient Stunnel !

3. Stunnel: sécurisation de la connexion

3.1 Pré-requis: OpenSSL

Stunnel a besoin de OpenSSL pour pouvoir fonctionner

apt-get install openssl libssl-dev
3.2 Installation de Stunnel

Le site de stunnel est http://www.stunnel.org. Nous aurons besoin ici de l'installer à la fois sur le serveur et sur le client. Je fournis ici les commandes que j'ai utilisé pour l'installer sans plus de détails

wget http://www.stunnel.org/download/stunnel/src/stunnel-4.20.tar.gz
tar xvzf  stunnel-4.20.tar.gz
cd stunnel-4.20
./configure --with-ssl=/usr --prefix=/opt/stunnel
make
make install

Lors de l'installation un fichier stunnel.pem sera généré dotn voici une copie d'écran de ce que j'ai renseigné pour jenna

Generating a 1024 bit RSA private key
.................++++++
............++++++
writing new private key to 'stunnel.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [PL]:FR
State or Province Name (full name) [Some-State]:Hérault
Locality Name (eg, city) []:Castelnau-Le-Lez
Organization Name (eg, company) [Stunnel Developers Ltd]:01MAP
Organizational Unit Name (eg, section) []:01MAP
Common Name (FQDN of your server) [localhost]:jenna

Je renouvelle l'instalaltion sur bremko, en changeant la ligne Common Name (FQDN of your server) [localhost]:bremko

3.3 Mise en oeuvre

J'ouvre maintenant un terminal sur jenna et j'y tape

root@jenna:/opt/stunnel/sbin/stunnel3 -D 7 -f -P /opt/stunnel/stunnel.pid \
-o /opt/stunnel/log/stunnel.log -p /opt/stunnel/etc/stunnel/stunnel.pem -d 9000 -r localhost:5432

Sur bremko, je lance

root@bremko:/opt/stunnel# /opt/stunnel/sbin/stunnel3 -D 7 -f \
-P/opt/stunnel/stunnel.pid -o /opt/stunnel/log/stunnel.log -c -d localhost:5433 \
-o /opt/stunnel/log/stunnel.log -c -d localhost:5433 -r 192.168.0.5:9000

Et pour m'assurer que les connexions seront chiffrées dans un troisème terminal sur bremko, je fais

nast -pd -i eth0 -f "dst 192.168.0.5" -f "port 9000"

Dans un nouveau terminal toujours - sur bremko - j'ouvre maintenant une connexon PostgreSQL en faisant

psql -h localhost -p 5433 -U damien template1

Je saisis quelques requêtes et j'apprécie le travail en regardant les lignes retournées par nast depuis le troisième terminal en question

3.4 Installation de Stunnel en tant que service

Pour l'installtion en service sur les deux machines, il suffit de modifer le script de démarrage de Ubuntu à savoir /etc/init.d/rc.local. J'y ai par exemple effectuer les modifications suivantes sur jenna

#! /bin/sh
# Modications du PATH pour accéder à stunnel
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/opt/stunnel/sbin
[ -f /etc/default/rcS ] && . /etc/default/rcS
. /lib/lsb/init-functions

do_start() {
        if [ -x /etc/rc.local ]; then
                log_begin_msg "Running local boot scripts (/etc/rc.local)"
                /etc/rc.local
                log_end_msg $?
        fi
}
# Ma ligne pour lancer stunnel sur jenna
# à adapter en conséquence sur bremko (voir ci-dessus dans la doc)
/opt/stunnel/sbin/stunnel3 -D 7 -f -P /opt/stunnel/stunnel.pid -p /opt/stunnel/etc/stunnel/stunnel.pem -d 9000 -r localhost:5432 -o /opt/stunnel/log/stunnel.log

case "$1" in
    start)
        do_start
        ;;
    restart|reload|force-reload)
        echo "Error: argument '$1' not supported" >&2
        exit 3
        ;;
    stop)
        ;;
    *)
        echo "Usage: $0 start|stop" >&2
        exit 3
        ;;
esac

Liens

Utilisation de Tsearch2 avec PostgreSQL

Introduction

Tsearch est une extensions utilisable avec PostgreSQL pour la recherche de textes dans les colonnes d'une base de données, comme pour les moteurs de recherche, comme google, yahoo etc... Pour une meilleure présentation de Tsearch, merci de consultez le lien http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/

Nous allons ici essayer de l'utiliser sur une table contenant pas moins de ??? enregistrements. Les tests ici ont lieu avec PostgreSQL 8.1.5

Pré-requis

Avoir PostgreSQL d'installé!

Installation

Les sources de tsearch se trouvent dans le sous-répertoire contrib des sources de PostgreSQL. Pour l'installation, il suffira de faire en tant que root

cd contrib/tsearch2
make
make install

Pour charger les fonctionnalités de tsearch dans notre base - que nous appelerons ici testdb -, il suffira de faire

su postgres
psql -d testdb -f /usr/local/pgsql/share/contrib/tsearch2.sql

Dans notre base, nous avons une table bdnyme dont un des champs est nom dont voici un extrait

testdb#select distinct nom from bdnyme where like(nom,'%Castelnau%') limit 4;
                  nom
---------------------------------------
 Aérodrome de Castelnaudary-Villeneuve
 Aérodrome de Castelnau-Magnoac
 Barrage de Castelnau-Lassouts
 Bois Communal de Castelnau-de-Médoc
(4 lignes)
ALTER TABLE public.bdnyme ADD COLUMN nom_vectors tsvector;
UPDATE public.bdnyme SET nom_vectors=to_tsvector('simple', nom);
VACUUM FULL ANALYZE;
CREATE INDEX nom_idxv ON public.bdnyme USING gist(nom_vectors);
VACUUM FULL ANALYZE;

Je tiens quand même à préciser ici que les lignes UPDATE et CREATE INDEX m'ont pris quand même un sacré temps pour une table de plus de 1.4 millions de lignes! Au moins entre 9h00 à 12h00 sur mon pauvre SONY VAIO FS315H. Mais bon je n'ai pas de grosse machine à la maison

Pour le fun, par exemple recherchons par exemple le caractère 'castelnau' sans tenir compte de la casse dans la colonne nom de ma tabe

testdb=# explain analyze select nom from bdnyme where nom ~* 'castelnau';
                                                 QUERY PLAN
------------------------------------------------------------------------------------------------------------
 Seq Scan on bdnyme  (cost=0.00..85066.32 rows=4 width=16) (actual time=600.210..18545.878 rows=51 loops=1)
   Filter: ((nom)::text ~* 'castelnau'::text)
 Total runtime: 18546.257 ms
(3 lignes)

Soit 18 secondes mama !!!

Bon au tour de Tsearch maintenant !

testdb=# explain analyze select nom from bdnyme where nom_vectors @@ to_tsquery('simple','castelnau');
                                                       QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on bdnyme  (cost=39.74..5164.24 rows=1449 width=16) (actual time=38.356..38.739 rows=49 loops=1)
   Filter: (nom_vectors @@ '''castelnau'''::tsquery)
   ->  Bitmap Index Scan on nom_idxv  (cost=0.00..39.38 rows=1449 width=0) (actual time=38.299..38.299 rows=49 loops=1)
         Index Cond: (nom_vectors @@ '''castelnau'''::tsquery)
 Total runtime: 39.047 ms
(5 lignes)

Soit 0.03 secondes. Purée ...... ! Requête de l'enfer de la mort qui du le diable !

Promettant comme on dit! Bon je n'ai pas encore essayé les index GIN à la place de GiST pour le moment bien que la rumeur veuille que leur création prennent beaucoup de temps! Mais bon à tester, à tester!

Utilisation du dictionnaire fançais

Pour utiliser le dictionnaire, on fera

BEGIN TRANSACTION; 

INSERT INTO pg_ts_cfg (ts_name, prs_name, locale) VALUES ('default_french', 'default', 'fr_FR.UTF-8');


insert into pg_ts_cfgmap values ('default_french','email','{simple}');
insert into pg_ts_cfgmap values ('default_french','file','{simple}');
insert into pg_ts_cfgmap values ('default_french','float','{simple}');
insert into pg_ts_cfgmap values ('default_french','host','{simple}');
insert into pg_ts_cfgmap values ('default_french','hword','{simple}');
insert into pg_ts_cfgmap values ('default_french','int','{simple}');
insert into pg_ts_cfgmap values ('default_french','lhword','{fr_ispell}');
insert into pg_ts_cfgmap values ('default_french','lpart_hword','{fr_ispell}');
insert into pg_ts_cfgmap values ('default_french','nlhword','{simple}');
insert into pg_ts_cfgmap values ('default_french','nlpart_hword','{simple}');
insert into pg_ts_cfgmap values ('default_french','part_hword','{simple}');
insert into pg_ts_cfgmap values ('default_french','sfloat','{simple}');
insert into pg_ts_cfgmap values ('default_french','uint','{simple}');
insert into pg_ts_cfgmap values ('default_french','uri','{simple}');
insert into pg_ts_cfgmap values ('default_french','url','{simple}');
insert into pg_ts_cfgmap values ('default_french','version','{simple}');
insert into pg_ts_cfgmap values ('default_french','word','{fr_ispell}');
insert into pg_ts_cfgmap values ('default_french','nlword','{fr_ispell}');
insert into pg_ts_cfgmap values ('default_french','lword','{fr_ispell,simple}');


 INSERT INTO pg_ts_dict
               (SELECT 'fr_ispell',
                       dict_init,
                       'DictFile="/home/david/download/ispell-french/french.dict",'
                       'AffFile="/home/david/download/ispell-french/french.aff",'
                       'StopFile="/home/postgres/french.stop"',
                       dict_lexize
                FROM pg_ts_dict
                WHERE dict_name = 'ispell_template');

END TRANSACTION;

On peut vérifier tout ça en faisant par exemple

ignportal=# select to_tsvector('default_french','mon village écolé');
     to_tsvector
---------------------
 'mon':1 'village':2
(1 ligne)

ignportal=# select to_tsvector('default_french','mon village école');
          to_tsvector
-------------------------------
 'mon':1 'école':3 'village':2
(1 ligne)

ignportal=# select to_tsvector('default_french','mon village ecole');
          to_tsvector
-------------------------------
 'mon':1 'ecole':3 'village':2
(1 ligne)

ignportal=# select to_tsvector('default_french','mon village ecole d\'avant là guerre');
                           to_tsvector
-----------------------------------------------------------------
 'd':4 'là':6 'mon':1 'avant':5 'ecole':3 'guerre':7 'village':2
(1 ligne)

ignportal=# select to_tsvector('default_french','mon village école d\'avant là guerre');
                           to_tsvector
-----------------------------------------------------------------
 'd':4 'là':6 'mon':1 'avant':5 'guerre':7 'école':3 'village':2
(1 ligne)

ignportal=# select to_tsvector('default_french','mon village écolu d\'avant là guerre');
                      to_tsvector
-------------------------------------------------------
 'd':3 'là':5 'mon':1 'avant':4 'guerre':6 'village':2
(1 ligne)

ignportal=# select to_tsvector('default_french','mon village écoles d\'avant là guerre');
                           to_tsvector
-----------------------------------------------------------------
 'd':4 'là':6 'mon':1 'avant':5 'guerre':7 'école':3 'village':2
(1 ligne)

ignportal=# select to_tsvector('default_french','mon village écol d\'avant là guerre');
                      to_tsvector
-------------------------------------------------------
 'd':3 'là':5 'mon':1 'avant':4 'guerre':6 'village':2
(1 ligne)

ignportal=# select to_tsvector('default_french','mon village écolier d\'avant là guerre');
                            to_tsvector
-------------------------------------------------------------------
 'd':4 'là':6 'mon':1 'avant':5 'guerre':7 'village':2 'écolier':3
(1 ligne)

ignportal=# select to_tsvector('default_french','mon village écoliers d\'avant là guerre');
                            to_tsvector
-------------------------------------------------------------------
 'd':4 'là':6 'mon':1 'avant':5 'guerre':7 'village':2 'écolier':3
(1 ligne)

ignportal=# select to_tsvector('default_french','mon village écolières d\'avant là guerre');
                      to_tsvector
-------------------------------------------------------
 'd':3 'là':5 'mon':1 'avant':4 'guerre':6 'village':2
(1 ligne)

ignportal=# select to_tsvector('default_french','mon village écoliers d\'avant là guerre');
                            to_tsvector
-------------------------------------------------------------------
 'd':4 'là':6 'mon':1 'avant':5 'guerre':7 'village':2 'écolier':3
(1 ligne)

ignportal=# select to_tsvector('default_french','ils sont beaux les nouveaux écoliers dans leur nouvelles école');
                                                to_tsvector
------------------------------------------------------------------------------------------------------------
 'il':1 'le':1,4 'dan':7 'les':4 'beau':3 'leur':8 'sont':2 'école':10 'nouveau':5 'nouvelle':9 'écolier':6
(1 ligne)

ignportal=# select to_tsvector('default_french','ils sont beaux les nouveaux écoliers dans leur nouvelles école mais école prend un accent');
                                                                                    to_tsvector 
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 'ce':15 'il':1 'le':1,4 'un':14 'dan':7 'les':4 'mai':11 'beau':3 'cens':15 'leur':8 'mais':11 'sont':2 'accent':15 'prends':13 'école':10,12 'nouveau':5 'nouvelle':9 'écolier':6
(1 ligne)

ignportal=# select to_tsvector('default_french','ils sont beaux les nouveaux écoliers dans leur nouvelles école mais école prend un accent, pas ecole!');
                                                                                              to_tsvector 
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 'ce':15 'il':1 'le':1,4 'un':14 'dan':7 'les':4 'mai':11 'pas':16 'beau':3 'cens':15 'leur':8 'mais':11 'sont':2 'ecole':17 'accent':15 'prends':13 'école':10,12 'nouveau':5 'nouvelle':9 'écolier':6
(1 ligne)

ignportal=# select to_tsvector('default_french','ils sont beaux les nouveaux écoliers dans leur nouvelles école de Castelnau-Le-Lez mais école prend un accent, pas ecole!');
                                                                                                        to_tsvector 
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 'ce':18 'de':11 'il':1 'le':1,4,12 'un':17 'dan':7 'les':4 'lez':13 'mai':14 'pas':19 'beau':3 'cens':18 'leur':8 'mais':14 'sont':2 'ecole':20 'accent':18 'prends':16 'école':10,15 'nouveau':5 'nouvelle':9 'écolier':6

Maintenant on remet tout en place

ignportal=# drop INDEX nom_idxv ;
DROP INDEX
ignportal=# alter TABLE bdnyme drop COLUMN nom_vectors;
ALTER TABLE
ignportal=# ALTER TABLE public.bdnyme ADD COLUMN nom_vectors tsvector;
ALTER TABLE
ignportal=# explain ANALYZE UPDATE public.bdnyme SET nom_vectors=to_tsvector('default_french', nom);
                                                      QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
 Seq Scan on bdnyme  (cost=0.00..49545.33 rows=1449466 width=95) (actual time=15.996..215115.297 rows=1449466 loops=1)
 Total runtime: 20318651.206 ms
(2 lignes)

Soit déjà 5h38m38s pour cette dernière requête

Maintenant un petit Vacuum sur la table

VACUUM FULL ANALYZE

Puis on crée l'index

postgres@bremko:/home/david$ time psql ignportal -c "CREATE INDEX nom_idxv ON public.bdnyme USING gist(nom_vectors)"
CREATE INDEX

real    4m44.361s
user    0m0.024s
sys     0m0.000s

dimanche 7 janvier 2007

Obtenir les dimensions d'une image et les réduire

Suite à un billet précédent, je propose donc ce petit test pour permettre de pouvoir réduire une image!

Tout d'abord il nous faut convert (fournit dans le paquet imagemagick d'ubuntu) et imagesize (fournit quand à lui dans le paquet libimagesize-perl)

apt-get install libimage-size-perl imagemagick 

Supposons que j'ai une image Capture-1.png dont j'obtiens les dimensions par

root@bremko:/home/david# imgsize Desktop/Capture-1.png
width="1280" height="800"

L'option -r de imgsize (cf. man imgsize) me permet de me débarasser des witdh et heights

root@bremko#imgsize -r Desktop/Capture-1.png
1280 800

La page man de convert me permet de savoir que pour réduire une image il suffit d'utiliser l'option resize

convert -resize [nouveau_width]x[nouveau_height] [image_source] [image_finale]

Donc pour mon exemple, en utilsant cut pour récupérer à la fois width et height depuis imgsize, ainsi que expr je peux par exemple faire un petit script comme celui-ci pour réduire mon image par exemple d'un rapport au quart

#!/bin/sh
 image="/home/david/Desktop/Capture-1.png"
rapport=4 
width=$(imgsize -r ${image} |cut -d ' ' -f 1)
height=$(imgsize -r ${image} |cut -d ' ' -f 2)
convert -resize $(expr ${width} / ${rapport})x$(expr ${height} / ${rapport}) ${image} ${image}

Suite à l'exécution de ce script par sh script.sh, imgsize me confirme bien les nouvelles dimensions qui sont donc

root@bremko:/home/david# imgsize Desktop/Capture-1.png
width="320" height="200"

GDAL vesion 1.4.0

GDAL a donc sortie sa version 1.4.0 récemment! L'un des nouveautés qui m'intéresse surtout c'est la possibilité pour le format KML avec ogr2ogr! Oh yeahh ! Apparement cette nouvelle mouture supporte aussi l'utilisation des schémas pour OGR mais pas encore essayé!

Vous pouvez voir les nouveautés de la 1.4.0 à cette adresse http://www.gdal.org/NEWS.html