Every interaction between a program and the Linux kernel goes through system calls (syscalls). strace intercepts and logs these calls in real-time, making it invaluable for debugging, security analysis, and understanding program behavior. This lab covers filtering, counting, following forks, and tracing real programs.
💡 strace works by using the ptrace() syscall to intercept system calls of the target process. This is why it requires root or matching UID. It has a performance overhead (2–10x slowdown) — use it for debugging only.
Step 2: Basic Tracing — Understand the Output Format
Trace a simple command and observe the output format:
stracels/tmp2>&1|head-15
📸 Verified Output:
Output format anatomy:
= followed by positive number: success (often a file descriptor)
Output includes <N.NNNNNN> — time in seconds for each call:
💡 -tt shows wall-clock time of each call (for sequencing). -T shows duration of each call (for identifying slow operations). Use both together with -ttT.
Step 5: Count Syscalls with -c
Get a statistical summary of all syscall activity:
📸 Verified Output:
💡 The errors column is gold — it shows failed syscall counts. 2 access errors above = the access() calls for /etc/ld.so.preload (doesn't exist but checked anyway).
Step 6: Follow Forks with -f
Trace child processes spawned via fork() or clone():
📸 Verified Output:
With -f, output prefixes show which PID made each call:
💡 Use -ff -o /tmp/trace to write each process's trace to a separate file (/tmp/trace.PID). Essential for debugging multi-process applications.
Step 7: Write Output to File with -o
For long traces, redirect to a file:
📸 Verified Output:
💡 Attaching with -p doesn't restart the program — it observes an already-running process. The process continues normally; only syscall logging is added.
Step 8: Capstone — Debug a "File Not Found" Error
Scenario: A program fails silently. Use strace to find what file it's trying to open.
📸 Verified Output:
📸 Verified Output:
Debug summary: strace revealed exactly which two files were missing, their full paths, and the error code — without needing source code or verbose logging.
# Show exactly which opens failed
strace -e trace=openat /tmp/myapp.sh 2>&1 | grep 'ENOENT'
openat(AT_FDCWD, "/etc/myapp/config.yaml", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/var/lib/myapp/data.db", O_RDONLY) = -1 ENOENT (No such file or directory)