Consider the following script wrapcat.sh
(a wrapper for cat) for illustrative purposes. It is run with busybox (ash) in an embedded Linux 2.6 box.
#!/bin/sh
cat $1
Under certain circumstances, this script will not always exit cleanly. For instance, when I run
$./wrapcat.sh /proc/pid/cmdline
for some pid
, I will sometimes be dropped into a shell awaiting a command. After hitting return or the like, it terminates.
My diagnosis is that cat
is interrupted by some signal, and therefore the script does not exit cleanly (as I do not set any -e option). So I am interested in the return status of the cat
command. I modify the script as follows:
#!/bin/sh
cat $1
echo $? # echo the exit status
However, the exit status is not echoed when the script fails to exit cleanly. I'd like to know why the $?
exit status is not echoed (and perhaps more specifically why a clean exit doesn't always happen particularly when catting /proc/pid/cmdline
). The same also sometimes occurs when catting /proc/pid/auxv
and /proc/pid/environ
. Relevant function in source: http://lxr.linux.no/#linux+v2.6.31/fs/proc/base.c#L253
I don't want to necessarily know how to 'fix' this, that can probably be done by setting the aforementioned -e option.
Note: you will probably not be able to reproduce this in something like Ubuntu or Debian - the phenomenon may be specific to busybox ash, cat, or embedded Linux. You can, however, simulate it by interrupting a child process sleep
run inside a script.
E.g. run a script s.sh
:
#!/bin/sh
sleep 1000
echo $?
Then $./s.sh
, ctrl-z, bg
, disown %1
to run the script in it's own process. Now in ps
you will see something like:
15610 pts/35 00:00:00 s.sh
15611 pts/35 00:00:00 sleep
If you go ahead and run kill -2 15611
(on the child process), you observe
$ 130 # the exit status, which does get printed
command line waits for next command without clean exit
$ 130
because the background process has output that130
, your shell doesn't redraw its prompt but that's to be expected since it has no way to know that something has written to the terminal in background.