A pretty (simple) alternative to strace

Overview

lurk

CICD

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.

Demo

Demo

Features

  • Supports an opinionated subset of strace flags.
  • Supports JSON output for further processing via e.g. jq
  • Uses colorized, formatted output ;-).

Installation

cURL

curl -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
sudo install /tmp/lurk /usr/local/bin

Cargo

cargo install lurk-cli

Usage

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

Basic trace

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).

Executing a command

$ 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
...

Attaching to a running process

$ 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
...

Filtering with --expr

Unlike 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.

Filtering for system calls not containing the letter 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
...

Filtering only for all system calls taking a file as an argument

$ 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
...

Suppress error for 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

Only output 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

Acknowledgements

  • sharkdp/fd as an inspiration on how to structure a Rust CLI and its README.
  • All maintainers of the dependencies used to create lurk and all of those who answered my questions regarding ptrace.

License

lurk (c) 2022 Jakob Waibel and contributors

SPDX-License-Identifier: AGPL-3.0

Comments
  • Using Json and output interleaves output formats

    Using Json and output interleaves output formats

    Reproduction

    lurk --json -o /tmp/test ls
    

    Expected

    The output file /tmp/test to represent valid json.

    Actual

    $ jq < /tmp/test 
    [
      7008
    ]
    parse error: Invalid numeric literal at line 1, column 15
    

    This is because the file starts with some non-json print in addition to the json document:

    [7008] execve("", "", "") = 0
    {"args":["\"\"","\"\"","\"\""],"pid":"7008","result":"0","syscall":"execve","type":"SYSCALL"}[7008] brk(NULL) = 0x55578000
    
    opened by HeroicKatora 2
  • Use `lurk` as the binary name

    Use `lurk` as the binary name

    Note: Since the crate name lurk was already gone, lurk is called lurk-cli when installing via cargo.

    Even though the crate is named lurk-cli you can easily name the produced binary lurk if you want that.

    opened by badboy 1
  • String argument formatting

    String argument formatting

    Command

    lurk -j cat /etc/fstab|jq 'select(.syscall == "openat") | .args[1]'

    Result

    "\"/usr/local/lib/x86_64-linux-gnu/\"..."
    "\"/usr/local/lib/x86_64-linux-gnu/\"..."
    

    Expected Result

    "/usr/local/lib..."
    
    bug 
    opened by JakWai01 0
  • Implement additional flags for professional use

    Implement additional flags for professional use

    Needs to be implemented

    • [ ] Implement -ff
    • [ ] Implement -x
    • [ ] Implement -xx
    • [ ] Implement -yy
    • [ ] Try to increase precision of wall clock time

    Further information

    Source: https://news.ycombinator.com/item?id=32275902

    Heavy professional strace user here. Afaics the wall clock time of the call is not implemented. This is effectively useless to me without that. The second -ff is critical for following busy multiprocess stuff like a JVM. If you aren't resolving every known struct then -x and -xx can be useful. The FD resolution provided by -yy is not critical but can be a real time saver. The flags I use most often are -ffttTyy -o -s.

    enhancement 
    opened by JakWai01 0
  • follow-forks flag seems to be not working correctly

    follow-forks flag seems to be not working correctly

    Hello, thanks for this nice project

    I tried debugging a project with lurk but I noticed 2 problems with -f:

    • Sometimes it hang and doesn't terminate
    • When it does terminate paradoxically the output is really short its shorter then without -f flag

    For example here is a comparison of running without -f and with -f

    without -f: https://pastebin.com/4bD03gYG with -f: https://pastebin.com/e6AjTwRm

    Reproduction

    lurk -f deno run --unstable -A https://pastebin.com/raw/XkLSzG34

    If you try this multiple times sometimes it hangs on epollwait, and when it succeeds the output is very short, shorter then without -f flag.

    meta:

    • Linux 5.18.13-arch1-1 1 SMP PREEMPT_DYNAMIC Fri, 22 Jul 2022 13:05:04 +0000 x86_64 GNU/Linux
    • deno 1.24.0
    • lurk 0.2.9
    bug 
    opened by sigmaSd 0
Owner
Jakob Waibel
Software Engineer at IBM, student at Stuttgart Media University. Working with Kubernetes. Interested in Rust, Go and Linux.
Jakob Waibel
Tiny Rust library to draw pretty line graphs using ascii characters.

rasciigraph Tiny Rust library to draw pretty line graphs using ascii characters. Usage Add this to your Cargo.toml [dependencies] rasciigraph = "0.1.1

Orhan Balci 50 Sep 12, 2022
A small CLI tool to query ArcGIS REST API services, implemented in Rust. The server response is returned as pretty JSON.

