2

strace runs a specified command until it exits. It intercepts and records the system calls which are called by a process and the signals which are received by a process.

When running an external command in a bash shell, the shell first fork() a child process, and then execve() the command in the child process. So I guess that strace will report fork() or something similar such as clone()

But the following example shows it doesn't. Why doesn't strace report that the parent shell fork() the child process before execve() the command? Thanks.

$ strace -f time
execve("/usr/bin/time", ["time"], [/* 66 vars */]) = 0
brk(0)                                  = 0x84c000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efe9b2a5000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=141491, ...}) = 0
mmap(NULL, 141491, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7efe9b282000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\37\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1840928, ...}) = 0
mmap(NULL, 3949248, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7efe9acc0000
mprotect(0x7efe9ae7b000, 2093056, PROT_NONE) = 0
mmap(0x7efe9b07a000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1ba000) = 0x7efe9b07a000
mmap(0x7efe9b080000, 17088, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7efe9b080000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efe9b281000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efe9b27f000
arch_prctl(ARCH_SET_FS, 0x7efe9b27f740) = 0
mprotect(0x7efe9b07a000, 16384, PROT_READ) = 0
mprotect(0x602000, 4096, PROT_READ)     = 0
mprotect(0x7efe9b2a7000, 4096, PROT_READ) = 0
munmap(0x7efe9b282000, 141491)          = 0
write(2, "Usage: time [-apvV] [-f format] "..., 177Usage: time [-apvV] [-f format] [-o file] [--append] [--verbose]
       [--portability] [--format=format] [--output=file] [--version]
       [--quiet] [--help] command [arg...]
) = 177
exit_group(1)                           = ?
+++ exited with 1 +++
6
  • Where is the shell in this example? Mar 2, 2016 at 23:39
  • Not sure what you mean. The bash shell where I run the command will first fork a sub process which is a copy of itself, and then the sub process will execve the specified command time.
    – Tim
    Mar 2, 2016 at 23:44
  • 2
    The subprocess will exec the specified command strace. Mar 2, 2016 at 23:47
  • 1
    Then the output of strace starts at the beginning of its child. If you want to trace a shell, you have to strace the shell. strace -f -e trace=process sh -c '/usr/bin/time ; echo' or something. Mar 2, 2016 at 23:48
  • @Michael: Thanks. I see. Why do you add echo after /usr/bin/time?
    – Tim
    Mar 3, 2016 at 3:17

2 Answers 2

10
$ strace -f time
execve("/usr/bin/time", ["time"], [/* 66 vars */]) = 0
brk(0)                                  = 0x84c000
...

Strace directly invokes the program to be traced. It doesn't use the shell to run child commands, unless the child command is a shell invocation. The approximate sequence of events here is as follows:

  1. The shell executes strace with arguments "strace", "-f", "time".
  2. Strace starts up, parses its command line, and eventually forks.
  3. The original (parent) strace process begins tracing the child strace process.
  4. The child strace process executes /usr/bin/time with the argument "time".
  5. The time program starts up.

After step 1, the original shell process is idle, waiting for strace to exit. It's not actively doing anything. And even if it were doing something, it's not being traced by strace, so its activity wouldn't appear in the strace output.

1
  • Thanks. Before tracing begins, are there two calls to fork() (first one is by the parent shell to run strace, and the second one is to run time)? Or is there only one call to fork()?
    – Tim
    Apr 14, 2016 at 23:24
4

The fork in question is part of the mechanism which launches strace; it has concluded by the time tracing begins.

1
  • Thanks. Before tracing begins, are there two calls to fork() (first one is by the parent shell to run strace, and the second one is to run time)? Or is there only one call to fork()?
    – Tim
    Apr 14, 2016 at 23:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .