It's all because of a person by the name of Albert D. Cahalan. Xe did not know BSD.
The original ps
command for Linux was written and first published in March 1992 by Branko Lankester. It was later to become known as "kmem-ps" to distinguish it from "proc-ps" that was published in December 1992 by Michael K. Johnson. M. Lankester's ps
used the kmem
device to read the process table from kernel memory. M. Johnson's ps
used the proc
filesystem to read the process table, and there were several releases of it made over the next few years (e.g. January 1993, January 1994).
These ps
commands provided a fairly old, even then, syntax for the command whose style dated from the pre-getopt()
days of the 1980s. Here it is from a November 1993 release of kmem-ps:
usage: ps 0acefhHjlmnprsStuUvwxXy [t tty] [pid[,pid]...]
j -- job control format, l -- long format, m -- memory format,
s -- signal format, u -- user format, v -- virtual memory format,
X -- register format, y -- syscall format, default -- short format
0 -- include task zero, a -- include processes for all users
c -- print only command name, e -- show env vars, f -- print forest of procs
h -- suppress the header, n -- print the user and wchan fields numerically
p -- print counts in pages, r -- restrict listing to runnable processes
S -- summarize usage for children in CPU time and page fault fields
t tty -- show all proccesses with TTY as their controlling terminal
w -- wide: 132, ww -- 264, www -- unlimited, default -- screen width or 80
x -- include processes without a controlling terminal
U [SYSTEM-PATH [SWAP-PATH]] -- update ps database
As you can see, there was one personality, a single meaning for the letters, and no leading minus sign characters.
The idea of a U
flag (not -U
, notice) comes from a 1986 patch to BSD ps
by that was posted to the Usenet mod.sources
newsgroup (as Volume 6 Issue 83) by Michael A. Callahan.
Along came Albert D. Cahalan a few years later, who rewrote proc-ps. Xe made a lot of claims about it. Unfortunately, the debunking of a lot of those claims has been forgotten, and what stands all of these years later is the ps
manual claiming that this ps
provides Unix, BSD, and GNU option syntax.
It does not.
BSD ps
has used getopt()
option processing since Marc Teitelbaum changed it to do so in April 1990, years before even M. Lankester's version of Linux ps
, let alone M. Cahalan's.
M. Cahalan's ps
provided the old Linux kmem-ps/proc-ps syntax. It later added some syntax that M. Cahalan claimed to be from the AIX ps
command. M. Cahalan, who adamantly propounded the view on Usenet that "BSD sucks and SysV doesn't" that FreeBSD "sucks" and that xyr rewrite of proc-ps was a "standards-compliant /bin/ps
" that supported "your obsolete BSD syntax", ironically was not aware that this had not in fact been the BSD syntax for almost a decade by that point. ps
itself had only just been standardized that year, moreover. The analysis in the standard's rationale of BSD versus AT&T Unix command-line options is a lot more thoughtful than any of M. Cahalan's ever were.
This ps
famously introduced the I_WANT_A_BROKEN_PS
environment variable, which confusingly M. Cahalan blamed on M. Johnson whilst simultaneously claiming xyrself to be responsible for the option parsing. In fact, the twain were maintaining two ps
implementations in parallel.
Bizarrely, if one used getopt()
-style options preceded by minus signs, as was the case for BSD ps
at the time and as the (then) new standard for ps
documented, Cahalan/Johnson ps
would state:
warning: `-' deprecated; use `ps e', not `ps -e'
Actually, it was not using -
that was deprecated. Indeed, the very claim made by M. Cahalan was that xyr ps
was going to work in the standard way using -
— like BSD ps
already had been. This caused numerous questions from perplexed users in the late 1990s and early 2000s, and generally confused the hell out of system administrators and users when books started saying things like:
You might be wondering why we don't use dashes before the flags with ps
. You can use them, but with ps
that's the old fashioned way and you get a warning about sticking with the program.
—Deborah S. Ray and Eric J. Ray (1998). UNIX. Peachpit Press. ISBN 9780201353952. p. 174.
You can still see this discussed in the oldps
manual which talks of being "derived from the BSD version of ps
" although it really was not, it being fairly obviously derived from the Linux one; and which states that "command-line arguments should not be preceeded by a `-' character, because in the future, a `-' will be used to indicate Unix98-standard command-line arguments, while no `-' will indicate the current ``extended BSD'' style of command line arguments".
Some of this was toned down in procps-ng, a third rewrite that was done just after the turn of the century (when "-ng" in project names was à la mode), which is when Cahalan/Johnson ps
became oldps
. As you can see, the ps
manual no longer says "extended". But the new version of ps
(which still involved M. Cahalan) did take the whole multiple-personality idea to extremes. Unfortunately, moreover, it still perpetuated the canard about BSD command-line options, and does so to this day.
In the meantime, the happily single-personality BSD ps
has provided getopt()
command-line option parsing for the past 29 years and 7 days at the time of writing this answer; FreeBSD has gained a procstat
command; the NetBSD and OpenBSD ps
has tracked the new compromise -A
option; and the Single Unix Specification has reserved (but not included) the new BSD -O
option to ps
.
Further reading
- Robert N. M. Watson (2017-01-14).
procstat
. FreeBSD General Commands Manual.
ps
. FreeBSD General Commands Manual. 2018-03-13.
ps
. NetBSD General Commands Manual. 2016-12-02.
ps
. OpenBSD General Commands Manual. 2016-10-26.