Monday, January 23, 2006

How Not To Write a While Loop

I was running a few long processes recently, and was getting tired of watching it in top. I wanted to run something that would tell me when it quit. I went looking, and found wait, but that only works on processes that are children of the current shell, which wouldn't work in my case.

So I figured I'd just write a bash one-liner. I tried while 1 as my base loop, but that didn't work. I thought (incorrectly) that I had tried while true already, and found that it didn't work (I hadn't), and got this flash of, well, non-genius:

while `yes`

Think about it. (Don't run it yourself, especially without reading the rest of this post!) yes outputs "y\n" in an endless loop. Wrapping a command in backticks runs that command, and puts its output inline for whatever command it's a part of. Do you see the disaster looming?

When I ran the loop, it started by running yes, saving its (infinite) output. This filled available memory. It then filled available swap. My memory docklet reported "MEM 96% SWP 99%", right before the system stopped responding completely. As a testament to the solidity of Linux, the non-responsive stuff only lasted a little while, after which the system responded to all of the Ctrl-C and "close window" clicks I had been sending it, and all of the offending processes (and a few non-offending ones) disappeared. No system crash.

Anyway, lesson learned, and I ended up writing my one-liner as follows:

while test -e /proc/nnnnn; do sleep 5; done; echo ^G

which waits for the process to go away, then beeps. Made much more sense than whatever I originally had in mind.


Post a Comment

<< Home