Fri 09 January 2015
| tags: Bash/Shell Linux Pelican Translations:
en
Comme je l'ai déjà dit ici , mon blog est géré par
Pelican . Il est également placé sous gestion de
version. Pour régénérer automatiquement après chaque modification la version
html des pages, il faut utiliser la commande make regenerate . Pour lancer le
serveur de test pour voir les pages, on utilise make serve . Enfin, pour
synchroniser le contenu sur le serveur, j'utilise make rsync_upload . J'en
profite pour pousser les modifications de mon dépôt local vers mon serveur et
vers Bitbucket pour
en avoir une copie de sauvegarde.
Jusqu'à présent, je gérais tout ça à la main, dans un terminal. J'avais déjà
écrit une petite fonction bash pour me déplacer dans le bon dossier et activer
le venv python. Mais ce n'était pas très pratique : les commandes make serve
et make regenerate doivent tourner en permanence en tâche de fond, il faut
pusher sur deux dépôts différents et synchroniser les pages sur le serveur. J'ai
donc décider de me créer un script pour améliorer tout ça.
Comme j'ai besoin de lancer plusieurs commandes bien définies dans un même
dossier, sans sortir de l'environnement virtuel et que je veux pouvoir
interagir facilement avec les processus en tâche de fond, j'ai décidé de créer
un mini-shell. Je dois admettre que j'en suis très satisfait.
Quelques explications sur le script :
Tout est dans une boucle infinie pour imiter un vrai shell. echo -ne "> "
permet d'afficher un prompt et de laisser le curseur sur cette ligne.
exec 3< <(make serve)
La syntaxe <(make serve) est remplacée par chemin vers un fichier
virtuel qui est connecté à la sortie standard de la commande située entre
les parenthèses. Ici make serve qui démarre le serveur.
Comme on veut que le processus soit en background, on lance la commande avec
exec .
Enfin, comme on veut pouvoir récupérer facilement la sortie de la commande,
on envoie le contenu du fichier vers une nouvelle sortie 3. On lit son
contenu avec cat <&3 . Tant que le fichier n'est pas fermé, cette
commande ne se retourne pas.
Voir cette réponse sur stackoverflow
pour plus de détails.
Sorties additionnelles : j'ai tenté de stocker le numéro des sorties dans des
variables. Le code est plus clair et cela permet de le
factoriser. Malheureusement, exec "${var}"< <(make serve) provoque une
erreur. Idem pour cat <&"${var}" .
[ -n "${serve_pid}" ] && has_died "${serve_pid}" : la fonction
has_died ne doit pas être entre crochets (donc passée en argument à la
fonction test ) pour que le script fonctionne correctement.
echo ${pid} : on ne peut pas renvoyer autre chose que des codes d'erreur avec
return . Pour tout le reste, il faut utiliser echo .
Ci-dessous le script complet. Vous pouvez aussi le télécharger ou le voir sur github pour
avoir la version la plus à jour.
1 #!/usr/bin/bash
2
3 stop_command() {
4 if [ " $1 " ] ; then
5 kill " $1 "
6 fi
7 }
8
9 has_died() {
10 if kill -0 " $1 " > /dev/null 2 >& 1 ; then
11 return 1
12 else
13 return 0
14 fi
15 }
16
17 find_pid() {
18 echo $( ps -elf | grep " $1 " | grep -v '&&' | grep -v 'grep' | awk '{print $4}' )
19 }
20
21 get_pid() {
22 pid = $( find_pid " $1 " )
23 until [ -n " ${ pid } " ] ; do
24 pid = $( find_pid " $1 " )
25 done
26 echo " ${ pid } "
27 }
28
29 # Activate venv
30 cd ~/server/blog/
31 source bin/activate
32 cd pelican/jujens.eu
33
34 regenerate_pid = ''
35 serve_pid = ''
36 # These variables cannot be used. If you try to use them, you will get an error like 3< not found.
37 #regenerate_output=3
38 #serve_output=4
39
40 while true; do
41 # Print errors for regenerate
42 if [ -n " ${ regenerate_pid } " ] && has_died " ${ regenerate_pid } " ; then
43 echo -e "Regenerate has died with ouput:\n"
44 cat <& 3
45 fi
46 # Print errors for serve
47 if [ -n " ${ serve_pid } " ] && has_died " ${ serve_pid } " ; then
48 echo -e "Serve has died with ouput:\n"
49 cat <& 4
50 fi
51
52 echo -en "(blog) > "
53 read command
54
55 case " ${ command } " in
56 deploy)
57 hg push > /dev/null
58 hg push bitbucket >/dev/null
59 stop_command " ${ serve_pid } "
60 stop_command " ${ regenerate_pid } "
61 serve_pid = ''
62 regenerate_pid = ''
63 cat <& 3 > /dev/null 2 >& 1
64 cat <& 4 > /dev/null 2 >& 1
65 make rsync_upload > /dev/null
66 ;;
67 push)
68 hg push > /dev/null
69 hg push bitbucket > /dev/null
70 ;;
71 st| status)
72 hg st
73 ;;
74 add)
75 echo "Enter the filename to add (. for all files)"
76 read file_name
77 hg add " ${ file_name } "
78 ;;
79 ci| commit)
80 echo "Please enter the commit message:"
81 read commit_msg
82 hg ci -m " ${ commit_msg } "
83 ;;
84 serve)
85 if [ -n " ${ serve_pid } " ] && ! has_died " ${ serve_pid } " ; then
86 echo "Serve is already running."
87 else
88 exec 4 < <( make serve 2 >& 1 )
89 serve_pid = $( get_pid 'python3 -m pelican.server' )
90 fi
91 ;;
92 regenerate)
93 if [ -n " ${ regenerate_pid } " ] && ! has_died " ${ regenerate_pid } " ; then
94 echo "Regenerate is already running."
95 else
96 exec 3 < <( make regenerate 2 >& 1 )
97 regenerate_pid = $( get_pid 'make regenerate' )
98 fi
99 ;;
100 "stop serve" )
101 stop_command " ${ serve_pid } " > /dev/null
102 serve_pid = ''
103 cat <& 4 > /dev/null
104 ;;
105 "stop regenerate" )
106 stop_command " ${ regenerate_pid } " > /dev/null
107 regenerate_pid = ''
108 cat <& 3 > /dev/null
109 ;;
110 stop)
111 echo "Stop requires an argument: serve or regenerate"
112 ;;
113 quit)
114 break
115 ;;
116 help )
117 echo "Available commands:"
118 echo -e "\tdeploy"
119 echo -e "\tpush"
120 echo -e "\tserve"
121 echo -e "\tregenerate"
122 echo -e "\tstop serve"
123 echo -e "\tstop regenerate"
124 echo -e "\thelp"
125 ;;
126 *)
127 if [ -n " ${ command } " ] ; then
128 echo -e " ${ command } is invalid."
129 fi
130 esac
131 done
132
133 echo "Done"
Powered by Pelican . Theme blueidea , inspired by the default theme.
Pour me contacter par e-mail : comments [at] jujens [dot] eu