mercredi 8 juin 2011

Postgresql: localisation

En guise de préambule, notons que le plus souvent aucun problème de localisation ne se pose avec postgresql, mais parfois quelques surprises se trouvent au rendez-vous...

Suivant ce qui est expliqué dans le billet PostgreSQL (initiation), nous procédons, après l'installation du paquet postgresql, à l'initiation de la base de données:


Tiens cette fois les messages sont en anglais. Pourtant notre système (Fedora 15) semble bien francisé.
Un doute affreux s'insinue. Vérifions: après être devenu postgres, affichons la liste des bases de données existantes:


Enfer et damnation!
Mais qu'à cela ne tienne: man createdb nous apprend que l'on peut choisir la localisation avec l'option --locale.
Bon, continuons avec la création de l'utilisateur toto. Lançant la commande createuser  sans options, nous sommes interrogés sur nos intentions:


Ensuite après être devenu toto, nous procédons à la création de notre base de donnée à l'aide de la commande createdb et de l'option --locale.
Notre base de données s'appellera bd01:


Mais à quoi sert l'option --locale alors?
Manifestement, quelque chose nous échappe.
(EDIT: voir ici)
Mais tant pis: aux grands maux, les grands remèdes.
Cherchons où se trouve le database cluster?


Arrêtons le service postgresql et supprimons le cluster en question:


Nous pouvons maintenant initialiser le cluster à notre guise en utilisant la commande initdb, mais attention initdb ne peut pas être lancé par le root. On va l'exécuter en tant que postgres:

bash-4.2$ initdb -A ident -D /var/lib/pgsql/data --locale=fr_FR.utf8
Les fichiers de ce cluster appartiendront à l'utilisateur « postgres ».
Le processus serveur doit également lui appartenir.

Le cluster sera initialisé avec la locale fr_FR.utf8.
L'encodage par défaut des bases de données a été configuré en conséquence
avec UTF8.
La configuration de la recherche plein texte a été initialisée à « french ».

correction des droits sur le répertoire existant /var/lib/pgsql/data... ok
création des sous-répertoires... ok
sélection de la valeur par défaut de max_connections... 100
sélection de la valeur par défaut pour shared_buffers... 28MB
création des fichiers de configuration... ok
création de la base de données template1 dans /var/lib/pgsql/data/base/1... ok
initialisation de pg_authid... ok
initialisation des dépendances... ok
création des vues système... ok
chargement de la description des objets système... ok
création des conversions... ok
création des dictionnaires... ok
initialisation des droits sur les objets internes... ok
création du schéma d'informations... ok
chargement du langage PL/pgSQL... ok
lancement du vacuum sur la base de données template1... ok
copie de template1 vers template0... ok
copie de template1 vers postgres... ok

Succès. Vous pouvez maintenant lancer le serveur de bases de données par :

    postgres -D /var/lib/pgsql/data
ou
    pg_ctl -D /var/lib/pgsql/data -l journal_applicatif start

Les commandes indiquées, postgres et pg_ctl, ne peuvent pas être exécutées par le root (tout comme initdb):
On a le choix:
  • soit utiliser une des commandes postgres ou pg_ctl en tant qu'utilisateur postgres
  • soit la commande service postgresql start en tant que root.
Dans ce blog, nous n'avons pas encore présenté les commandes postgres ou pg_ctl. Voici l'occasion d'en dire un peu plus à ce sujet. Pour peu que la variable d'environnement PGDATA soit définie de manière adéquate (par exemple en ayant ajouté en temps utile export PGDATA=/var/lib/pgsql/data au fichier /etc/bashrc), l'option -D est inutile.

La commande postgres tourne en avant plan, comme ceci:


La commande pg_ctl elle, tourne en arrière plan et les lignes de log qui étaient affichées à l'écran avec la commande postgres sont dirigées suite à l'emploi de l'option -l vers le fichier désigné, à savoir: journal_applicatif.

