watch cuts off ps aux output when piped

While working on a (Python) script which is of no consequence here, I have come across a very strange behavior involving watch and ps aux, when the latter is piped to something else.

I have managed to reduce the issue down to a single line. When running

watch "ps aux | grep 'ps aux'"

in a terminal, you usually get several lines of output, as is expected.

output showing 5 results

Note that the top three lines are cut off, and just barely fit ps aux at the end. When you reduce the size of your terminal to where it does not fit any more, it is cut from the results completely.

output showing 2 results

This means that grep only receives the cut off output. What I find most baffling about this is the extremely limited scope for which this happens. It does not happen for either of

ps aux | grep "ps aux"
watch "ps u -C ps"
watch "ssh localhost 'ps aux | grep \"ps aux\"'"

In all of these cases, the list wraps around as expected.

This seems to be the case for both bash and sh, on Ubuntu 15.04.

While I managed to work around this issue in my script, does anyone have an explanation for this behavior?


Solution 1:

Nasal demons.1

man ps says (emphasis mine):

comm       COMMAND   command name (only the executable name).
                     Modifications to the command name will not be
                     shown.  A process marked  is partly
                     dead, waiting to be fully destroyed by its
                     parent.  The output in this column may contain
                     spaces.  (alias ucmd, ucomm).  See also the args
                     format keyword, the -f option, and the c option.
                     When specified last, this column will extend to
                     the edge of the display.  If ps can not determine
                     display width, as when output is redirected
                     (piped) into a file or another command, the
                     output width is undefined (it may be 80,
                     unlimited, determined by the TERM variable, and
                     so on).  The COLUMNS environment variable or
                     --cols option may be used to exactly determine
                     the width in this case.  The w or -w option may
                     be also be used to adjust width.

Indeed, setting the COLUMNS variable manually helps:

watch "ps aux | grep 'ps aux'"

enter image description here

COLUMNS=2000 watch "ps aux | grep 'ps aux'"

enter image description here

1Even though we're not talking about a C compiler...