<?xml version="1.0" ?><entry xml:lang="en" xmlns="http://www.w3.org/2005/Atom" xmlns:planet="http://planet.intertwingly.net/"><id>http://price.mit.edu/blog/?p=203</id><link href="http://price.mit.edu/blog/2010/08/strace-the-lost-chapter/" rel="alternate" type="text/html"/><title>Strace: The Lost Chapter</title><summary>pre { overflow-x: auto; overflow-y: auto; }
I wrote another post last week for the Ksplice blog: Strace — The Sysadmin’s Microscope.  If you’re running a Linux system, or just writing or maintaining a complex program, sometimes strace is indispensable — it’s the tool that tells you what a program is really doing.  My [...]</summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I wrote another post last week for the Ksplice blog: <a href="http://blog.ksplice.com/2010/08/strace-the-sysadmins-microscope/">Strace — The Sysadmin’s Microscope</a>.  If you’re running a Linux system, or just writing or maintaining a complex program, sometimes <code><a href="http://linux.die.net/man/1/strace">strace</a></code> is indispensable — it’s the tool that tells you what a program is <em>really</em> doing.  My post explains why <code>strace</code> is so good at showing the interesting events in a program (hint: it gets to sit between the program and everything else in the universe), describes some of its key options, and shows a few ways you can use it to solve problems.</p>
<p>Unfortunately there’s only so much you can say in a blog post of reasonable length, so I had to cut some of my favorite uses down to bullet points.  Here’s one such use, which I can’t bear to keep off of the Web, just because I thought I was so clever when I came up with it <a href="http://www.ksplice.com/">in real life</a> a couple of months ago.</p>
<p>(If you haven’t already, I encourage you to <a href="http://blog.ksplice.com/2010/08/strace-the-sysadmins-microscope/">go read the main post</a> first.  I’ll be here when you come back.)</p>
<h2>Strace As A Progress Bar</h2>
<p>Sometimes you start a command, and it turns out to take <em>forever</em>.  It’s been three hours, and you don’t know if it’s going to be another three hours, or ten minutes, or a day.</p>
<p>This is what progress bars were invented for.  But you didn’t know this command was going to need a progress bar when you started it.</p>
<p>Strace to the rescue.  What work is your program doing?  If it’s touching anything in the filesystem while it works, or anything on the network, then <code>strace</code> will tell you exactly what it’s up to.  And in a lot of cases, you can deduce how far into its job it’s gotten.</p>
<p>For example, suppose our program is walking a big directory tree and doing something slow.  Let’s simulate that with a synthetic directory tree and a <code><a href="http://linux.die.net/man/1/find">find</a></code> that just sleeps for each directory:</p>
<pre>  $ mkdir tree &amp;&amp; cd tree
  $ for i in $(seq 1000); do mktemp -d -p .; done &gt;/dev/null
  $ find . -exec sleep 1 \;
