Table of Contents#
- Understanding strace’s Default Argument Truncation
- Why
-sMight Not Be Enough (Or Seem That Way) - Solutions to Show Complete Arguments
- Special Case: Capturing Brace Expansion and Curly Brackets
- Advanced: Patching
strace(For Edge Cases) - Conclusion
- References
1. Understanding strace’s Default Argument Truncation#
What is strace?#
strace intercepts and logs syscalls made by a process (e.g., open(), read(), execve()). For string arguments (like file paths or command-line args), it prints a truncated version by default to keep output manageable.
Default String Truncation: The -s Flag#
By default, strace truncates strings to 32 characters. This is controlled by the -s (string limit) flag, which defaults to 32. For example, if a process calls write(STDOUT_FILENO, "Hello {world}, this is a long argument...", ...), strace will print:
write(1, "Hello {world}, this is a long arg"..., 56) = 56Here, the string is cut off at 32 characters, with ... indicating truncation.
Example: Truncation with Curly Brackets#
Curly brackets are common in shell scripting (e.g., brace expansion: {a,b,c}) or configuration files. If an argument contains {}, truncation can hide critical context. Consider this Python script (long_arg.py):
import os
os.system('echo "Brace expansion: {apple,banana,cherry} and a very long string that exceeds 32 characters..."')Running strace python3 long_arg.py (without -s) shows truncated output for the execve syscall (which launches the echo command):
execve("/bin/sh", ["sh", "-c", "echo \"Brace expansion: {apple,banana,ch"..., ...]) = 0The full argument—including the {} and the rest of the string—is hidden!
2. Why -s Might Not Be Enough (Or Seem That Way)#
At first glance, increasing -s (e.g., -s 1024) should fix truncation. But in practice, users often hit walls due to:
- Forked Processes: If the target process forks a child (common in shells, daemons, or scripts), the child may execute the syscall with the full argument, while the parent does not.
stracewithout-f(follow forks) misses the child’s syscalls. - Brace Expansion: Shells like
bashexpand{a,b,c}intoa b cbefore executing the command. If you trace the shell itself, you’ll see the unexpanded{}; to see the expanded arguments, you need to trace the child process (e.g.,echoormkdir). - Nested Syscalls: Some programs pass arguments via multiple syscalls (e.g.,
execve→execvp). Tracing only the top-level syscall may miss the full argument.
3. Solutions to Show Complete Arguments#
3.1 Increase -s to a Higher Value#
The simplest fix is to increase -s to a value larger than your longest expected argument. Use -s 1024, -s 4096, or even -s 10000 for extreme cases.
Example:#
Rerun the earlier Python script with -s 4096:
strace -s 4096 python3 long_arg.pyNow the execve syscall shows the full argument, including curly brackets:
execve("/bin/sh", ["sh", "-c", "echo \"Brace expansion: {apple,banana,cherry} and a very long string that exceeds 32 characters...\""], 0x7ffd6b8a2b80 /* 24 vars */) = 0Pro Tip: There’s no strict upper limit for -s, but values above 10000 may slow down strace or clutter output. Use the smallest value that captures your arguments.
3.2 Follow Forks with -f to Capture Child Processes#
Many programs (e.g., shells, systemd, or scripts) fork child processes to execute commands. By default, strace only traces the parent. Use -f (follow forks) to trace child processes too.
Example: Tracing Brace Expansion#
Suppose you run bash -c 'mkdir {apple,banana,cherry}' and want to see the expanded mkdir arguments. Without -f, strace traces bash but not the mkdir child:
# Without -f: Only traces bash, shows unexpanded {apple,banana,cherry}
strace -s 4096 bash -c 'mkdir {apple,banana,cherry}'With -f, strace follows the mkdir child and shows the expanded arguments:
# With -f: Traces both bash and the mkdir child
strace -f -s 4096 bash -c 'mkdir {apple,banana,cherry}'Look for the execve syscall in the child process (marked with [pid 12345]):
[pid 12345] execve("/usr/bin/mkdir", ["mkdir", "apple", "banana", "cherry"], 0x7ffd6b8a2b80 /* 24 vars */) = 03.3 Focus on Key Syscalls (e.g., execve)#
Most arguments (command-line args, file paths) are passed via execve (or its variants like execvp). Tracing only execve with -e execve reduces noise and ensures you capture critical arguments.
Example:#
To trace only execve syscalls for the Python script:
strace -e execve -s 4096 python3 long_arg.pyOutput is simplified to show only execve calls, making it easier to spot arguments:
execve("/usr/bin/python3", ["python3", "long_arg.py"], 0x7ffd6b8a2d00 /* 24 vars */) = 0
execve("/bin/sh", ["sh", "-c", "echo \"Brace expansion: {apple,banana,cherry} and a very long string that exceeds 32 characters...\""], 0x7f3c2a3a8e00 /* 24 vars */) = 03.4 Use Verbose Mode (-v) for Additional Context#
The -v (verbose) flag increases output detail, including environment variables and hidden syscall arguments. While it doesn’t directly affect string truncation (that’s still controlled by -s), it helps when arguments are passed via environment variables or complex data structures.
Example:#
Combine -v with -s to see environment variables alongside full arguments:
strace -v -s 4096 python3 long_arg.pyOutput includes environment variables (e.g., PATH, HOME) and full syscall details, which can be critical for debugging environment-dependent issues.
4. Special Case: Capturing Brace Expansion and Curly Brackets#
Brace expansion (e.g., {a,b,c}) is handled by the shell, not the kernel. When you run mkdir {a,b,c}, the shell first expands {a,b,c} to a b c, then executes mkdir a b c. To capture the expanded arguments:
- Trace the child process (use
-fto follow forks). - Focus on
execve(the syscall that launchesmkdirwith expanded args).
Step-by-Step Example:#
# Trace bash with -f and -e execve to capture the mkdir child
strace -f -e execve -s 4096 bash -c 'mkdir {apple,banana,cherry}'Output shows the bash parent and mkdir child:
execve("/usr/bin/bash", ["bash", "-c", "mkdir {apple,banana,cherry}"], 0x7ffd6b8a2f00 /* 24 vars */) = 0
[pid 12345] execve("/usr/bin/mkdir", ["mkdir", "apple", "banana", "cherry"], 0x55f8d3b0a200 /* 24 vars */) = 0Here, the child mkdir process has the expanded arguments apple, banana, cherry—no curly brackets in sight, because the shell already expanded them!
5. Advanced: Patching strace (For Edge Cases)#
In rare cases (e.g., proprietary software with extremely long arguments), even -s 100000 may not suffice. For these edge cases, you can patch strace to remove string truncation entirely by modifying its source code.
How to Patch:#
- Download the
stracesource:git clone https://github.com/strace/strace.git && cd strace - Edit
src/print_args.cto setdefault_strsizeto a very high value (e.g.,1000000):// Change from: #define DEFAULT_STRSIZE 32 // To: #define DEFAULT_STRSIZE 1000000 - Compile and install:
./configure && make && sudo make install
Warning: This is not recommended for most users, as it may slow down strace and produce unmanageably large output. Use only as a last resort.
6. Conclusion#
strace is a powerful tool, but its default string truncation can hide critical arguments—especially those with curly brackets or from child processes. To capture complete arguments:
- Increase
-sto a value larger than your longest argument (e.g.,-s 4096). - Use
-fto follow forked child processes (critical for brace expansion or scripts). - Focus on
execvewith-e execveto reduce noise and target command-line arguments. - Combine with
-vfor verbose context when needed.
With these techniques, you’ll never miss a curly bracket or truncated argument again!
7. References#
straceman page:man strace- strace Official Documentation
- Linux Syscall Reference
- Bash Brace Expansion