top's exit code indicates error--is this a bug?

This single line of code in a sh script file

top -b -n 1 -U $USER

causes the script to prematurely exit with an exit code of 1 (i.e. an error) if the script is run with the -e option (e.g. if

set -e

is executed near the top of the script file).

Alternatively, you can execute it like

top -b -n 1 -U $USER
topExitCode=$?
if [ "$topExitCode" -ne "0" ]; then
	echo "ERROR: exit code == $topExitCode detected"
	exit $topExitCode
fi

and prove that that top line is the offender.

So why is top generating an error exit code?

I am on box whose uname -a returns

Linux jellybean 2.6.20-15-generic #2 SMP Sun Apr 15 07:36:31 UTC 2007 i686 GNU/Linux

The man pages top(1): tasks - Linux man page indicate the following BUG:

So, naturally I tried

top -b -n 2 -U $USER

as well as

CPULOOP=1
top -b -n 1 -U $USER

but both of those still fail.

Does anyone know what is going on? Should I file a bug report?

What version and on what OS/distribution?

I see the same behaviour on a SLES 9.3 server with procps-3.2.5-1.2, but it seems to behave as expected on RHEL 4.6 with procps-3.2.3-8.9.

I had a look through the current source here and could see no reason why it should exit with code 1 (current CVS version of the package is 3.2.7):

SourceForge.net Repository - [procps] View of /procps/top.c

Executing

top -h

yields

top: procps version 3.2.7

My original post gave the uname -a result. This is a ubuntu server. Is there some other command that you would have me run?

Whew--at least someone else sees it too...

Also occurs on SLES 10.1 with procps-3.2.6-18.7. Yeah, I'd go ahead and report the bug (or obtain the source code and attempt to debug it if you are so inclined).

Incidentally, you may already be aware but as a workaround you can do this to ensure your script carries on its merry way without having to turn off set -e:

top -b -n 1 -U $USER || true

What kind of shell lets you set an environment variable like that? With sh you need to export it or set it on the command line.

Thats clever, and it works! It is what I use now.

I was thinking that there had to be some way to suppress the exit code, thanks.

I thought that if you did not export an "environment variable" when you change its value, then the change is only local, that is, the change is only seen within the process that performed that change. Since I execute the top command inside the process that set CPULOOP=1, I would have thought that top would see this new value.

Is this not the way that unix shells typically work? If not, then my experience with normal languages' scoping rules has led me astray.

Note that even if I do

export CPULOOP=1
top -b -n 1 -U $USER

I still get an error exit code, so I will still file a bug report.

Precisely correct... "only...the process".

top is not a command built-in to the shell. The shell must fork() a copy of itself and then that copy must exec() the top command. During the exec, the code for top, in effect, overlays the code for the shell. But a very few things are saved and environment variables are one. Regular variables are not saved.

Meanwhile the parent shell is waiting for its child process to finish. It continues to know that CPULOOP is 1. When you put an & on the end on the line, the parent shell does not wait.. it just keeps going.