A debugger session that lives only in your head is useless the second time you need it. This guide runs lldb-20 so it loads a program, fires a known set of commands, and exits on its own instead of sitting at an interactive prompt. You will also see where program arguments go and how to keep an untrusted local .lldbinit out of the picture. Allow about 15 minutes.
You need a shell, an executable you can read, and LLDB 20. Examples use the installed lldb-20 package, version 1:20.1.8~++20250804090239+87f0227cb601-1~exp1~20250804210352.139, which reports LLDB 20.1.8. Nothing here changes a service or needs elevated privileges.
Confirm which binary is actually being called and which version it reports:
$ command -v lldb-20
/usr/bin/lldb-20
$ lldb-20 --version
lldb version 20.1.8
The manpage covers the lldb-20 command and its command-line options. Commands you type after LLDB starts, like run and bt, are LLDB commands rather than shell options: keeping those two layers apart in your head prevents a common source of confusing errors.
Checkpoint: if the command is missing, stop and install LLDB the normal way. Don't swap in a different version and assume every option behaves the same.
Pass an executable as a positional argument to prepare a target:
$ lldb-20 --no-lldbinit /bin/true
(lldb) target create "/bin/true"
Current executable set to '/bin/true' (x86_64).
(lldb) quit
--no-lldbinit stops LLDB automatically parsing .lldbinit files, which is a useful explicit boundary when debugging code from an unfamiliar directory or reviewing a command that needs to be reproducible. It does not stop debugger commands you type yourself.
Use --file /path/to/program, or its short alias -f, to make the target choice explicit in a script. Both forms load the target; neither starts it.
Add --batch and one or more -o options when you want LLDB to run commands and then quit on its own:
$ lldb-20 --no-lldbinit --batch \
-o 'version' \
-o 'target modules list' \
/bin/true
(lldb) target create "/bin/true"
Current executable set to '/bin/true' (x86_64).
(lldb) version
lldb version 20.1.8
(lldb) target modules list
[ 0] ... /bin/true
The exact module-list formatting varies with the host and symbols. What matters is that target creation succeeds, the version command runs, and LLDB exits instead of leaving you at a prompt. --batch runs commands supplied with -s, -S, -o and -O, then quits.
-o, long form --one-line, means one command run after a file on the command line has been loaded. Quote each shell argument so the shell hands the whole LLDB command over as one value.
Use -O (--one-line-before-file) for a command that has to run before the executable loads:
$ lldb-20 --no-lldbinit --batch \
-O 'settings set stop-disassembly-count 20' \
-o 'settings show stop-disassembly-count' \
/bin/true
(lldb) target create "/bin/true"
...
(lldb) settings show stop-disassembly-count
target.process.stop-disassembly-count (unsigned) = 20
Order on the command line matters here: -O for setup before a file, then -o for commands after it. For more than a few commands, put them one per line in a file and pass it with -S before the target, or -s after it.
Add --source-quietly, or its short alias -Q, for a quiet log. It suppresses command echo while sourcing files or one-line commands, but it doesn't turn diagnostic output into a stable machine interface.
An argument starting with a hyphen can easily be mistaken for an LLDB option. Put arguments belonging to the debugged program after --:
$ lldb-20 --no-lldbinit --batch \
-o 'settings show target.run-args' \
-- /path/to/program --input /path/to/data
(lldb) target create "/path/to/program"
(lldb) settings show target.run-args
target.run-args (arguments) =
[0]: "--input"
[1]: "/path/to/data"
The separator makes the boundary visible: LLDB options and its target come first, program and arguments come after. Replace both paths with real values. The example deliberately never runs the program, so it's safe to use while checking argument parsing.
To actually debug the target, swap the diagnostic command for run. Treat that as an action boundary: the program can write files, contact services or change other state, so review its arguments before adding run to a batch script.
LLDB reads command files with -s after loading a target, -S before loading one, -k after a crash in batch mode, and -K before a crash in batch mode. A command file is executable debugger input, not documentation: review its contents and permissions before handing it to LLDB.
Warning: don't add --local-lldbinit merely to make a command work. That option permits a .lldbinit in the current working directory, and --no-lldbinit is the safer default for repeatable work. If you deliberately allow a local file, inspect it first and record that choice in the script.
When a batch run fails, rerun the same command without --source-quietly first so the command sequence is visible, then check the executable path and lean on LLDB's own help:
$ test -r /path/to/program && echo readable
$ lldb-20 --no-lldbinit --batch -o 'help target create' /path/to/program
Don't treat a visually similar output line as proof the program actually ran. Include an explicit run, and reach for a later command such as bt or process status when you need real evidence of what happened.
run command is supplied.-o runs commands after loading.--.--no-lldbinit, and any deliberate exception was reviewed.