A program exits silently with code 1
-o writes the trace to a file, and the program's output stays on screen.
The last failures before exited with 1 are the cause: a missing file, no
permission, a port that did not open.
strace shows the system calls of a program and their results: a file that did not open, a failed connect, a wait.
strace cat /etc/hostname
all calls of a command
strace -f sh -c '…'
and of its children
strace -e trace=openat cmd
openat only
strace -f -e trace=file cmd
everything with file paths
strace -e trace=network cmd
sockets and connections
strace -o /tmp/t.log -f cmd
to a file, apart from the output
strace -c ls /etc > /dev/null
summary: calls of each kind
sudo timeout 10 strace -p 1234
attach to a process
A program does not open or send anything by itself: it asks the kernel.
Each such request is a system call: openat opens a
file, read and write read and write, connect connects, exit_group
ends the process. strace runs the program and prints every call with its
arguments and result — to standard error, so as not to mix with the
program's output.
name(arguments) = result. openat(…, "/etc/hostname", O_RDONLY) = 3 means
the file was opened and got descriptor 3; then
read(3, …) reads exactly that file. write(1, …) writes to standard
output — that is why ubuntu cut into the strace line. The last line,
+++ exited with 0 +++, is the exit code.
A failure is the result -1 plus an error name:
| Error | Meaning |
|---|---|
ENOENT |
no such file or directory |
EACCES |
permission denied |
ECONNREFUSED |
nobody listens on that port |
EMFILE |
the open files limit ran out (see ulimit) |
EAGAIN |
the resource is busy, try later |
Not every ENOENT is a problem. A program looks for files in several places
in turn: sh tried /usr/local/sbin/ls, /usr/local/bin/ls,
/usr/sbin/ls before it found /usr/bin/ls. What matters is the failure
after which the program gave up — usually near the end.
Without -f, strace sees only the process it started. A shell, a service,
a script do their work in children — with -f their calls are visible, each
line with a PID:
The full output runs to hundreds of lines. -e trace= keeps what you need:
| Filter | What stays |
|---|---|
-e trace=openat |
openat only |
-e trace=openat,read,write |
the listed calls |
-e trace=file |
everything with a file path: openat, statx, execve, access |
-e trace=network |
socket, connect, sendto, recvfrom |
-e trace=process |
starting and ending processes |
strace -p <PID> attaches to a running process and prints its calls from
that moment on. Ubuntu sets kernel.yama.ptrace_scope = 1: without root you
can trace only your own children. Attaching to an already running process —
even your own — needs sudo:
A waiting process shows an unfinished call — with no = and no result.
Here flock waits for a lock held by another process:
timeout 3 detaches strace after 3 seconds (exit code 124); the process
keeps working as if nothing happened. Ctrl+C does the same.
The main options are in the table below. The full list is man strace.
| Option | What it does | Example |
|---|---|---|
-f |
Follow forked child processes and threads. | strace -f cmd |
-p PID |
Attach to an already running process by PID. | sudo strace -p 1234 |
-e trace=... |
Filter by call group — file, network, openat,read, and more. | strace -e trace=network cmd |
-c |
Summary profile — which calls were made and how much time they took. | strace -c cmd |
-T |
Show the time spent in each call. | strace -T -e trace=openat cmd |
-y |
Show paths and addresses instead of raw file-descriptor numbers. | strace -y -p 1234 |
-s N |
Length of displayed strings (default is 32 — often too short). | strace -s 200 -e trace=write -p 1234 |
-o FILE |
Write the output to a file instead of the terminal. | strace -o trace.log -f cmd |
-tt |
A microsecond timestamp before each line. | strace -tt -o trace.log cmd |
Nothing found. Try a shorter query.
-o writes the trace to a file, and the program's output stays on screen.
The last failures before exited with 1 are the cause: a missing file, no
permission, a port that did not open.
root can read any file, so sudo strace shows no permission failures. A
service runs as its own user — trace as that user:
systemctl show -p User <service> shows the service's user.
The address and port are in the connect arguments.
A single unfinished line means the process waits in that call: flock
waits for a file lock (who holds it — lsof and /proc/locks,
see proc-filesystem), read for data, connect for the network.
A process in state D waits for the kernel inside a call, and strace may
print nothing until the wait ends (see load-average).
calls is how many times, errors how many failed, % time the share of
time in the kernel.
ptrace_scope = 1 forbids attaching to a process that is not your child.
Run sudo strace -p <PID>. PID 1 and other users' processes need sudo
too.
Both write to the terminal. -o file sends the trace to a file.
strace shows 32 characters of a string, the rest is .... -s 200 shows
200.
A child process does the work, and strace without -f does not see it.
fd, status, limits in /proc.exited with line.EMFILE and the open files limit.D.Found an inaccuracy? Report an error in the article