mercredi 20 mai 2015

shebang postgresql

Le shebang (#!) est un en-tête de fichier qui indique au système d'exploitation que ce fichier est en fait un script. Le chemin d'accès vers l'interpréteur à utiliser est indiqué juste après sur la même ligne.
Ainsi un script bash devrait avoir une première ligne du genre:

#!/bin/bash

Problème avec les scripts interprétés par psql:  pour SQL, # n'indique pas un commentaire, mais bien  --
Faisons le test dans un terminal psql:


Nous imprimons (\p) ce qui sera envoyé au serveur pour exécution avant de procéder (;). Nous constatons que le commentaire a disparu et n'est pas envoyé au serveur.
Par contre:



'# commentaire' figure bien dans ce qui est envoyé au serveur, d'où l'erreur.

Nous avons le même genre d'erreur lors de l'exécution du script sbpsql1x:

#!/usr/bin/psql -f
select now()
\echo 'Sera envoyé au serveur:'
\echo
\p
\echo
\echo 'Procédons:'
\echo
;

Vérifions:


Comme proposé ici on peut remplacer la ligne shebang par

--() { :; }; exec psql [options] -f "$0"

Notre script devient sbpsql2x:

--() { :; }; exec psql bdtest -f "$0" 
select now()
\echo 'Sera envoyé au serveur:'
\echo
\p
\echo
\echo 'Procédons:'
\echo
;

Cette fois ça fonctionne car la ligne 1 est traitée comme un commentaire par psql:


Cette ligne n'est pas vraiment un shebang (où est #! ?). Elle commence par la définition d'une fonction (notée --) associée à une commande qui ne fait rien (:). Comme la fonction n'est jamais utilisée on pourrait mettre n'importe quoi (par exemple echo 'Hello') à la place de :).
En toute rigueur on devrait commencer le script par un véritable shebang, comme ceci:

#!/bin/bash
--() { :; }; exec psql bdtest -f "$0" 
select now()
...

Mais on retombe alors sur la même erreur.

Une autre possibilité est celle utilisée dans ce script (sbpsql3x):

#!/bin/sh
exec sh -c "tail -n +3 $0 | psql bdtest -f -" 
select now()
\echo 'Sera envoyé au serveur:'
\echo
\p
\echo
\echo 'Procédons:'
\echo
;

La commande tail envoie à partir de la ligne 3 le contenu du script (dont le nom se trouve dans $0) vers la commande psql. L'option -f - signifie que psql lit les instructions depuis l'entrée standard qui dans notre cas est la sortie standard de tail (voir ici: les canaux de communication avant et après un pipe: stdout de la commande en aval est connecté à stdin de la commande en amont).