A small CLI tool to query ArcGIS REST API services, implemented in Rust. The server response is returned as pretty JSON.

Andrew Vitale 2 Apr 25, 2022
An easy to use library for pretty print tables of Rust structs and enums.

tabled An easy to use library for pretty printing tables of Rust structs and enums. Table of Contents Usage Settings Style Themes ASCII Psql Github Ma

Maxim Zhiburt 1k Sep 19, 2022
fd is a program to find entries in your filesystem. It is a simple, fast and user-friendly alternative to find

fd is a program to find entries in your filesystem. It is a simple, fast and user-friendly alternative to find. While it does not aim to support all of find's powerful functionality, it provides sensible (opinionated) defaults for a majority of use cases.

David Peter 24.6k Sep 26, 2022
`ls` alternative with useful info and a splash of color 🎨

?? Natls ?? Why Natls? Showing file permissions Showing file size Showing the date that the file was modified last Showing the user that the file belo

Will 1.2k Sep 21, 2022
This is choose, a human-friendly and fast alternative to cut and (sometimes) awk

Choose This is choose, a human-friendly and fast alternative to cut and (sometimes) awk Features terse field selection syntax similar to Python's list

Ryan Geary 1.3k Sep 21, 2022
Intuitive find & replace CLI (sed alternative)

sd - s[earch] & d[isplace] sd is an intuitive find & replace CLI. The Pitch Why use it over any existing tools? Painless regular expressions sd uses r

Gregory 3.7k Sep 18, 2022
Alternative to *fetch, uwuifies all stats.

owofetch-rs Alternative to *fetch, uwuifies all stats. Installation: Arch: AUR Other Linux distros: Either compile the source with cargo build --relea

nett_hier 4 Sep 11, 2022
Count your code by tokens, types of syntax tree nodes, and patterns in the syntax tree. A tokei/scc/cloc alternative.

tcount (pronounced "tee-count") Count your code by tokens, types of syntax tree nodes, and patterns in the syntax tree. Quick Start Simply run tcount

Adam P. Regasz-Rethy 47 Aug 31, 2022
fcp is a significantly faster alternative to the classic Unix cp(1) command

A significantly faster alternative to the classic Unix cp(1) command, copying large files and directories in a fraction of the time.

Kevin Svetlitski 486 Sep 20, 2022
⚡ A Blazing fast alternative to the stock windows folder delete function!

Turbo Delete A blazing fast alternative to the default Windows delete. Turbodelete is a blazing fast alternative to the default Windows delete functio

Tejas Ravishankar 162 Sep 9, 2022
Faster and better alternative to Vtop written in Rust.

Rtop Faster and better alternative to Vtop written in Rust. Work in Progress Features Lightweight < 1MB Responsive UI Sort Process by Memory, CPU Usag

Squitch 6 Jun 14, 2022
Sugar is an alternative to the current Metaplex Candy Machine CLI

Sugar: A Candy Machine CLI Sugar is an alternative to the current Metaplex Candy Machine CLI. It has been written from the ground up and includes seve

Metaplex Foundation 131 Sep 23, 2022
a simple program that you can scrap, is shit and really simple but is cool.

if you want to run it you need to have installed curl by default scrap youtube, but you can change it, also change the number of threads and run: carg

pai 7 Oct 15, 2021
A dead simple ANSI terminal color painting library for Rust.

yansi A dead simple ANSI terminal color painting library for Rust. use yansi::Paint; print!("{} light, {} light!", Paint::green("Green"), Paint::red(

Sergio Benitez 155 Sep 24, 2022
(Rust) Coloring terminal so simple you already know how to do it !

Colored Coloring terminal so simple, you already know how to do it! "this is blue".blue(); "this is red".red(); "this is red on blue".red(

Thomas Wickham 1.1k Sep 22, 2022
A simple guide for optimizing linux in detail

Optimizing Linux I am writing this guide as to save my progress and let others contribute to increase the performance even further, after all many are

Siddharth Naithani 64 Aug 30, 2022
Cork is a simple command-line calculator, mainly targeted towards people who deal with hex numbers

Cork is a simple command-line calculator, mainly targeted towards people who deal with hex numbers. It deals only with integer arithmetic. Expressions may involve mixed bases (limited to decimal, hexadecimal, octal and binary numbers). The global output format may be set to a particular radix - by default it is hex.

Deep Majumder 37 Sep 7, 2022
A simple CLI pomodoro timer written in Rust.

Pomodoro A simple CLI pomodoro timer written in Rust. Based on the Pomodoro Technique. Works on any platform that supports desktop notifications. Exam

null 6 Nov 26, 2021