You can modify the behavior of Kiwi with adding a plug-in in the software. Plug-ins can perform actions at predefined moments:

  • When the app starts

  • When a backup is launched

  • When a backup process iterates on a file

  • When a backup ends

Writing a plug-in

Create a plug-in on your own is pretty simple. Plug-ins are stored in your data directory. under the plugins/[your plugin name] directory.

Plug-in structure

The plug-in can act at four moments in the code, and there are the four functions that you can write corresponding to these four moments. The backup process shares data about the current backup to plug-ins, and a plug-in itself could change this data. This is how a plug-in can really interact with the backup process.

When app starts

def on_server_start():
    """Launched when the backup is started"""

When backup starts/stops

def on_backup_start(context):
    """Launched when backup starts

    :param context: shared context of the backup
def on_backup_stop(context):
    """Launched when backup stops

    :param context: shared context of the backup

When backup iterates on a file

def on_file(kfile, context):
    """Launched when backup stops

    :param kfile: kfile of the current iteration
    :param context: shared context of the backup


This example is a very simple plug-in that executes a script file at a backup start or stop. The execution is cross-platform. There can be a lot of improvements (asynchronous/synchronous, arguments to script …) but let’s begin with an easy one. You must create a file in your plugin directory with the name “” with the following code:


import kclient
from kclient import bos
import os
import subprocess

from logging import getLogger

logger = getLogger('kclient.runner')

PLUGIN_ROOT = os.path.join(kclient.bos.getPluginsDir(),

def launch_script(filepath):
    """ Cross-platform script launching """
    if kclient.bos.isWin32():
        filepath += '.bat'
    elif kclient.bos.isLinux() or kclient.bos.isOsX():
        filepath += '.sh'
    script_fullpath = os.path.join(PLUGIN_ROOT, filepath)
    if os.path.exists(script_fullpath):
        logger.warning('execute %s', script_fullpath)
        return True
        logger.error('cannot execute missing script %s', script_fullpath)
        return False

def on_start_backup(context):
    if not launch_script('pre_backup'):
        logger.error('can not launch pre-backup script')

def on_stop_backup(context):
    if not launch_script('post_backup'):
        logger.error('can not launch pre-backup script')

In your data directory, under plugins/script-launcher, put two files: (post|pre)_backup.(bat|sh). If there is no script the plug-in will log it and the backup will continue.

Database state handling

Imagine you have a database that you need to save. This database holds a lot of very sensitive data. Because the database is open, you can not save it. So you need to manually close it before going to bed and re-open it at 2:00 AM when the backup is done (because data is very important to the functionality of your site).

If you are in the case above, here is an example of how useful this example is in case you use mysql.

The first script below executed before the backup starts closes the database. The second one re-open it at the end.

#! /bin/sh

service mysql stop

#! /bin/sh

service mysql start