How to Use the Linux strace Command to Debug Executable System Calls and Hanging Processes

The Black Box of System Execution

When a Linux application fails silently, administrators are often left completely blind. Suppose you deploy a custom Python web scraper, and the moment you execute the script, it hangs indefinitely. It consumes 0% CPU, throws no errors to the terminal, and writes absolutely nothing to /var/log/syslog. The application is a black box.

Standard tools like top or lsof will only tell you that the process exists, not what it is actually waiting for. To shatter the black box, UNIX engineers deploy the strace (System Trace) command. strace is a brutally powerful diagnostic utility that intercepts and records every single System Call (syscall) the application makes to the Linux kernel.

Every time an application tries to open a file, allocate memory, or read data from a network socket, it must politely ask the Linux kernel for permission via a syscall. strace intercepts these requests in real-time. By reading the strace output, you can definitively prove exactly which file the application is trying to open (and failing to find), or exactly which IP address the application is attempting to connect to (and hanging on).

Step 1: Tracing a Basic Command

The simplest way to use strace is to launch an executable directly through it.

Let’s trace a standard Linux command, like cat, attempting to read a file that does not exist:

strace cat /etc/ghost_file.txt

The terminal will instantly explode with dozens of lines of highly technical C-style function calls. Do not be intimidated. You only need to look at the last few lines before the program exited.

You will see something like this:

openat(AT_FDCWD, "/etc/ghost_file.txt", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, "cat: ", 5cat: ) = 5
write(2, "/etc/ghost_file.txt", 19/etc/ghost_file.txt) = 19
write(2, ": No such file or directory", 27: No such file or directory) = 27
write(2, "\n", 1
) = 1
exit_group(1) = ?

This is the absolute, mathematical truth of what happened. The application fired the openat() syscall asking the kernel for the file. The kernel responded with -1 ENOENT (Error No Entry). The application then fired a series of write() syscalls to file descriptor 2 (Standard Error) to print the error message to your screen, and then executed exit_group(1) to crash.

Step 2: Attaching to a Hanging Process (-p)

The most critical enterprise use case is debugging a daemon (like Nginx, MySQL, or a custom script) that is already running but is completely frozen.

You cannot simply restart the application, or you will destroy the frozen state. You must attach strace to the live, hanging process using its Process ID (PID).

First, find the PID of the frozen Python script using ps aux | grep python (assume it is PID 4599).

Now, attach strace to it as the root user:

sudo strace -p 4599

The output might instantly hang on a single line:

connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("203.0.113.50")}, 16 ...

You have instantly solved the mystery. The Python script is not broken. It fired a connect() syscall, attempting to open a TCP socket to IP address 203.0.113.50 on port 80. The application is completely frozen because the corporate firewall is dropping the packet, and the application developer failed to code a timeout limit into their script. strace proved it is a network issue, not an application bug.

Step 3: Filtering the Noise (The -e Flag)

If you attach strace to a highly active database server like MySQL, it will generate thousands of lines per second, rendering the output completely illegible.

You must use the -e (Expression) flag to filter the exact system calls you care about.

Suppose an application keeps crashing due to permission denied errors, but it won’t tell you which file it is failing to open. You don’t care about memory allocation (mmap) or network sockets (recvfrom). You only care about file opening (open and openat).

sudo strace -e trace=open,openat -p 4599

The terminal will now sit perfectly silently. It will only print a line when the application explicitly attempts to open a file. When you see openat("/etc/secret_config.ini") = -1 EACCES (Permission denied), you immediately know you need to fix the CHMOD permissions on that specific file.

You can also filter by categories. For example, -e trace=network will only show networking system calls, stripping away all file I/O noise.

Step 4: Generating Statistical Heatmaps (-c)

Sometimes an application isn’t frozen, but it is inexplicably slow. You don’t know exactly what is causing the latency. Instead of streaming the live system calls, you can instruct strace to silently monitor the application and generate a statistical heatmap of where the application is wasting its time.

You use the -c (Count/Summary) flag.

Attach it to the slow process, wait 30 seconds, and then press Ctrl+C.

sudo strace -c -p 4599

Instead of thousands of lines of text, strace will output a brilliant, formatted table.

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 95.50    4.502100       45021       100           select
  3.20    0.150822          15     10000           read
  1.10    0.051833           5     10000      5000 openat

This table instantly reveals that the application is spending 95% of its execution time sitting idly in the select syscall (waiting for network traffic or disk I/O to arrive), and that 50% of its attempts to open files resulted in errors. This provides the exact empirical data required to hand the issue back to the software development team.

Conclusion

Attempting to debug a silently failing Linux application by guessing at configuration files is a futile exercise. By deploying the strace utility, UNIX engineers strip away the application’s abstraction layer and peer directly into the kernel’s execution matrix. The ability to intercept live system calls, filter for specific network or file I/O bottlenecks, and generate mathematical execution heatmaps transforms strace into the ultimate diagnostic weapon for solving the most complex, undocumented software failures in the enterprise.

RELATED POSTS

  • How to Use the Linux file Command to Identify File Types
  • How to Use the htop Command to Monitor Linux Server Performance
  • How to Check Your CPU Temperature in the Linux Terminal
  • How to Use the cut Command to Extract Specific Columns of Data from a Text File in Linux
  • How to Configure Log Rotation using logrotate on Linux Servers
  • Get the best tech tips delivered straight to your inbox.

    Join thousands of readers mastering Apple, Google, Microsoft, and Linux.