How "ps" works and why

The simple "ps" command has generated a fair amount of confusion. Almost every Unix variant does it slightly differently; flags have different meanings and column headers or position also differ. This wreaks havoc with cross-platform scripts and has also caused bitter comments now and then. As I explained at I_WANT_A_BROKEN_PS , I had the same misunderstandings. Albert Cahalan (author of the Linux procps package, which includes "ps") noticed a newsgroup thread where I had made such a comment, and took the time to reply to me.

After reading his explanation, I understand that I was quite wrong. Albert gave me permisson to quote from his email:

There's an ongoing effort to gently transition to new syntax.
It goes like this:

1. add a warning about the obsolete syntax
2. add the new syntax for a non-default personality
3. make the new syntax be the default
4. if the old syntax was really evil, remove it

I try to make this happen over a period of several years,
so that nobody gets caught by surprise. Unfortunately,
many Linux distributions like to patch out the warnings.
Their users will suffer horribly when things break in
some future release. To combat this, I break the rotten
patches by adding comments that explain the problem.
Everyone but Slackware has gotten the message by now.

Right now, "-x" is in the hpux personality. When I add
it to the default personality next year, "ps -ax" will
no longer issue a warning and fall back to "ps ax".
I'm pretty much waiting for Fedora to go out as Red Hat
first, and giving Slackware one last chance to warn people.

As to current behavior...

There is no oldps anymore. It was, literally, the old ps.
(there was a complete rewrite) You get 90% of oldps by
setting PS_PERSONALITY=old though.

Doing "ps -e" is always legit, though the meaning differs
by personality. You'll get a warning from "ps -u" though,
because that's only legit in BSD-like personalities.
The e and -e should mean...

oldps -e                   display the environment, with warning
PS_PERSONALITY=old ps -e   display the environment
ps -e                      show every process
oldps e                    display the environment
PS_PERSONALITY=old ps e    display the environment
ps e                       display the environment

The old ps had an I_WANT_A_BROKEN_PS variable that you
could set to disable the warning. The new ps interprets
this as setting PS_PERSONALITY=old, which makes it OK
to start BSD options with a "-".

It's not bad to start BSD options with a "-" if you've
given some indication that you actually want ps to interpret
them that way, so there isn't a warning. The warning is
delivered when you rely on your BSD options to be illegal
in the UNIX syntax. To rely on this is dangerous, because
your usage will fail as more UNIX options are added.

The warning amounts to saying "hey, if I add an -x option,
your ps command will have radically different behavior".
As it is, a Google query found one person who noticed that
"ps -aux" breaks when a user named "x" is created. :-(
This person was unaware of the danger because their Linux
distribution had patched out the warning.

Notice the comment about distros patching out the warnings? Perhaps there would have been less confusion had they not done that.

So, Albert is trying to make "ps" righteous, but also trying to avoid doing it too quickly. That's a tough road to walk, I think.

Albert explained some of the details behind PS_PERSONALITY

Well, oldps was discontinued 2 years ago. The latest procps
is version 3.2.2 at Procps - The /proc file system utilities now.

The personality stuff can change the columns that get output.
Try CMD_ENV=irix with "ps -l" for example. The "digital"
personality changes most formats by a column or two. There's
the choice of 4-column or 5-column default output, and the
choice to include processes on other TTYs by default or not.
There's "ps -opid,ppid=MOM,stat,comm" behavior.

Much of it is done via some flags. From my memory...

#define PER_BROKEN_o      0x0001
"ps -opid,ppid=MOM,stat,comm" is 2 columns

#define PER_BSD_h         0x0002
"h" will repeat the header once per screenful
of output instead of disabling the header

#define PER_BSD_m         0x0004
"m" does sorting by memory usage
(instead of thread display)

#define PER_IRIX_l        0x0008
"ps -l" does a funny ADDR:SZ (or SZ:RSS?) column.

#define PER_FORCE_BSD     0x0010
"ps -aux" is interpreted as "ps aux", you get a
5-column display be default, and the default selection
will include processes on other TTYs

#define PER_GOOD_o        0x0020
"ps -opid,ppid=MOM,stat,comm" is 4 columns

#define PER_OLD_m         0x0040
"m" is the old memory usage format
(instead of thread display)

#define PER_NO_DEFAULT_g  0x0080
process selection like SunOS 4 (need "ps axg" to see all)

#define PER_ZAP_ADDR      0x0100
replace the ADDR column with RSS

#define PER_SANE_USER     0x0200
column with usernames titled "USER", not "UID"

#define PER_HPUX_x        0x0400
show command args and do a wide display

#define PER_SVR4_x        0x0800
-x acts like -y

So, sadly, CMD_ENV=sco just sets PER_SVR4_x and PER_BROKEN_o.

As you can see, there's a lot of potential confuson here. Here's Albert again:

I've always felt that the man page was a bit terse, but that
getting wordy would be inappropriate for a man page. I'm not
a fan of info pages, since I never remember to check them myself.

This comment on your web site shocked me:

 "Regarding the ps semantics, I really don't appreciate
 some of these ADD-suffering coders intentionally deviating
 from the POSIX standards so as avoid typing one or two
 extra characters."

Woah. The whole POINT of the changes is to meet the POSIX
standard! The POSIX standard will parse "ps -aux" for sure,
but not in a way that BSD fans could tolerate. I'd expected
former SCO users to use "ps -ef" and recognize what "ps -aux"
does on a Real UNIX system. Simply pretend that Linux is SysV.
Stick to the UNIX syntax and you'll never see a warning.

My ultimate hope is to unify things, to the extent that an
admin can sit down at any UNIX-like system and expect that
both "ps -ef" and "ps aux" will work. I seem to have the
FreeBSD developers 60% convinced. Sun merely needs to cause
/bin/ps to run /usr/ucb/ps when an unparsable option is
found or when the first arg lacks a "-". AIX and Tru64 already
support both syntaxes. In fact, Tru64 (then called OSF/1) is
where I got the idea from in the first place.

I've been thinking of submitting the BSDisms to be included
in the UNIX standard. I almost did last time, but real-life
events got too intense for me to write up the spec in time.
I'd leave out the ability to mix BSD syntax with UNIX syntax,
so that Sun would have an easy time complying.

So, as you see, he's really working hard to "do the right thing" for everyone.

Got something to add? Send me email.

(OLDER) <- More Stuff -> (NEWER)    (NEWEST)   

Printer Friendly Version

-> -> How Linux 'ps' works and why

Increase ad revenue 50-250% with Ezoic

More Articles by

Find me on Google+

© Tony Lawrence

Kerio Samepage

Have you tried Searching this site?

Unix/Linux/Mac OS X support by phone, email or on-site: Support Rates

This is a Unix/Linux resource website. It contains technical articles about Unix, Linux and general computing related subjects, opinion, news, help files, how-to's, tutorials and more.

Contact us

It all sounds good from the pulpit,but come Monday morning all the sinners are back to business as usual writing crappy code. (Tony Lawrence)

Any problem in computer science can be solved with another level of indirection. (David Wheeler)

This post tagged: