Browse by type
lurk is a simple and pretty alternative to strace. It allows the user to
trace system calls of a process or of a command. In contrast to strace,
lurk focuses on a simple, yet pretty, user experience while implementing the
most important use cases of strace.
jqcurl -L -o /tmp/lurk.tar.gz "https://github.com/JakWai01/lurk/releases/latest/download/lurk-x86_64-unknown-linux-gnu.tar.gz"
tar -xzf /tmp/lurk.tar.gz -C /tmp
sudo install /tmp/lurk /usr/local/bin
cargo install lurk-cli
pacman -S lurk
To get a quick overview, you can run lurk --help:
lurk 0.2.7
USAGE:
lurk [OPTIONS] [command]...
ARGS:
<command>... Trace command
OPTIONS:
-c, --summary-only
Report a summary instead of the regular output
-C, --summary
Report a summary in addition to the regular output
-e, --expr <expr>
A qualifying expression which modifies which events to trace or how to trace them.
-E, --env <env>
--env var=val adds an environment variable. --env var removes an environment variable.
-f, --follow-forks
Trace child processes as they are created by currently traced processes.
-h, --help
Print help information
-j, --json
Display output in JSON format
-n, --syscall-number
Display system call numbers
-o, --file <file>
Name of the file to print output to
-p, --attach <attach>
Attach to a running process
-s, --string-limit <string-limit>
Maximum string size to print
-T, --syscall-times
Show the time spent in system calls in ms.
-u, --username <username>
Run the command with uid, gid and supplementary groups of username.
-v, --no-abbrev
Print unabbreviated versions of strings
-V, --version
Print version information
-z, --successful-only
Print only syscalls that returned without an error code
-Z, --failed-only
Print only syscalls that returned with an error code
Basically, there are two ways of tracing system calls. You can either execute a
command directly or attach to a running process by providing the process ID
(PID) via --attach. In the latter case, the command has to be run with
escalated privileges (sudo).
$ lurk ls
[54605] execve("", "", "") = 0
[54605] brk(NULL) = 0x55578000
[54605] arch_prctl(12289, 0xffffe780) = -22
[54605] access("", 4) = -2
[54605] openat(4294967196, "/etc/ld.so.cache", 524288) = 3
[54605] newfstatat(3, "", 0xffffd9a0, 4096) = 0
[54605] mmap(NULL, 92599, 1, 2, 3, 0) = 0xf7fa9000
...
$ sudo lurk --attach $PID
[54683] epoll_wait(5, 0xd01a3c20, 8, 4294967295) = -4
[54683] recvmsg(3, 0x4a4a0020, 0) = -11
[54683] recvmsg(3, 0x4a4a0020, 0) = -11
[54683] clock_gettime(1, 0x4a49df40) = 0
[54683] clock_gettime(1, 0x4a4a0220) = 0
[54683] recvmsg(3, 0x4a4a0050, 0) = -11
...
--exprUnlike in strace, lurk only supports --expr trace. Since this flag
behaves almost exactly like in strace, here a short, slightly changed,
excerpt of the strace
manpage on how to use
lurk --expr trace:
-e trace=syscall_set
--trace=syscall_set
Trace only the specified set of system calls. syscall_set
is defined as [!]value[,value], and value can be one of
the following:
syscall
Trace specific syscall, specified by its name (but
see NOTES).
?value Question mark before the syscall qualification
allows suppression of error in case no syscalls
matched the qualification provided.
/regex Trace only those system calls that match the regex.
You can use POSIX Extended Regular Expression
syntax (see regex(7)).
%file
file Trace all system calls which take a file name as an
argument. You can think of this as an abbreviation
for -e trace=open,stat,chmod,unlink,... which is
useful to seeing what files the process is
referencing. Furthermore, using the abbreviation
will ensure that you don't accidentally forget to
include a call like lstat(2) in the list. Betchya
woulda forgot that one. The syntax without a
preceding percent sign ("-e trace=file") is
deprecated.
%process
process
Trace system calls associated with process
lifecycle (creation, exec, termination). The
syntax without a preceding percent sign ("-e
trace=process") is deprecated.
%net
%network
network
Trace all the network related system calls. The
syntax without a preceding percent sign ("-e
trace=network") is deprecated.
%signal
signal Trace all signal related system calls. The syntax
without a preceding percent sign ("-e
trace=signal") is deprecated.
%ipc
ipc Trace all IPC related system calls. The syntax
without a preceding percent sign ("-e trace=ipc")
is deprecated.
%desc
desc Trace all file descriptor related system calls.
The syntax without a preceding percent sign ("-e
trace=desc") is deprecated.
%memory
memory Trace all memory mapping related system calls. The
syntax without a preceding percent sign ("-e
trace=memory") is deprecated.
%creds Trace system calls that read or modify user and
group identifiers or capability sets.
%stat Trace stat syscall variants.
%lstat Trace lstat syscall variants.
%fstat Trace fstat, fstatat, and statx syscall variants.
%%stat Trace syscalls used for requesting file status
(stat, lstat, fstat, fstatat, statx, and their
variants).
%statfs
Trace statfs, statfs64, statvfs, osf_statfs, and
osf_statfs64 system calls. The same effect can be
achieved with -e trace=/^(.*_)?statv?fs regular
expression.
%fstatfs
Trace fstatfs, fstatfs64, fstatvfs, osf_fstatfs,
and osf_fstatfs64 system calls. The same effect
can be achieved with -e trace=/fstatv?fs regular
expression.
%%statfs
Trace syscalls related to file system statistics
(statfs-like, fstatfs-like, and ustat). The same
effect can be achieved with
-e trace=/statv?fs|fsstat|ustat regular expression.
%clock Trace system calls that read or modify system
clocks.
%pure Trace syscalls that always succeed and have no
arguments. Currently, this list includes
arc_gettls(2), getdtablesize(2), getegid(2),
getegid32(2), geteuid(2), geteuid32(2), getgid(2),
getgid32(2), getpagesize(2), getpgrp(2), getpid(2),
getppid(2), get_thread_area(2) (on architectures
other than x86), gettid(2), get_tls(2), getuid(2),
getuid32(2), getxgid(2), getxpid(2), getxuid(2),
kern_features(2), and metag_get_tls(2) syscalls.
The -c option is useful for determining which system calls
might be useful to trace. For example,
trace=open,close,read,write means to only trace those four
system calls. Be careful when making inferences about the
user/kernel boundary if only a subset of system calls are
being monitored. The default is trace=all.
Note: When negating a statement with !, make sure to escape it (\!)
when using bash.
o$ lurk --expr trace=\!/o ls
[55155] execve("", "", "") = 0
[55155] brk(NULL) = 0x55578000
[55155] arch_prctl(12289, 0xffffe780) = -22
[55155] access("", 4) = -2
[55155] newfstatat(3, "", 0xffffd9a0, 4096) = 0
[55155] mmap(NULL, 92599, 1, 2, 3, 0) = 0xf7fa9000
[55155] read(3, "\u{7f}ELF\u{2}\u{1}\u{1}", 832) = 832
...
$ lurk --expr trace=%file ls
[55121] access("", 4) = -2
[55121] openat(4294967196, "/etc/ld.so.cache", 524288) = 3
[55121] newfstatat(3, "", 0xffffd9a0, 4096) = 0
[55121] openat(4294967196, "/usr/lib/libcap.so.2", 524288) = 3
[55121] newfstatat(3, "", 0xffffd9a0, 4096) = 0
[55121] openat(4294967196, "/usr/lib/libc.so.6", 524288) = 3
[55121] newfstatat(3, "", 0xffffd980, 4096) = 0
...
prctl system call$ lurk --expr trace=?prctl ls
[55407] execve("", "", "") = 0
[55407] brk(NULL) = 0x55578000
[55407] arch_prctl(12289, 0xffffe780) = -22
[55407] access("", 4) = -2
[55407] openat(4294967196, "/etc/ld.so.cache", 524288) = 3
[55407] newfstatat(3, "", 0xffffd9a0, 4096) = 0
[55407] mmap(NULL, 92599, 1, 2, 3, 0) = 0xf7fa9000
openat, close and mmap system calls$ lurk --expr trace=openat,close,mmap ls
[55440] openat(4294967196, "/etc/ld.so.cache", 524288) = 3
[55440] mmap(NULL, 92599, 1, 2, 3, 0) = 0xf7fa9000
[55440] close(3) = 0
[55440] openat(4294967196, "/usr/lib/libcap.so.2", 524288) = 3
[55440] mmap(NULL, 8192, 3, 34, 4294967295, 0) = 0xf7fa7000
[55440] mmap(NULL, 45128, 1, 2050, 3, 0) = 0xf7f9b000
[55440] mmap(0xf7f9e000, 20480, 5, 2066, 3, 12288) = 0xf7f9e000
See the tracer example.
ptrace.execve/execveat argument vectors (argv, envp) from the traced process' memory at syscall entry and prints them verbosely. This allows the tracer to show string values instead of raw pointer addresses.exec (which replaces the address space), by default the traced child raises a SIGSTOP after calling ptrace::traceme() so the tracer parent can configure options first.SIGSTOP), set the environment variable LURK_DISABLE_SIGSTOP=1 when running the traced program; the tracer will not expect the initial SIGSTOP from the child.lurk (c) 2022-2023 Jakob Waibel, Yuri Astrakhan, and contributors
SPDX-License-Identifier: MIT OR Apache-2.0