mardi 8 décembre 2015

trouver des paquets sous debian dans un script

On a parfois besoin dans un script shell de trouver le nom exact d'un paquet disponible, ou en tout cas tous ceux qui pourraient convenir. Par exemple si on veut trouver les forth disponibles on peut utiliser :

aptitude search 'forth' -F '%p'

On peut trouver la liste des directives de format dont %p est un exemple.

Si aptitude n'est pas installé, on peut utiliser dpkg, mais il faut plus de travail autour pour avoir un résultat similaire :

dpkg -l '*forth*' | tail -n +6 | awk '{ print $2; }'

Si on n'est intéressé que par les paquets installés, on peut utiliser dpkg-query :

dpkg-query -f '${binary:Package}\n' -l '*forth*'

Exemple concret : trouver le nom du paquet à installer pour installer libmagickwand et y procéder.

lmw=$(aptitude search '~n^libmagickwand[0-9]' -F '%p' | head -1)
sudo aptitude install $lmw

vendredi 4 décembre 2015

un peu d'historique et de tenue

À la suite de la lecture de cet article, j'ai été amené à modifier mes fichiers .bashrc et .vimrc pour les rendre plus sympas. J'ai regardé un peu d'autres ressources et voilà finalement ce que j'ai ajouté à mon .bashrc

# no duplicate in history
export HISTCONTROL=ignoreboth:erasedups

# do not make noise. Also visible can cause delays.
set bell-style none

# Don't echo ^C etc (new in bash 4.1)
# Note this only works for the command line itself,
# not if already running a command.
set echo-control-characters off

# Enable coloring for tab completions with bash >= 4.3
set colored-stats on

# Note this must be done before the settings below
# Caveats:
#   Broken on bash 3.2 (can't move cursor to EOL).
#   ^L only works in command mode and when line is empty
set editing-mode vi
set -o vi

# By default up/down are bound to previous-history
# and next-history respectively. The following does the
# same but gives the extra functionality where if you
# type any text (or more accurately, if there is any text
# between the start of the line and the cursor),
# the subset of the history starting with that text
# is searched (like 4dos for e.g.).
# Note to get rid of a line just Ctrl-C
bind '"\e[B": history-search-forward'
bind '"\e[A": history-search-backward'

Et voici les ajoûts de mon .vimrc :

set bs=2
let g:is_posix=1
set listchars=tab:>-,trail:.,extends:> 

Les autres suggestions ne m'ont pas intéressé finalement. Pour vim, je n'ai pas vu grande différence pour l'instant, mais pour bash, c'est nettement mieux !

Mais pour vim j'ai aussi installé deux extensions assez chouettes :

  1. syntastic pour la coloration syntaxique ;
  2. vim-airline pour une belle ligne d'état (vim et gvim).

lundi 15 juin 2015

clavier Kensington keyfolio pro 2 pour IPad avec linux

Je viens d'acheter un tel clavier d'occasion, quasimment neuf. C'est le modèle pour iPad 10" mais il fonctionne très bien avec Android ou linux. L'image ci-dessous est en QWERTY (elle provient de the-gadgeeteer.com).

C'est un AZERTY de type Mac. Ceda signifie que l'équivalent dans le monde PC est un clavier belge. C'est presque pareil, la seule différence notable étant dans l'affectation de la touche à côté du chiffre 1 en haut. En belge, c'est le 2 et 3 en exposant. Très inutile pour presque tout le monde. En Mac, c'est <, > et \ qui sert tout le temps.

Sur un clavier belge à 105 touche, cette touche existe aussi : c'est celle à gauche du W en bas. Sauf qu'elle n'existe pas physiquement dans mon clavier Kensington ! Il faut y remédier !

La solution est de remettre la touche du haut déjà évoquée dans son usage Mac. Cela me donnera les symboles, en accord avec la gravure du clavier qui plus est !

Pour cela, il faut éditer le fichier /usr/share/X11/xkbd/symbols/be et voici la tranformation à y faire :

avant :
 key  { [twosuperior, threesuperior,  notsign,      notsign ] };

après :
  // key  { [twosuperior, threesuperior,  notsign,      notsign ] };
  key     { [less,        greater,        backslash,    backslash ] };