</pre>
<p>Well, this is taking a while.  Let’s open up another terminal and ask <code>strace</code> what’s going on:</p>
<pre>  $ pgrep find
  2714
  $ strace -p 2714
  [...]
  open(&quot;tmp.HvbzfbbWSa&quot;, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 5
  fstat(5, {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0
  fchdir(5)                               = 0
  getdents(5, /* 2 entries */, 4096)      = 48
  getdents(5, /* 0 entries */, 4096)      = 0
  close(5)                                = 0
  open(&quot;..&quot;, O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 5
  fstat(5, {st_mode=S_IFDIR|0755, st_size=36864, ...}) = 0
  fchdir(5)                               = 0
  close(5)                                = 0
  newfstatat(AT_FDCWD, &quot;tmp.MiHDWiBURu&quot;, {st_mode=02, st_size=17592186044416, ...}, AT_SYMLINK_NOFOLLOW) = 0
  clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fb19c92a770) = 13044
  wait4(13044, [{WIFEXITED(s) &amp;&amp; WEXITSTATUS(s) == 0}], 0, NULL) = 13044
  --- SIGCHLD (Child exited) @ 0 (0) ---
  open(&quot;tmp.MiHDWiBURu&quot;, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 5
  fstat(5, {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0
  fchdir(5)                               = 0
  [...]
</pre>
<p>The <code>find</code> just looked at <code>tmp.HvbzfbbWSa</code>, and now it’s going into <code>tmp.MiHDWiBURu</code>.  How far is that into the total?  <code><a href="http://linux.die.net/man/1/ls">ls</a></code> will tell us the list of directories that the <code>find</code> is working from; we just have to tell it to give them to us in the raw, unsorted order that the parent directory lists them in, with the <a href="http://linux.die.net/man/1/ls">-U flag</a>.  And then <code><a href="http://www.gnu.org/software/grep/manual/grep.html#Output-Line-Prefix-Control">grep -n</a></code> will tell us where in that list the entry <code>tmp.HvbzfbbWSa</code> appears:</p>
<pre>  $ ls -U | grep -n tmp.HvbzfbbWSa
  258:tmp.HvbzfbbWSa
  $ ls -U | grep -n tmp.MiHDWiBURu
  259:tmp.MiHDWiBURu
  $ ls -U | wc -l
  1000
</pre>
<p>So <code>tmp.HvbzfbbWSa</code> is entry 258 out of 1000 entries in this directory — we’re 25.8% of the way there.  If it’s been four minutes so far, then we should expect about twelve more minutes to go.</p>
<h2>(But With The Benefit Of Foresight…)</h2>
<p>I’d be remiss if I taught you this hackish approach without mentioning that if you realize you want a progress bar <em>before</em> you start the command, you can do it much better — after all, the ‘progress bar’ above doesn’t even have a bar, except in your head.</p>
<p>Check out <a href="http://www.ivarch.com/programs/pv.shtml">pv, the pipe viewer</a>.  In my little example, you’d have the command itself print out where it is, like so:</p>
<pre>  $ find . -exec sh -c 'echo $1 &amp;&amp; sleep 1' -- \{\} \;
  .
  ./tmp.BToqLElOGC
  ./tmp.xnuhzmGbOP
  [...]
</pre>
<p>and then you could get a real, live, automatically-updated progress bar, like so:</p>
<pre>  $ find . -exec sh -c 'echo $1 &amp;&amp; sleep 1' -- \{\} \; \
     | pv --line-mode --size=$(find . | wc -l) &gt;/dev/null
   175 0:02:57 [0.987/s ] [=====&gt;                               ] 17% ETA 0:13:55
</pre>
<p>Here we’ve passed <code>--line-mode</code> to make <code>pv</code> count lines instead of its default of bytes, and <code>--size</code> with an argument to tell it how many lines to expect in total.  Even if you can’t estimate the size, <code>pv</code> will cheerfully tell you how far you’ve gone, how long it’s been, and how fast it’s moving right now, which can still be handy.  <code>pv</code> is a pretty versatile tool in its own right — explaining all the ways to use it could be another whole blog post.  But <a href="http://www.ivarch.com/programs/quickref/pv.shtml">the <code>pv</code> man page</a> is a good start.</p>
<h2>That’s Just One</h2>
<p>There’s lots of other ways to use <code>strace</code> — starting with the two I described <a href="http://blog.ksplice.com/2010/08/strace-the-sysadmins-microscope/">in my main post</a>, and the three more, besides this one, that I only mentioned there.  I don’t really know anymore how I used to manage without it.</p>
<p style="text-align: center;"><em>Liked this post?  <a href="http://feeds.feedburner.com/gregprice">Subscribe</a> and keep ‘em coming.</em></p></div></content><updated planet:format="August 16, 2010 04:50 AM">2010-08-16T04:50:03Z</updated><category term="Uncategorized"/><category term="C"/><category term="debugging"/><category term="free software"/><category term="howto"/><category term="kernel"/><category term="ksplice blog"/><category term="linux"/><category term="sipb"/><category term="strace"/><category term="system administration"/><category term="system calls"/><category term="unix"/><author><name>Greg Price</name></author><source><id>http://price.mit.edu/blog</id><link href="http://price.mit.edu/blog/tag/sipb/feed/" rel="self" type="application/rss+xml"/><link href="http://price.mit.edu/blog" rel="alternate" type="text/html"/><title>price.mit.edu/blog » sipb</title><updated planet:format="January 25, 2026 03:07 AM">2026-01-25T03:07:27Z</updated><planet:format>rss20</planet:format><planet:http_etag>&quot;452a10c017d6ace36ea6c313eb650a31&quot;</planet:http_etag><planet:http_last_modified>Mon, 16 Aug 2010 16:26:14 GMT</planet:http_last_modified><planet:bozo>false</planet:bozo><planet:encoding>utf-8</planet:encoding><planet:css-id>gregory-price</planet:css-id><planet:items_per_page>60</planet:items_per_page><planet:name>Gregory Price</planet:name><planet:days_per_page>0</planet:days_per_page><planet:http_status>200</planet:http_status></source></entry>