It is true. Even on the latest FreeBSD 11.0 (I checked the source tree).
ps | grep procName
can fail.
$(ps -p pid)
can fail.
ps
itself on a non-interactive shell can fail.
They can fail if procName comes somewhere after 79 characters (e.g. /abc/def/ghi/…/procName).
Or if you’re using ps -o comm=
and trying to match against a command
line, it can fail if the command line became too long.
79 ought to be enough
I looked up the source code for FreeBSD (8.4) ps
, and here it is:
/* ... */
else if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&ws) == -1 &&
ioctl(STDERR_FILENO, TIOCGWINSZ, (char *)&ws) == -1 &&
ioctl(STDIN_FILENO, TIOCGWINSZ, (char *)&ws) == -1) ||
ws.ws_col == 0)
termwidth = 79;
What that’s saying is: if you’re not on a terminal, or if your system is unable to tell us how wide your terminal is, then we’ll assume your terminal is 79 characters wide!
I wrote a program to test when the ioctl()
above returns non-zero.
It does if:
- You’re piping
ps
to another program, saygrep
- You’re running a non-interactive shell (e.g. over ssh: Ansible!)
Shouldn’t we assume unlimited width, if we’re not really writing to a terminal? Go figure.
The fix
Anyway, the fix is: Use the -w
option. TWICE. So it is actually:
-ww
. Unless you want your terminal to only go up from 79 to 131
characters. I’m not kidding!
case 'w':
if (wflag)
termwidth = UNLIMITED;
else if (termwidth < 131)
termwidth = 131;
wflag++;
break;
So, please use: ps -ww | grep procName
. Thank you.
What about Linux and Mac?
Both of these systems behave OK. Linux gets ps
from procps, which
has this piece of code:
142 if(!isatty(STDOUT_FILENO)) screen_cols = OUTBUF_SIZE;
The ps
on Mac works as expected, although the man page says it’s
derived from BSD. Did Steve Jobs run into it and then get it fixed?
;-)
Update Feb 16 2017
I’ve filed a defect and also uploaded a patch on FreeBSD’s bug database: BUG217159
Update Mar 5 2017
This has been accepted into mainline FreeBSD code. More info.