(j'ai recopiée la ligne de un peu plus bas et changé LSGT en TLDE).

Bon, il faut ensuite mettre le clavier belge dans les claviers supportés. On peut changer de clavier à la souris, mais c'est pas mal aussi au clavier. Je me suis donc créé deux raccourcis dans les préférences claviers :

clavier azerty
setxkbmap be
maj-F2
clavier bépo
setxkbmap fr bepo
maj-F1

Attention ! Le passage auclavier correspondant au clavier physique se fait toujours en tappant shift-F1 sur le clavier bépo ou le clavier Mac. C'est bizarre que ce ne soit pas identique. Attention encore, pour enregistrer la séquence de transition bépo vers azerty belge, il faut être en bépo et taper shift-F1 sur le clavier Mac. Et pour la séquence inverse azerty belge vers bépo il faut être en azerty et appuyer sur shift-F1 sur le clavier bépo (un typematrix 2030 dans mon cas). À noter que sur ce clavier typematrix, je peux faire shift-F2 pour passer en azerty quand je suis déjà en bépo. Je ne peux pas faire ça sur le clavier Kensington, assez logiquement (ce qui y serait la touche logique F1 est la touche escape donc pas de touche de code F1 sur ce clavier).

mercredi 10 décembre 2014

variables Bash : bye bye basename

édition rapide du contenu des variables sous bash et dash

Bash a un mécanisme d'édition de variables intégré permettant d'en supprimer le début ou la fin. En prime, ça peut aussi compter la longueur du contenu.

Pour supprimer le début c'est avec #. Si on prononce # « dièse », ça commence par un D comme « début ».

Pour supprimer la fin c'est avec %. Bon, on peut se dire qu'un pourcentage s'écrit avec % à la fin pour s'en souvenir.

Exemples d'utilisation

transformer un flac en ogg
sox $chanson ${chanson%.flac}.ogg
calculer la longueur d'un mot
echo $mot fait ${#mot} char. de long
afficher le début d'un texte
echo début du texte : ${texte:0:30}
évaluer le chemin du script exécuté
chemin=${0%/*}
évaluer le chemin du script exécuté, complété pour le cas des liens symboliques
this=$(readlink -e $0)
chemin=${this%/*}
afficher le seul nom du script exécuté
echo ${0##*/}
supprimer un éventuel / final à un nom de répertoire
repertoire=${repertoire%/}

Tout cela fonctionne aussi avec dash !

Une petite colle maintenant : si votre script est appelé par la commande point (.) alors $0 n'est pas le nom de votre script mais celui du shell appelant ou du script appelant. Comment récupérer le nom du script dans ce cas-là ? Je n'en sais rien !

un petit exemple concret

Le programme suivant permet d'éditer en mode comparaison tous les couples de fichiers de même nom dans deux répertoires différents, en se restreignant au seul cas où ils ont un contenu différent. C'est un script dash pour plus de radipité au lancement. L'éditeur utilisé est vim ou gvim (sous la forme vimdiff ou gvimdiff).

#!/bin/sh

# édite les fichiers de même nom dans deux répertoires mais différents

usage() {
  echo "usage: ${0##*/} [-g] dir01 dir02"
  echo "Edit same files in both directories with different contents only."
  echo "With -g use gvimdiff instead of vimdiff."
  exit 1
}

editor=vimdiff
if [ "$1" = '-g' ] ; then
  editor=gvimdiff
  shift
fi
[ $# -eq 2 ] || usage
dir01="${1%/}"
dir02="${2%/}"
ndiff=0
ntotal=0

compare() {
  if [ -f $2 ] ; then
    ntotal=$((ntotal+1))
    if ! cmp --quiet $1 $2 ; then
      #echo '!=' DIFF $1 $2
      $editor $1 $2
      ndiff=$((ndiff+1))
    fi
  fi
}

files=$(find "$dir01" -maxdepth 1 -type f)
for f01 in $files ; do
  f02=$dir02/${f01##*/}
  compare $f01 $f02
done
echo "$ndiff couples of files were different out of $ntotal."

jeudi 27 novembre 2014

Créer un sous-DBA sous mysql pour le dév

Il s'agit de créer un utilisateur dev qui a presque tous les droits sous mysql. On trouve de tels articles tout plein dans le web, mais celui-ci est taillé sur mesure pour mes besoins !

Avant de commencer, un petit truc pour phpmyadmin : on peut entièrement le reconfigurer, y compris si la base phpmyadmin a été abimée, avec :

sudo dpkg-reconfigure phpmyadmin

Il s'agit tout simplement de créer l'utilisateur dev et ensuite de lui donner ses pouvoirs. Rien de sorcier. 4 lignes de SQL suffisent :

flush privileges;
create user 'dev'@'localhost' identified by 'password';
grant create, drop, delete, insert, select, update, alter, index on *.* to 'dev'@'localhost';
flush privileges;
Le premier flush privileges; permet de recréer l'utilisateur dev si on vient de le supprimer. Le deuxième permet de s'en servir à coup sûr.

mercredi 26 novembre 2014

URL rewriting avec Apache pour Zend 1.x

J'ai eu beaucoup de mal à faire fonctionner le moindre exemple d'application avec Zend 1.x. Zend est un framework PHP qui ne marche qu'avec de l'URL rewriting et je n'en n'avais jamais fait. Mais j'avais déjà fait des configuration Apache avec VirtualHost aussi ai-je dès le départ mis en place un virtual host. Voir mon billet précédent sur la configuration d'Apache2 avec VirtualHost.

J'ai donc une URL applicative sur ma machine qui se nomme guestbook.machine.chez.moi et à cette URL correspond le contrôleur IndexController. Un synonyme de cet URL est guestbook.machine.chez.moi/index puisqui index est le désignateur de ce contrôleur dans une URL Zend. Oui mais voilà, chez moi cette deuxième ne marchait pas et j'avais une erreur 404 générée par Apache. Idem avec guestbook.machine.chez.moi/bidon.

Je finis par découvrir qu'en fait c'était parce que le fichier .htaccess que Zend avait créé pour assurer l'URL rewriting n'était pas pris en comptes parce que dans mon fichier de configuration Apache de l'application /etc/apache2/sites-available/guestbook j'avais d'actif un Options none alors qu'il fallait y mettre un FollowSymLinks. Mais je me suis contenté, bêtement, de recopier le bout de config donné là où j'ai trouvé cette information, à savoir Options Indexes MultiViews FollowSymLinks sans remarquer le MultiViews dont j'ignorais le rôle. Mais ça ne marchait toujours pas mieux…

Le log d'Apache m'informe de son refus de collaborer avec une ligne telle que :

[Wed Nov 26 15:31:52.624341 2014] [negotiation:error] [pid 10160] [client 127.0.0.1:43836] AH00687: Negotiation: discovered file(s) matching request: /home/geek/workspace/guestbook/public/index (None could be negotiated).

Mais je n'ai pas de fichier ou répertoire index, seulement un fichier index.php à la racine Apache du serveur. En gooolant le message d'erreur je trouve la cause et la solution : c'est ce foutu Multiviews qui fait coïncider index.php avec index et cela empêche l'URL rewriting conditionnel mis en place par Zend (pas d'URL rewriting si l'URL pointe sur un fichier existant). Il faut supprimer Multiviews et tout va pour le mieux. Voici donc ma configuration du VirtualHost avec les droits réduits au minimum :

<VirtualHost *:80>
  ServerName guestbook.machine.chez.moi
  DocumentRoot /home/geek/workspace/guestbook/public
  DirectoryIndex index.php
  <Directory />
    Options none
    AllowOverride None
    Require all denied
  </Directory>
  <Directory /home/geek/workspace/guestbook/public>
    Options FollowSymLinks SymLinksIfOwnerMatch
    AllowOverride None
    Require all granted
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} -s [OR]
    RewriteCond %{REQUEST_FILENAME} -l [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^.*$ - [NC,L]
    RewriteRule ^.*$ index.php [NC,L]
  </Directory>
  ErrorLog /var/log/apache2/guestbook.log
  LogLevel warn
  CustomLog /var/log/apache2/guestbook.log combined
</VirtualHost>
La directive AcceptPathInfo est inutile, mais je l'ai mise pour me rappeler que c'est finalement le mécanisme induit qui est utilisé par défaut dans ce cas. Comme je n'ai pas mis FollowSymLinks je pourrais aussi enlever RewriteCond %{REQUEST_FILENAME} -l [OR] qui devient un test inutile.

Si on utilise un fichier .htaccess alors son contenu est celui généré par Zend :

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
et le contenu de /etc/apache2/sites-available/guestbook est :
<VirtualHost *:80>
  ServerName guestbook.machine.chez.moi
  DocumentRoot /home/geek/workspace/guestbook/public
  DirectoryIndex index.php
  <Directory />
    Options none
    AllowOverride None
    Require all denied
  </Directory>
  <Directory /home/geek/workspace/guestbook/public>
    Options FollowSymLinks SymLinksIfOwnerMatch
    AllowOverride All
    Require all granted
  </Directory>
  ErrorLog /var/log/apache2/guestbook.log
  LogLevel warn
  CustomLog /var/log/apache2/guestbook.log combined
</VirtualHost>

mardi 28 octobre 2014

première version alpha de Blood and Blades



Eh non, ce ne sera pas encore aujourd'hui je vais vous parler de Blood and Blades ! C'est une règle de jeu d'histoire avec figurines de mon invention. Je me dois d'avouer tout de suite qu'elle doit beaucoup à DBM, DBMM et Armati, tout en visant une bataille de la taille et de la durée d'une partie d'ADG. Elle est en anglais pour ne pas rester franco-française. Mais surtout elle est sous licence libre CC-BY-SA tout en utilisant les listes d'armée DBMM ou DBM.

Voici la règle Blood and Blades sous forme d'un wiki. Enregistrez la cible de ce lien comme un fichier html et ouvrez-le.  Il faut autoriser le javascript pour pouvoir lire la règle. Je sais devoir entreprendre la réalisation d'une version PDF.

Tout retour est le bienvenu, sur le fond comme sur la forme. N'hésitez pas ! Et merci d'avance pour toute aide qui me parviendra !

(crédit photo «cutter & blood» par gaelx http://www.flickr.com/photos/7574080@N08/3236415581 CC-BY-SA)

mise à jour du 10/04/2013 : j'ai mis une version avec quelques changements que j'avais oublié de faire hier : escape --> flee et cluster --> group notamment.

mise à jour du 28/10/2014 <: le lien sur la règle a été changé pour une version plus récente. Et voici les liens pour la version epub (avec graphismes vectoriels SVG) et la version pdf A4.