Dans le système d'exploitation que nous utilisons actuellement (Fedora 15), les informations de log sont capturées et dirigées vers un fichier du répertoire /var/lib/pgsql/data/pg_log. On n'a donc aucun intérêt à utiliser la commande postgres ou l'option -l avec pg_ctl (puisque journal_applicatif resterait vide). Nous allons démarrer le serveur avec la commande pg_ctl start tout simplement:
Bien sûr, l'utilisateur toto a disparu: il doit de nouveau être créé par postgres:


Cette fois createuser nous parle en français (c'est bon signe).
Ensuite dans une fenêtre où nous sommes toto:


C'est merveilleux.

Arrêtons le serveur:


Nous voudrions maintenant procéder en démarrant le serveur en tant que root.
Ça ne fonctionne pas!


Étonnant puisque avec l'autre méthode le serveur démarre!
C'est SELinux qui fait des siennes:


SELinux is preventing /usr/bin/postgres from getattr access on the fichier /var/lib/pgsql/data/postgresql.conf.


Il faut restaurer le contexte de sécurité:


[root@rigel ~]# /sbin/restorecon -R /var/lib/pgsql/
/sbin/restorecon set context /var/lib/pgsql/data/postgresql.conf->system_u:object_r:postgresql_t:s0 failed:'Permission denied'

Lorsque tout fonctionne bien, la commande /sbin/restorecon (dans le contexte où elle a été utilisée) ne fournit aucun retour. Habituellement c'est le cas, mais pas cette fois: un problème se pose pour le fichier postgresql.conf. La commande semanage devrait pouvoir le résoudre:



[root@rigel ~]# semanage fcontext -a -t postgresql_db_t /var/lib/pgsql/data/postgresql.conf
[root@rigel ~]# /sbin/restorecon -v  /var/lib/pgsql/data/postgresql.conf
/sbin/restorecon reset /var/lib/pgsql/data/postgresql.conf context unconfined_u:object_r:var_lib_t:s0->system_u:object_r:postgresql_db_t:s0 


Tout semble en ordre maintenant. vérifions-le en affichant le contexte de sécurité avant de démarrer le serveur:


Ce qui suit est hors-sujet, mais comme nous avons maintenant présenté la commande pg_ctl, la question peut être posée:
quelle est la meilleur façon d'arrêter le serveur?
Examinons le fichier log.
Avec pg_ctl stop, ça donne ceci:




Avec service postgresql stop (ou lorsqu'on arrête l'ordinateur sur lequel tourne le serveur):



La réponse semble aller de soi.
Presque tout ce qui est expliqué dans ce billet peut s'appliquer à quelques détails près à la plupart des distributions. Avec cette évidence: SELinux quand il n'est pas installé ou quand il n'est pas actif ne pose évidemment aucun problème.
En ce qui concerne Ubuntu (11.04), c'est un peu plus compliqué. Les données ne se trouvent pas à l'emplacement habituel, mais on trouve sans difficulté où elles se trouvent:

root@rigel:~# ps -U postgres -o command | awk 'NR==2'
/usr/lib/postgresql/8.4/bin/postgres -D /var/lib/postgresql/8.4/main -c config_file=/etc/postgresql/8.4/main/postgresql.conf
root@rigel:~#


Par contre lorsqu'on veut exécuter initdb, la commande est introuvable.
Il convient de créer les liens suivant:


root@rigel:~# cd /usr/bin
root@rigel:/usr/bin# ln -s ../share/postgresql-common/pg_wrapper initdb
root@rigel:/usr/bin# ln -s ../share/postgresql-common/pg_wrapper postgres
root@rigel:/usr/bin# ln -s ../share/postgresql-common/pg_wrapper pg_ctl


Démarrer le serveur avec postgres ou pg_ctl ne pose aucun problème, mais l'utilisation de service postgresql start conduit à un échec suite à un problème de certificats manquants. Il s'agit donc de recréer les liens qui ont disparu lors de la suppression de /var/lib/postgresql/8.4/main:


root@rigel:~# cd /var/lib/postgresql/8.4/main/
root@rigel:/var/lib/postgresql/8.4/main# ln -s /etc/ssl/certs/ssl-cert-snakeoil.pem server.crt
root@rigel:/var/lib/postgresql/8.4/main# ln -s /etc/ssl/private/ssl-cert-snakeoil.key server.key