Skip to content

Administration Système

wxPython ( on OS X El Capitan (10.11)

Since OS X 10.11 (El Capitan), the lastest version of the available wxPython dmg ( have an unsupported pkg structure. You can see an open bug at

Thanks to memoselyk@stackoverflow we can convert manually the package structure to be able to install it : ; you can find an updated version of the method below :

Installing wxPython- on OS X El Capitan :

# base workdir
mkdir ~/wxpython_elcapitan
cd ~/wxpython_elcapitan

# download the wxPython dmg
curl -L "" -o wxPython3.0-osx-

# mount the dmg
hdiutil attach wxPython3.0-osx-

# copy the dmg package to the local disk
mkdir ~/wxpython_elcapitan/repack_wxpython
cd ~/wxpython_elcapitan/repack_wxpython
cp -r /Volumes/wxPython3.0-osx- .

# unmount the dmg
dmgdisk="$(hdiutil info | grep '/Volumes/wxPython3.0-osx-' | awk '{ print $1; }')"
hdiutil detach ${dmgdisk}

# prepare the new package contents
mkdir ~/wxpython_elcapitan/repack_wxpython/pkg_root
cd ~/wxpython_elcapitan/repack_wxpython/pkg_root
pax -f ../wxPython3.0-osx-cocoa-py2.7.pkg/Contents/Resources/wxPython3.0-osx-cocoa-py2.7.pax.gz -z -r
cd ~/wxpython_elcapitan/repack_wxpython

# prepare the new package scripts
mkdir ~/wxpython_elcapitan/repack_wxpython/scripts
cp wxPython3.0-osx-cocoa-py2.7.pkg/Contents/Resources/preflight scripts/preinstall
cp wxPython3.0-osx-cocoa-py2.7.pkg/Contents/Resources/postflight scripts/postinstall

# delete the old package
rm -rf ~/wxpython_elcapitan/repack_wxpython/wxPython3.0-osx-cocoa-py2.7.pkg

# build the new one :
pkgbuild --root ./pkg_root --scripts ./scripts --identifier com.wxwidgets.wxpython wxPython3.0-osx-cocoa-py2.7.pkg

# put the package on Desktop, and clean workdir
mv ~/wxpython_elcapitan/repack_wxpython/wxPython3.0-osx-cocoa-py2.7.pkg ~/Desktop/
cd ~
rm -rf ~/wxpython_elcapitan

# install it ! it will ask for your password (to become superuser/root)
sudo installer -pkg ~/Desktop/wxPython3.0-osx-cocoa-py2.7.pkg -target /


wxPython is now available on your OS X El Capitan :

$ python -c “import wx ; print wx.version()” osx-cocoa (classic)

Using wxPython in a VirtualEnv :

OS X is now restricting screen access to a trusted list of Frameworks and binaries, and a standard VirtualEnv is not enought :

This program needs access to the screen.
Please run with a Framework build of python, and only when you are
logged in on the main display of your Mac.

Thanks to the wxPython wiki, we can find some ways to solve that :
See :

Below, a quick solution, assuming that you don’t want system packages in your virtual env :

mkdir ~/dev
cd ~/dev
virtualenv --python=python2.7 --distribute --no-site-packages --unzip-setuptools myvirtualenv
source ~/dev/myvirtualenv/bin/activate
ln -s /Library/Python/2.7/site-packages/wxredirect.pth ~/dev/myvirtualenv/lib/python2.7/site-packages/wxredirect.pth

And now you must use the system python interpreter, instead the one in your virtual env, you should use a script, a wrapper, or modify activate script, but the minimum is :

PYTHONHOME="/Users/davixx/dev/myvirtualenv/" /usr/bin/python -c "import wx ; app = wx.App()"

Have a nice day with Mercy – MUSE

mydumper-0.6 views dump and restore

Hi readers, i hope you are listening to the MUSE Drones Album,

The mydumper-0.6.2 (the current stable version) is not dumping views… Thankfully, the 0.9 branch (not stable at now) will… (MyDumper – Add support for all schema objects)

The question is, how to safely backup theses views (without using a beta version of mydumper) ?

I search into the myloader.c source code how the regular tables have theirs schema restored, and luckily, in the following function :

void restore_data(MYSQL *conn, char *database, char *table, const char *filename, gboolean is_schema);

we can see that the content of the schema dump file is ready and executed without special verification :

// [...]
if (!is_schema)
    mysql_query(conn, "START TRANSACTION");

while (eof == FALSE) {
    if (read_data(infile, is_compressed, data, &eof)) {
        // Search for ; in last 5 chars of line
        if (g_strrstr(&data->str[data->len >= 5 ? data->len - 5 : 0], ";\n")) {
            if (mysql_real_query(conn, data->str, data->len)) {
                g_critical("Error restoring %s.%s from file %s: %s", db ? db : database, table, filename, mysql_error(conn));
            if (!is_schema &&(query_counter == commit_count)) {
                query_counter= 0;
                if (mysql_query(conn, "COMMIT")) {
                    g_critical("Error committing data for %s.%s: %s", db ? db : database, table, mysql_error(conn));
                mysql_query(conn, "START TRANSACTION");

            g_string_set_size(data, 0);
    } else {
        g_critical("error reading file %s (%d)", filename, errno);
if (!is_schema && mysql_query(conn, "COMMIT")) {
    g_critical("Error committing data for %s.%s from file %s: %s", db ? db : database, table, filename, mysql_error(conn));
// [...]

That mean we can generate – by any way we want – a fake schema-dump file, but with a query creating a view.

For that,  i first thought of patching mydumper.c ; but as mydumper-0.9 (not stable at now) already support this feature, i will prefer another solution.

I’ve made a modest python script which list view and generate files named database.view_name-schema.sql into the mydumper dump dir. With that, myloader will consider thoses files as regular table schema create statements.

Please note that i force a DROP VIEW IF EXISTS into the dump file…

#!/usr/bin/python2.7 -u

import MySQLdb
import os

# settings
MARIADB_USER = 'a_readonly_user'
MARIADB_PASS = 'a_good_password_MU5E_D3AD_IN7ID3_%!@'
MARIADB_SCKT = ''  # empty for TCP , or path if socket (host must be localhost)
MYDUMPER_DUMP_DIR = '/tmp'  # the path of the dump already done by mydumper

# connection to the MariaDB server
mariadb_connection = MySQLdb.connect(

# creating cursors
views_list_cursor = mariadb_connection.cursor()
show_create_view_cursor = mariadb_connection.cursor()

# ask MariaDB for the views list
views_list_cursor.execute("SELECT `table_schema`, `table_name` FROM `tables` WHERE `table_type` = 'VIEW'")

for database, view in views_list_cursor:
    # and handle each results
    show_create_view_cursor.execute("SHOW CREATE VIEW `{}`.`{}`".format(database, view))
    view, create_view_stmt, character_set_client, collation_connection = show_create_view_cursor.fetchone()
    dump_file = os.path.join(MYDUMPER_DUMP_DIR, '{}.{}-schema.sql'.format(database, view))
    assert not os.path.exists(dump_file)
    with open(dump_file, 'w') as f:
        fwrite('DROP VIEW IF EXISTS `{}`.`{}`;'.format(database, view))

# release cursors and close the MariaDB connection

Feel free to make it PEP8, or with better error handling. Actually, the return code will be 0 only if everything seems good.

MariaDB, plugin-load et la table mysql.plugin

Bonne journée à tous en ce début de semaine et de mois :)
Bonne nouvelle, le futur album #Drones de MUSE va paraître en Juin 2015 ; et un single #Psycho risque de sortir dans quelques semaines.

Le problème

Avec MariaDB <=10.0.16 ; lorsque vous utilisez des “storage engine” reposant sur des plugins (comme Spider, TokuDB) vous pouvez être confrontés à ce genre de message d’erreur dans mysqld.err lors du démarrage de mysqld :

150302 9:09:58 [Note] Plugin 'FEEDBACK' is disabled.
150302 9:09:58 [ERROR] Function 'TokuDB' already exists
150302 9:09:58 [Warning] Couldn't load plugin named 'TokuDB' with soname ''.
150302 9:09:58 [ERROR] Function 'TokuDB_trx' already exists
150302 9:09:58 [Warning] Couldn't load plugin named 'TokuDB_trx' with soname ''.
150302 9:09:58 [ERROR] Function 'TokuDB_lock_waits' already exists
150302 9:09:58 [Warning] Couldn't load plugin named 'TokuDB_lock_waits' with soname ''.
150302 9:09:58 [ERROR] Function 'TokuDB_locks' already exists
150302 9:09:58 [Warning] Couldn't load plugin named 'TokuDB_locks' with soname ''.
150302 9:09:58 [ERROR] Function 'TokuDB_file_map' already exists
150302 9:09:58 [Warning] Couldn't load plugin named 'TokuDB_file_map' with soname ''.
150302 9:09:58 [ERROR] Function 'TokuDB_fractal_tree_info' already exists
150302 9:09:58 [Warning] Couldn't load plugin named 'TokuDB_fractal_tree_info' with soname ''.
150302 9:09:58 [ERROR] Function 'TokuDB_fractal_tree_block_map' already exists
150302 9:09:58 [Warning] Couldn't load plugin named 'TokuDB_fractal_tree_block_map' with soname ''.

Cela est du au fait que mysqld tente une seconde fois de charger le même plugin (ici tokudb).

Fort probable, vous avez dans votre my.cnf une configuration comme :


La première fois que vous avez démarré mysqld avec ces instructions, et jusqu’à que MariaDB l’installe dans ses tables systèmes, rien à signaler dans le mysqld.err

Mais aussitôt que vous aurez – par exemple – instancié une table TokuDB, alors MariaDB ajoute TokuDB dans sa table mysql.plugin pour charger automatiquement l’extension au prochain chargement de mysqld (ce qui fera doublon à la configuration du my.cnf) :

MariaDB [mysql]> select * from mysql.plugin where dl = '';
| name                          | dl           |
| TokuDB                        | |
| TokuDB_trx                    | |
| TokuDB_lock_waits             | |
| TokuDB_locks                  | |
| TokuDB_file_map               | |
| TokuDB_fractal_tree_info      | |
| TokuDB_fractal_tree_block_map | |
7 rows in set (0.00 sec)

La solution court-terme

Retirer “plugin-load=ha_tokudb” de votre my.cnf

Le problème de la solution

Que se passera-t’il le jour où vous démarrerez mysqld avec un datadir complètement vide, dans le but, par exemple, de restaurer une sauvegarde ?

L’import échouera lorsque il rencontrera une table TokuDB, parce qu’il ne connaitra pas le “storage engine” (le plugin correspondant n’aura pas été chargé).

Il faudra alors soit :

  • remettre la configuration dans le my.cnf ; re-démarrer mysqld ; retirer la configuration du my.cnf ; et faire l’import de votre sauvegarde
  • penser à charger le plugin – manuellement – avant l’import – avec l’instruction suivante :
INSTALL SONAME 'ha_tokudb'

Des idées de solutions long-terme


MariaDB devrait accepter que my.cnf et mysql.plugin fassent référence au même plugin, et que MariaDB soit assez intelligent pour ignorer la situation, en se basant à minima sur le nom du fichier, ou un checksum du .so

MyDumper / MysqlDump

Les outils de sauvegarde (notamment ceux cités) devraient s’assurer qu’en tête des instructions qui seront exécutés pour restaurer un “backup” ; des routines soient présentes pour charger – si nécessaire – les plugins qui seront ultérieument nécessaire, notamment pour des tables et leurs “storage engine”.



J’ai poussé les idées en question auprès du support de MariaDB.

Voir aussi :


Python-3.4 sur ma Gentoo habituée à Python-2.7

A la découverte de Python-3.4.0 sur une de mes install Gentoo :) A ce jour (17/05/2014) Python-3.4 est encore masqué sous Gentoo, je vais l’installer sans modifier (volontairement) le package.keywords :

ACCEPT_KEYWORDS="~amd64" emerge -av =python-3.4*

[ebuild  NS    ] dev-lang/python-3.4.0:3.4 [2.7.5-r3:2.7, 3.3.3:3.3] USE="gdbm ipv6 ncurses readline sqlite ssl threads xml -build -examples -hardened -tk -wininst" 13,768 kB
GNU/Linux Magazine 171 (Mai 2014)
GNU/Linux Magazine 171 (Mai 2014)

J’utilisais jusque là python-2.7 uniquement, entendant ici ou là (notamment avec les développeurs Ansible) que Python >= 3.0 s’apparentait plutôt à un nouveau language qu’à une évolution de ce dernier.

C’est en lisant GNU/Linux Magazine 171 (Mai 2014) que je me retrouve tenté d’essayer la version 3.4  – entre-autres pour le module asyncio…

J’en profite par ailleurs pour parler de ce “Dr KissCool” visiblement adepte du troll et accompagné d’un humour de second et troisième degré. Je n’aime pas ce rédacteur, je ne remet pas en cause ses éventuels talents dans le domaine, mais je ne prends presque aucun plaisir à lire son blah blah trop souvent éloigné à mon goût de l’information technique recherchée dans ce genre de Mag.

Mes contenus sur ce blog sont probablement moins pertinents avec plus de fautes d’orthographes et grammaticales, mais personne ne paye pour les lires

Je n’oublie pas ensuite d’aller modifier le PYTHON_TARGETS dans make.conf que Gentoo consultera pour déterminer les version de python concernées par l’installation de nouveaux modules  :

PYTHON_TARGETS="python2_7 python3_3 python3_4"

Il faudrait ensuite théoriquement demander à Gentoo la recompilation de tous les modules python pour prendre en compte cette nouvelle branche :

 * You have just upgraded from an older version of Python.
 * Please adjust PYTHON_TARGETS (if so desired), and run emerge with the --newuse or --changed-use option to rebuild packages installing python modules.

Tiens donc, jusque là, Gentoo préconisait l’utilisation de l’outil python-updater pour ça ; mais effectivement le résultat n’a pas l’air d’être pertinent :

# python-updater -- --pretend --tree --verbose
 * Starting Python Updater...
 * Main active version of Python:    2.7
 * Active version of Python 2:       2.7
 * Active version of Python 3:       3.3
 * Globally supported Python ABIs in installed repositories:
 *   gentoo:                         2.4 2.5 2.6 2.7 3.1 3.2 3.3 2.5-jython 2.7-jython 2.7-pypy-1.7 2.7-pypy-1.8 2.7-pypy-1.9 2.7-pypy-2.0
 *   sdfoverlay:                     2.4 2.5 2.6 2.7 3.1 3.2 3.3 2.5-jython 2.7-jython 2.7-pypy-1.7 2.7-pypy-1.8 2.7-pypy-1.9 2.7-pypy-2.0
 *   Adding to list: sys-libs/cracklib:0
 * emerge -Dv1 --keep-going sys-libs/cracklib:0 --pretend --tree --verbose

These are the packages that would be merged, in reverse order:

Calculating dependencies... done!
[ebuild     U  ] sys-libs/cracklib-2.9.1 [2.8.19] USE="nls zlib -python -static-libs {-test%} (-build%)" PYTHON_TARGETS="python2_7%* (-python2_6)" 621 kB

Total: 1 package (1 upgrade), Size of downloads: 621 kB

par ailleurs, on constate que python-3.4 ne semble pas être listé dans les “Globally supported ABIs” ; cela à t’il donc un intérêt de recompiler les modules avec emerge ? essayons avec dev-python/django pour commencer :

emerge -av dev-python/django

[ebuild     U  ] dev-python/django-1.4.11 [1.4.8] USE="vhosts -mysql -postgres -sqlite {-test} (-doc%)" PYTHON_TARGETS="python2_7 (-python2_6%)" 7,571 kB
# equery files dev-python/django | grep 2.7 | tail -n 1
# equery files dev-python/django | grep 3.4 | tail -n 1

à priori non, alors je m’arrête là et j’utilise python3.4 pour mes tests sans me soucier (et sans que cela ne perturbe) mes install stable via portage de python2.7 et python3.4 … Désolé si ce post est… inutile…

# python3.4
Python 3.4.0 (default, May 17 2014, 11:59:14)
[GCC 4.7.3] on linux
Type "help", "copyright", "credits" or "license" for more information.

Grub2 with GPT and BIOS on Gentoo

Too long time holding Grub2, and using Grub (called now “grub-legacy”).

On a fresh installed Gentoo system, here the links i used to setup it


The importants things is that on a BIOS based system (not EFI), and using GPT partitions, you need to give grub a dedicated partition permitting him to store the “second stage” ; (in grub legacy, this code was placed on a kind of unofficial MBR extra-space).

Secondly, i don’t like the way that Grub2 is defaultly provided on linux distributions : /etc/grub.d/* now hold scripts executed in alphabetic order, and their outputs are concatenated to build the configuration. (Note that /etc/defaults/grub also hold some new configuration entries instead keeping theses variables in /etc/grub.d scripts).

To be opposite as myself few lines after, it’s not a bad way to proceed, so let’s go with that :

# kernel-default is not a special kernel name
#  searched by grub2 scripts
# but grub2 scripts search only
#  kernels starting by "kernel-" and "vmlinuz-"

cd /boot
ln -s linux-3.4.56 kernel-default

# partitioning a disk for Grub2 over BIOS/GPT :

# be sure to have an empty GPT partition table :
parted --script --align optimal /dev/sda mklabel gpt
parted --script --align optimal /dev/sda mklabel msdos
parted --script --align optimal /dev/sda mklabel gpt

# our partition needed because of grub2 overs BIOS/GPT
parted --script --align optimal /dev/sda mkpart primary ext2 0% 8MiB

# /boot
parted --script --align optimal /dev/sda mkpart primary ext2 8MiB 192MiB

# swap and root
parted --script --align optimal /dev/sda mkpart primary linux-swap 192MiB 704MiB
parted --script --align optimal /dev/sda mkpart primary ext3 704MiB 100%

# make /boot flagged "boot"
parted --script --align optimal /dev/sda set 2 boot on

# make /dev/sda1 out bios_grub partition
parted --script --align optimal /dev/sda set 1 bios_grub on

# check everything
parted --script --align optimal /dev/sda print

# will install grub files in /boot/grub
grub2-install --grub-setup=/bin/true /dev/sda

# will execute /etc/grub.d scripts
grub2-mkconfig -o /boot/grub/grub.cfg

# writing boot sector 
grub2-install /dev/sda

Hope this will help someone :)

socat permitting MySQL migration

Fast idea using socat (loosed as draft since 2013-02-01) to quickly migrate a tcp and/or unix socket MySQL installation. (socat- used for the test).

If the need is temporary, this avoid a MySQL Proxy setup.

Launch that as a daemontools service (for example):

1. /service/socat-mysql-tcp/run

exec setuidgid mysql socat -d TCP4-LISTEN:${bind_port},bind=${bind_addr},fork TCP4:${forward_host}:${forward_port}

2. /service/socat-mysql-unixsocket/run

exec setuidgid mysql socat UNIX-LISTEN:${sock},fork TCP4:${forward_host}:${forward_port}

ansible – sysctl module

The first version of my sysctl module for ansible have been merged to the devel tree of the mainstream ansible projet (on github) by mpdehaan.

You can now use easily this sysctl module :

  • by using git pull, if you have installed ansible by a simple git clone
  • by downloading manually sysctl in the library subdirectory of your playbooks :
cd /path/to/my/playbooks
[ -d "library" ] || mkdir -v library
wget -O library/sysctl
Ansible Servers Orchestration
Ansible is the easiest way to deploy, manage, and orchestrate computer systems you’ve ever seen. You can get started in minutes

After that, you can now use the sysctl module in your playbooks (extracted from the embedded documentation) :

  • Set vm.swappiness to 5 in /etc/sysctl.conf
    (first, check if /proc/sys/vm/swappiness file exist and is writteable, and after change, call sysctl -p and verify if /proc/sys/vm/swappiness file content is now 5) :
sysctl: name=vm.swappiness value=5 state=present
  • Remove kernel.panic entry from /etc/sysctl.conf
sysctl: name=kernel.panic state=absent sysctl_file=/etc/sysctl.conf
  • Set kernel.panic to 3 in /tmp/test_sysctl.conf, check if the sysctl key seems writable, but do not reload sysctl, and do not check kernel value after (not needed, because it is not the real /etc/sysctl.conf updated) :
sysctl: name=kernel.panic value=3 sysctl_file=/tmp/test_sysctl.conf check=before reload=no

gentoo fcron and system crontab

After a new install of gentoo with fcron-3 :

  • there is no /etc/crontab file ; and is it wanted (by default).
  • also, system crontab must not be setup in root crontab’s, but in systab  crontab, using the check_system_crontabs tool.
  • finally, note that by default, /etc/cron.* is not handled by fcron.

So, if you wanna to add support for /etc/cron.* you can :

  • Add this line in a new /etc/crontab (or in an existing if there is no equivalent lines already) :
%hourly * /bin/run-parts /etc/cron.hourly
%daily * * /bin/run-parts /etc/cron.daily
%weekly * * /bin/run-parts /etc/cron.weekly
%monthly * * * /bin/run-parts /etc/cron.monthly
  • Last point do nothing, just a file is updated, not any crontab.
  • Now you call the tool :
check_system_crontabs -v -i -f
  • This command will create or update dynamically the crontab of the systab user (needed by fcron for system crontab, created by the gentoo ebuild)
  • You can after check that the generated systab crontab is the concatenation of your /etc/crontab, any /etc/cron.d/ entry, and a call to the check_system_crontabs tool himself to update – if needed – the crontab – every ten minutes (in fact, for this laspoint, he use the content of /etc/fcron/fcrontab file) :
fcrontab -usystab -l

Découverte d’ansible – Orchestration de serveurs

Bonjour !

Je viens de découvrir ansible, et j’ai décidé de tenter de l’utiliser, pendant quelques mois, pour mes besoins personnels et pour certains clients.

Pourquoi ansible au lieu de Opscode Chef  ou Puppet ou CFEngine pour gérer le parc de configuration, le déploiement de logiciels, et autres ?

Sincèrement je n’ai pas de raisons majeures à ce stade, je fais les choses au feeling, je n’ai pas assez d’expérience dans les alternatives citées pour les juger.

Ansible Servers Orchestration powerfull tools
Ansible Servers Orchestration powerfull tools

Par contre, voici les premiers plus qui m’ont attirés et qui m’ont menés là : (sans pour autant sous-entendre que les alternatives ne peuvent pas, dans certains cas, en faire autant)

  • une architecture reposant sur ssh, l’installation d’aucun agent sur chacun des nodes n’est nécessaire.
  • une architecture modulaire, dans laquelle un script bash, python, php, ou encore un binaire peuvent être utilisés de manière transparente.
  • un mode had-hoc, avec lequel je peux – par exemple – déployer en une seule ligne de commande, propager un nouveau réglage pour la conntrack sur un pool de 45 serveurs.
  • un mode playbook, avec lequel je modélise des configurations idempotentes partielles et/ou totales de serveurs que je peux ensuite appliquer sans avoir la nécessité d’être un développeur, le playbook ressemble plus à une documentation rédigé au format yaml plutôt qu’un script en ruby.
  • pas d’abstraction sur le système d’exploitation des nodes et de son gestionnaire de paquets ; et cela volontairement ; pourquoi ? la pluralité des OS fait que certaines distributions Linux par exemple, ont des particularités qui sont valorisables. Reposer sur un outil qui ne retiendrait que le plus petit dénominateur de chaque distribution serait une sorte de gaspillage.

Et donc ?

Le projet ansible est récent (environ 1 an) initié – entre autres – par Michael DeHaan (un développeur ayant un historique dans les outils d’orchestration/industrialisation)

Ansible est disponible sur GitHub, je l’ai forké pour pouvoir contribuer en développant le module sysctl en un premier temps, et pour le module emerge (gestionnaire de paquet de Gentoo) en un second temps.