Debugging Lua Scripts With the Lua Debugger
KeyDB includes a complete Lua debugger, that can be used in order to make the task of writing complex KeyDB scripts much simpler.
The KeyDB Lua debugger, codename LDB, has the following important features:
- It uses a server-client model, so it's a remote debugger. The KeyDB server acts as the debugging server, while the default client is
keydb-cli. However other clients can be developed by following the simple protocol implemented by the server.
- By default every new debugging session is a forked session. It means that while the KeyDB Lua script is being debugged, the server does not block and is usable for development or in order to execute multiple debugging sessions in parallel. This also means that changes are rolled back after the script debugging session finished, so that's possible to restart a new debugging session again, using exactly the same KeyDB data set as the previous debugging session.
- An alternative synchronous (non forked) debugging model is available on demand, so that changes to the dataset can be retained. In this mode the server blocks for the time the debugging session is active.
- Support for step by step execution.
- Support for static and dynamic breakpoints.
- Support from logging the debugged script into the debugger console.
- Inspection of Lua variables.
- Tracing of KeyDB commands executed by the script.
- Pretty printing of KeyDB and Lua values.
- Infinite loops and long execution detection, which simulates a breakpoint.
A simple way to get started with the Lua debugger is to watch this video introduction by redis (same commands but use keydb instead of redis):
Important note: please make sure to avoid debugging Lua scripts using your KeyDB production server. Use a development server instead. Also note that using the synchronous debugging mode (which is NOT the default) results into the KeyDB server blocking for all the time the debugging session lasts.
To start a new debugging session using
keydb-cli do the following steps:
Create your script in some file with your preferred editor. Let's assume you are editing your KeyDB Lua script located at
Start a debugging session with:
./keydb-cli --ldb --eval /tmp/script.lua
Note that with the
--eval option of
keydb-cli you can pass key names and arguments to the script, separated by a comma, like in the following example:
You'll enter a special mode where
keydb-cli no longer accepts its normal
commands, but instead prints a help screen and passes the unmodified debugging
commands directly to keydb.
The only commands which are not passed to the KeyDB debugger are:
quit-- this will terminate the debugging session. It's like removing all the breakpoints and using the
continuedebugging command. Moreover the command will exit from
restart-- the debugging session will restart from scratch, reloading the new version of the script from the file. So a normal debugging cycle involves modifying the script after some debugging, and calling
restartin order to start debugging again with the new script changes.
help-- this command is passed to the KeyDB Lua debugger, that will print a list of commands like the following:
Note that when you start the debugger it will start in stepping mode. It will stop at the first line of the script that actually does something before executing it.
From this point you usually call
step in order to execute the line and go to the next line. While you step KeyDB will show all the commands executed by the server like in the following example:
<reply> lines show the command executed by the line just
executed, and the reply from the server. Note that this happens only in stepping mode. If you use
continue in order to execute the script till the next breakpoint, commands will not be dumped on the screen to prevent too much output.
#Termination of the debugging session
When the scripts terminates naturally, the debugging session ends and
keydb-cli returns in its normal non-debugging mode. You can restart the
session using the
restart command as usual.
Another way to stop a debugging session is just interrupting
manually by pressing
Ctrl+C. Note that also any event breaking the
keydb-cli and the
keydb-server will interrupt the
All the forked debugging sessions are terminated when the server is shut down.
#Abbreviating debugging commands
Debugging can be a very repetitive task. For this reason every KeyDB debugger command starts with a different character, and you can use the single initial character in order to refer to the command.
So for example instead of typing
step you can just type
Adding and removing breakpoints is trivial as described in the online help.
b 1 2 3 4 to add a breakpoint in line 1, 2, 3, 4.
b 0 removes all the breakpoints. Selected breakpoints can be
removed using as argument the line where the breakpoint we want to remove is, but prefixed by a minus sign. So for example
b -3 removes the breakpoint from line 3.
Note that adding breakpoints to lines that Lua never executes, like declaration of local variables or comments, will not work. The breakpoint will be added but since this part of the script will never be executed, the program will never stop.
breakpoint command it is possible to add breakpoints into specific
lines. However sometimes we want to stop the execution of the program only
when something special happens. In order to do so, you can use the
keydb.breakpoint() function inside your Lua script. When called it simulates
a breakpoint in the next line that will be executed.
This feature is extremely useful when debugging, so that we can avoid continuing the script execution manually multiple times until a given condition is encountered.
As explained previously, but default LDB uses forked sessions with rollback of all the data changes operated by the script while it has being debugged. Determinism is usually a good thing to have during debugging, so that successive debugging sessions can be started without having to reset the database content to its original state.
However for tracking certain bugs, you may want to retain the changes performed
to the key space by each debugging session. When this is a good idea you
should start the debugger using a special option,
Note that the KeyDB server will be unreachable during the debugging session in this mode, so use with care.
In this special mode, the
abort command can stop the script half-way taking the changes operated to the dataset. Note that this is different compared to ending the debugging session normally. If you just interrupt
keydb-cli the script will be fully executed and then the session terminated. Instead with
abort you can interrupt the script execution in the middle and start a new debugging session if needed.
#Logging from scripts
keydb.debug() command is a powerful debugging facility that can be
called inside the KeyDB Lua script in order to log things into the debug
If the script is executed outside of a debugging session,
keydb.debug() has no effects at all. Note that the function accepts multiple arguments, that are separated by a comma and a space in the output.
Tables and nested tables are displayed correctly in order to make values simple to observe for the programmer debugging the script.
Inspecting the program state with
keydb.debug() function can be used in order to print values
directly from within the Lua script, often it is useful to observe the local
variables of a program while stepping or when stopped into a breakpoint.
print foo to look at the value of
foo in the context
of the calling function. When called without a variable name,
eval command executes small pieces of Lua scripts outside the context of the current call frame (evaluating inside the context of the current call frame is not possible with the current Lua internals). However you can use this command in order to test Lua functions.
LDB uses the client-server model where the KeyDB server acts as a debugging server that communicates using RESP. While
keydb-cli is the default debug client, any client can be used for debugging as long as it meets one of the following conditions:
- The client provides a native interface for setting the debug mode and controlling the debug session.
- The client provides an interface for sending arbitrary commands over RESP.
- The client allows sending raw messages to the KeyDB server.