IPS(1)

πŸ’– IPS(1) β€” intelligent process status πŸ’–

okay bestie, sit DOWN. this is ips, the intelligent process status program, and yeah it lives in section 1 of the general commands manual. she's basically ps but with main character energy, and i'm gonna walk you through every single thing she does because she is so worth it. 🫢


✨ SYNOPSIS ✨

ips [column-options] [select-options] [sort-options] [other-options]
[macro-names]

that's the whole vibe. a pile of option groups, and maybe some macro names at the end. we're gonna unpack literally all of it, no skips, i promise. πŸ’…


🌸 DESCRIPTION 🌸

Ips is an intelligent ps-like program, and what she does is display process or thread status, which she gets straight out of the /proc filesystem. she's got features specifically built to make tracking active, semi-active, and transient processes actually easy. she is extremely configurable but still efficient β€” like, she only collects as much information as is needed for the particular display you specified, so she can consume as little runtime as possible. efficient queen behavior, no cap. πŸ‘‘

Ips normally displays the process status once and then exits, but she can also act like a top program and display process status repeatedly, over and over. the output can be:

  • displayed line by line, like for a dumb terminal
  • displayed through the curses library using cursor addressing
  • displayed in a raw X11 window

and the output can be colored to highlight rows of interest. 🌈

the info displayed about processes can be selected on a column-by-column basis. each column displays one piece of information about the processes. the set of columns to be displayed and their order can both be changed. slay.

processes can be selected for display based on the values of one or more columns. some selection criteria are pre-defined, for efficiency and convenience β€” stuff like the process id and user name. other selection criteria can be defined using general expressions which refer to any combination of the column values.

the order that processes are displayed is based on sorting the values of one or more columns. the set of columns to sort by, the order of the columns for sorting, and whether each sorting is normal or reversed can all be changed. and yeah, arbitrary expressions based on the values of the columns can also be used for sorting. flexible much?? πŸ’œ

process lines can be colored based on arbitrary expressions, so you can highlight the processes you actually care about. foreground color, background color, underlining, and boldness can all be set for the output. the header lines can be colored too. the whole thing is giving ~aesthetic~.

Ips reads initialization files to define macros, which make it easy to specify useful combinations of configuration options. so like, many different output formats and short-cuts to common option combinations are available. iykyk. πŸŽ€

okay here's the iconic part, pay attention bestie:

options to ips are minus signs followed by short words or phrases. multiple options cannot be combined together following one minus sign (unlike the case with many other utilities β€” don't try it, she's different). options are processed in the order that they are given on the command line. combinations of options which appear to do conflicting actions are permitted. why? because each option merely modifies the state left from the previous options. the state left after all the options have been processed is the one which is actually executed. so it's a stack of vibes that resolves into one final vibe. periodt. πŸ’…


πŸ¦‹ SPECIFYING COLUMNS FOR OUTPUT πŸ¦‹

there are many columns of information which can be selected for display. each column displays one item of information about the displayed processes. the set of columns and their order can be specified by the user. you're the boss. πŸ‘‘

every column has a defined width, which is usually adequate to hold the widest possible data item for that column. that width is just a default though, and it can be changed if you want. the data items shown within a column are left justified, right justified, or centered within the column width, depending on the type of column.

in some cases the column width might not be adequate to show the complete data item β€” and when that happens, the item is truncated to the column width. truncation is indicated by a vertical bar at the right edge of the column. the usual suspects for truncation are the command and environment columns, which display the full command line or environment string for a process. 😭

the ips program enforces a limit on the total width used for displaying columns. if too many columns are selected for display, then one or more columns from the right are removed until the remaining columns fit within the total width. the width limit is usually implicitly set by the terminal or window's width. but if you want, you can explicitly specify the width limit yourself. (this is convenient if the ips program's output is being piped to another process, for example.)

if the final displayed column does not extend out to the total width limit, then that column's width is extended to include the remaining columns. this lets more of the data item be seen before it requires truncation. (typically, the command column is the rightmost column so as to take advantage of these extra columns. smart girl. 🧚)

the options for manipulating columns are -col, -addcol, -remcol, -sep, -width, -colwidth, -vert, and -listcolumns. let's go through them one by one, bestie.

πŸ“ the column options, one by one

  • -col β€” this one first clears any existing list of column names for display, and then sets the new list of column names to be displayed as specified. the columns are displayed in the order specified in the option. and if there's a duplicate column name in the list? only the last use of the column name is effective. 🫢
  • -addcol β€” adds the specified columns to the existing list of column names to be displayed. the new columns are added in the order specified, and by default they're appended after the previously existing columns in the list. if any of the column names are already in the existing list, they get removed from the list before being added back into it. an argument can also be a number, in which case any later column names are inserted into the list starting at the specified column number. out of range column numbers are silently changed to the nearest legal value. for example:
ips -addcol 2 uid gid 999 percentcpu

that adds the user id column as column 2, the group id column as column 3, and appends the percentage cpu column after all other columns. see how the 999 just clamps to the end? yeah. iconic. ✨

  • -remcol β€” removes the specified columns from the list of column names, and honestly she does not care whether or not the columns were in the list in the first place. no drama. πŸ’…
  • -sep β€” specifies the separation between adjacent columns in the display. it has one argument, which is the number of spaces to insert between each pair of columns. the default separation is 2 spaces.
  • -width β€” specifies the total width available for the display of columns. it has one argument, which is the number of columns available. if this option is not given and the output is to stdout, then the width is obtained from the kernel if stdout is a terminal, or else is set to 80 columns if stdout is not a terminal.
  • -colwidth β€” specifies the width of a particular column. it has one or two arguments. the first argument is the name of the column whose width is to be set. the second argument is the desired width of the column. if the second argument is not given, then the column width is set to its default value. pick your fighter. πŸŽ€
  • -vert β€” changes the output format from the default horizontal one into a vertical one. in vertical format, the status for each process is multi-line, where each displayed value uses a complete line. the beginning of each line contains the column heading and a colon character, unless the -noheader option was used. each value is left justified to the same position on the line and can use the rest of the available output width. the -sep option sets the number of spaces between the widest column header and the beginning of the values. and if multiple processes are being displayed, then a blank line separates their status lines. very readable, very demure. 🌸
  • -listcolumns β€” simply lists the names of the available columns and then exits. the heading for the column and the default width of the column is also shown. she's just showing you the menu, bestie. ⭐

and that's where we're pausing β€” there's so much more of ips left to get into, so stay tuned. πŸ’–

✨ SELECTION OF PROCESSES FOR DISPLAY ✨

Okay bestie, let's talk about how you pick which processes show up. You can use a bunch of options, and each one is a condition. A process has to meet all the conditions you set to be shown. No half measures. πŸ’–

The options that set conditions are: -pid, -user, -group, -my, -noroot, -noself, -active, -top, and -cond. (Yeah, -program is described below but somehow not in that list β€” we don't make the rules, we just report them. πŸ™ˆ)

  • -pid β€” followed by one or more process ids. It restricts the display to only those specified processes, if they exist. Using it multiple times just adds more pids to the list. Slay.
  • -user β€” followed by one or more user names or user ids. Restricts to processes with those user ids, if they exist. Multiple uses add to the list of users to show.
  • -group β€” followed by one or more group names or group ids. Restricts to processes with those group ids, if they exist. Multiple uses add to the list of groups.
  • -program β€” followed by one or more program names. Restricts to processes having those program names, if they exist. A program name is the name of the executable file that started the process (like what shows up in the program column). This is not always the same as the name in the command line arguments. Multiple uses add to the list of programs, periodt.
  • -my β€” only selects processes that have my user id. It's giving main character energy, honestly.
  • -noroot β€” disables selection of processes running as root. Sorry root, not today. πŸ‘‘
  • -noself β€” removes the ips process itself from the display. No selfies. πŸ™ˆ
  • -active β€” only shows processes that are either running or have run recently. Lowkey useful.
  • -top β€” limits the display to a specified number of processes. After showing that many, the rest are ignored. If you don't give it an argument, it uses the height of your terminal or window to limit how many processes show up. Highkey convenient. πŸ–₯️

The previous options can only select processes that match a small set of possible conditions. The -cond option is different β€” it understands general expressions. The expression goes in the argument right after the option. (Pro tip: you usually need to quote it so the shell doesn't split it into a million pieces or interpret tokens itself. Just a heads up. πŸ’…)

Warning: The argument usually needs quoting to avoid being split into multiple arguments or having its tokens interpreted by the shell.

You can select processes matching a condition that's any combo of column values for the process. You do this by specifying an expression evaluated for each process. If the result is non-zero or non-null, the process is selected. If the expression can't be evaluated (like dividing by zero β€” mess), no error is generated, but the process just won't be selected. It's giving silent treatment. 😭

Most C expression syntax works on column values: arithmetic, comparisons, logical ANDs and ORs, parentheses, the question mark operator, and some built-in functions. Numeric and string constants can be used. Numbers are usually decimal, octal if they start with a leading 0, hex if they start with a leading 0x. Strings are enclosed in matching single or double quotes. Generally, string values must be compared with string values, and numeric with numeric. But in some cases numeric values can be converted to strings for comparison. Slay. ✨

Column values in expressions are represented by their column names as listed by the -listcolumns option, where unique abbreviations are allowed. Values from multiple columns can be used in the same expression and compared against each other. Some column values are numeric, others are strings. No cap.

The value you get from a column name is usually its base value β€” the unformatted primitive unit of info for that column. For example, for runtimes, that's the number of jiffies of runtime the process has used (i.e., 100's of seconds). A base value can be numeric or string, depending on the column. So like, know your type. πŸ’β€β™€οΈ

You can apply qualifiers to column names to use alternate representations. A qualifier is a word following the column name, separated by a period. Allowed qualifiers: base, show, and test.

  • base β€” same as using the column name by itself (the base value). So extra, but okay.
  • show β€” returns the column value as a string, same as what's displayed for the column. For example, for runtimes, the show value contains colons and periods separating hours, minutes, and parts of seconds. It's giving formatted. ⏰
  • test β€” returns a boolean value (1 for TRUE and 0 for FALSE) indicating whether some useful aspect of the column is true. The meaning varies per column. For example, for the column showing the parent pid, the test returns whether or not the process has a parent (i.e., not 0 or 1). Cute.

There are several functions you can use in expressions: min, max, abs, strlen, match, cmp, str, and my.

  • min, max, and abs β€” take numeric arguments. min gives the minimum of two numbers, max the maximum of two numbers, abs the absolute value of a number.
  • strlen β€” returns the length of the string argument, or if a number was given, the length of the string representation of that number. Count 'em. πŸ”’
  • cmp β€” compares two arguments and returns -1, 0, or 1 depending on whether the first is less than, equal to, or greater than the second. If both are numeric, comparison is on their values. Otherwise, it's done as a string, converting a numeric argument to a string if needed.
  • match β€” takes two arguments (string or numeric; numeric values are converted to the corresponding string). The first is the string to test. The second is a wildcard pattern to match against. Wildcard syntax is like filename matching: ? means any single character, * means any sequence of characters, and [] matches single occurrences of the enclosed characters. Returns 1 if the string matches, 0 if not. It's giving glob vibes. 🌟
  • -str β€” converts its argument to a string value. (Yes, with a dash. We don't know why either. πŸ€”)
  • my β€” takes one argument, which is a column name (possibly qualified). It returns the value of that column for the ips process itself. For example, my(ttyname) returns a string which is my terminal name. To be of maximum use, the uid, user, gid, and group columns return the user's real group and user ids for the my function, even if the ips program has been made setuid. It's giving self-reflection. πŸͺž

Upper case names can be used within expressions β€” they're macro names to be expanded into sub-expressions. These macro names are defined in the initialization files. The expansion must be a complete expression on its own, with proper parentheses and operators. The macro name is replaced with the result of evaluating the sub-expression, so it can be a number or a string. The definition of a sub-expression can also contain macro names, which will also be evaluated. So like, macros all the way down. πŸŒ€


✨ SORTING OF DISPLAYED PROCESSES ✨

The default sorting order is by process id. But you can sort based on any combination of column values. The columns you sort by don't have to be ones you're displaying. So you can sort by secret columns. 🀫

The first specified sorting column is used to sort. If two or more processes have the same value for that first column, they're sorted by the second specified sorting column (if you gave one). This continues as long as there are sorting columns and processes still need sorting. If any processes still have matching values after all sorting columns are used, their process ids are used for a final sort. So it's a tiebreaker situation.

Sorting on a column can be normal or reverse. Normal: smaller values first. Reverse: larger values first. Values are compared based on the column type. Some columns sort on integer values, some on string values. Even if the displayed value is a string, sorting may be based on the underlying integral base value. (The start-time column is an example.) So don't judge a column by its display. πŸ’…

The options for sorting: -sort, -revsort, -sortexpr, -revsortexpr, and -nosort.

  • -sort and -revsort β€” append columns to the sorting list, for normal or reverse sorting. Followed by the list of columns to add.
  • -sortexpr and -revsortexpr β€” append an arbitrary expression to the sorting list, for normal or reverse sorting. The expression can be made of column names, numbers, strings, and operators, just like in -cond. Sorting is done on the result, which can be numeric or string.
  • -nosort β€” removes all columns from the sorting list, leaving only the default sort based on process id. So it's like a reset. πŸ”„

🎨 COLORING OF THE OUTPUT 🎨

okay bestie, so by default every single bit of text ips spits out is just shown in the normal foreground and background colors of whatever output method you're using (think black on white for X11 output, standard vibes ✨).

The information line, the header line, and the process rows can each be colored individually β€” you get to pick foreground colors, background colors, and attributes for each one. it's giving custom aesthetic, honestly πŸ’…

So how do you specify a color? Most generally, it's a string made of three parts, separated by slash characters. Those three parts are:

  1. a foreground color name
  2. a background color name
  3. attribute letters

Rules of the game, and yes you have to actually remember these:

  • If only one slash is present, then only a foreground and background color name are given, with no attributes.
  • If no slash is present at all, then only a foreground color name is given, with no background name and no attributes.
  • If a color name is empty or has the special value default, then that color is the default color of the output method.

The attribute letters can be either 'b' for bold (or bright) text, or 'u' for underlined text, or else both. slay.

Examples of color specifications, since examples are literally the best way to learn:

  • red β€” a foreground of red with a default background
  • /blue β€” a default foreground with a blue background
  • green/yellow β€” a foreground of green with a yellow background
  • default/default β€” a default foreground and background
  • //u β€” a default foreground and background with the text underlined
  • red//bu β€” a red foreground with a default background, with the text underlined and made bold

The colors available depend on the output method, and also on the naming convention of the colors. so it's a little different depending on where you're rendering:

  • For X11 output, many colors are available and can be named explicitly, or else specified using 3 or 6 hexadecimal digits following a hash mark to give the red, green, and blue components.
  • For curses and terminal output, up to 256 colors can be used (according to the capabilities of the terminal). The colors are numeric values from 0 to 255, with the first 8 being the primary colors, the next 8 being the secondary colors, the last 20 or so being gray scale colors, and the others an arbitrary color. Alternatively, the names of the eight primary colors can be used.

Now the actual options, because you know I love a good flag:

  • -infocolor β€” colors the information line πŸŽ€
  • -headercolor β€” colors the header line πŸ‘‘
  • -rowcolor β€” colors the process rows being output, and you can use it one or more times. This option takes two arguments. The first argument is a color specification. The second argument is an expression to be evaluated for the process being shown in the row, as in the -cond option. If the condition is true, then the row will be colored in the specified color. πŸ¦‹

A couple of very important notes about -rowcolor:

  • If multiple -rowcolor options are used and multiple conditions match a row, then the color of the last matching condition is used for the row.
  • Rows which are not matched by the conditions in any -rowcolor option are colored in the default foreground and background colors.

πŸ–₯️ SPECIFYING THE DISPLAY METHOD πŸ–₯️

The output from ips can be displayed using one of several different methods. The -once, -loop, -curses, and -x11 options are used to specify which of the display methods are used. The default option is -once. periodt.

-once and -loop πŸ’«

Both of these specify a display method which writes the process status to stdout line by line, using no cursor addressing sequences. Such output is suitable for saving to a file using redirection of standard output, or for processing in a pipeline. so useful, so unbothered.

The difference between the two options is whether the output is a once-only snapshot or is to be repeated indefinitely in a loop. There is no limit to the number of lines that can be written.

The -clear option can be used with either of these options to write the standard ANSI clear screen escape sequence before each display of the process status. clean slate energy 🧼

-curses 😭✨

This one specifies a display method which uses the curses(3) library for efficient updating of the screen using cursor addressing sequences. It uses the whole terminal screen. The screen can be resized if you want. The number of lines of information is limited by the size of the screen, so only a subset of the status might be visible at one time. BUT the display can be scrolled automatically or manually, so eventually all of the status can be seen. ips is in looping mode for this display method. You can terminate the program by typing the q or ESCAPE characters into the terminal.

-x11 πŸͺŸ

This one specifies a display method which uses a raw X11 window (i.e., without using a terminal emulator such as xterm). The window can be resized if desired. The number of lines of information is limited by the number of rows in the window, so only a subset of the status might be visible at one time. Again, the display can be scrolled automatically or manually so that eventually all of the status can be seen. ips is in looping mode for this display method too. You can terminate the program by typing the q or ESCAPE characters into the window, or by closing the window using the window manager.

X11 window options πŸŽ€

The -display, -geometry, -font, -foreground, and -background options can be used to set the display name, window geometry, font name, foreground color, and background color for the X11 window.

  • If no display name is set, then the default one using the DISPLAY environment variable is used.
  • The default window geometry is 150x50.
  • The default font is the fixed font, which is a mono-space (i.e., fixed-width) font. If a different font is specified, then it should also be a mono-space font.
  • The default foreground and background colors are black and white.
⚠️ Note: The X11 display mode is optional and must have been compiled into ips when it was built. This allows ips to be built for systems which have no X11 libraries installed. If your version of ips does not have X11 support, then the use of the -x11 option will produce an error message and fail. no X11, no window, bestie πŸ’€

Timing + scrolling πŸ•

For all of the looping display methods, the -sleep option can be used to set the sleep time in seconds between updates. (If not given, the default sleep time is 10 seconds.) The argument to this option can be a fixed point value, so that for example, a value of 0.5 specifies a sleep of 1/2 second. obsessed with the precision.

The -scroll and -overlap options can be used for the curses and X11 display modes.

  • -scroll β€” sets the time interval in seconds for automatic scrolling of the display if more processes are displayed than will fit. The default scroll time is 30 seconds. Note that the scrolling interval does not affect how often the display is updated (use -sleep for that). It just means that when the display is next updated, if the required time since the last scrolling has elapsed, then scrolling occurs for that update. It might take many update cycles before scrolling allows all of the process status to be seen. Scrolling wraps around, so that after the last process has been seen in the display, then the next scrolled display will return to the first process again. A scroll time of zero disables automatic scrolling completely.
  • -overlap β€” specifies the number of lines of process status which are duplicated when scrolling occurs. The default overlap is one line.

🧡 THREAD HANDLING 🧡

Depending on the options used, the ips program shows either the status of the processes in the system or the status of the threads in the system. Without any options, only processes are shown. In order to show thread information, the -showthreads option must be used. no cap.

Some processes only consist of one thread of execution, which is the case for most simple programs which have no use for multi-threading. For these processes, the showing of processes or threads gives the same results and there are no problems in interpreting their status. easy, we love a simple one πŸ’–

However, some processes contain more than one thread of execution. Threads share many of their attributes with each other, such as their memory and opened files, but have distinct program counters, stack pointers, runtime, and process state. The threads of a process all have the same process id, but have another id called the thread id (tid) which distinguishes them. One of the threads is called the main thread and has a thread id which is the same as the process id.

the misleading part 😬

When ips shows only processes, then the status shown for a process consisting of multiple threads can be slightly misleading.

  • The shared attributes are shown correctly for the process.
  • However, some of the distinct status values are only those of the main thread, while those values for the other threads are ignored. Examples of these values are the program counter and the process state.

In particular, the process state can give very misleading status of the process. If the main thread is sleeping, but another thread is constantly running, the state of the process can be misleadingly reported as 'S'. In this case, the runtime of the process increases quickly and is shown as active, however it never appears to be running. like bestie is literally sprinting and the label says napping πŸ’€

The runtime of a process is the sum of all of the runtimes of the individual threads, and so is generally meaningful. Note that in a multi-cpu system where multiple threads can simultaneously run, the runtime of a process can appear to increase faster than the clock rate, since multiple threads can contribute the full elapsed time to the process runtime.

thread mode fixes all of this ✨

When ips is showing thread status, then all of the above problems are avoided. Each thread of a process is then shown with its correct status. This includes the program counter, the process state, and the runtime. In this case, threads which are running will show their state as 'R' as expected. Also note that when threads are shown, the display of the main thread is only that of that particular thread, so that its runtime is no longer the sum of all of the threads.

-usethreads and the states column πŸ‘‘

Even when only processes are being shown, the state information for the process can optionally be more accurate than indicated above. If the -usethreads option is used, or if the states column is used, then the ips program will examine the states of all of the threads of a process, and select the most important state among all of the threads as the state to show for the process as a whole. For example, the priority order of the states starts with the 'R', 'D', and 'S' states so that, for example, if any thread is running, then the state of the process is 'R' as expected. icon behavior, honestly.

The states column shows all of the states of the threads of a process using multiple letters and numeric counts. For example, a value of 'R3DS2' indicates that there are three running threads, one thread in a disk I/O wait, and two sleeping threads. πŸ¦‹

COMMAND INPUT WHILE RUNNING πŸ’…

okay bestie so the curses and X11 display modes let you type commands while they're running β€” yes literally, living in the moment, main character energy. πŸ™ˆ The catch: the commands are not visible as you type them to the screen or window. They get read character by character, so each one fires off the instant it's complete β€” no terminating newline required, it's giving instant gratification. ✨ And if the command is one that messes with the display, the current sleep gets canceled so the display can show off the result right away. periodt.

Some commands accept an optional numeric argument which you type in just before the command. That numeric argument can be a non-negative integer value or a non-negative fixed point number. πŸ“ Commands that only take an integer just ignore any fractional part. If you don't pass a numeric argument, the command uses a default value. And if you typed a numeric argument but changed your mind (typo moment 😭), the backspace or delete keys will totally remove any partially typed numeric argument β€” at which point you can type a fresh one if you want. so forgiving of you. 🫢


the vibe-shifting commands 🌈

  • S β€” enables or disables the -noself option for the display, overriding whatever was specified on the command line. Basically: can the ips process itself show up in the display or not. No arguments? The option gets toggled. A zero argument enables display of the ips process if the other conditions are met. A nonzero argument disables display of the ips process in all cases. πŸ’€
  • R β€” enables or disables the -noroot option for the display, overriding the command line. This one controls whether root processes can appear. No arguments? -noroot gets toggled. A zero argument enables display of root processes if the other conditions are met. A nonzero argument disables display of root processes in all cases.
  • M β€” enables or disables the -my option for the display, overriding the command line. This is the "processes that don't have my user id" situation. No arguments? Toggled. A zero argument enables display of processes not having my user id if the other conditions are met. A nonzero argument disables display of those other processes in all cases.
  • A β€” enables or disables the -active option for the display, overriding the command line. This decides whether processes that are not active get shown. No arguments? Toggled. A zero argument enables display of processes if the other conditions are met. A nonzero argument disables display of processes which are not active in all cases.

the timing & navigation commands πŸ¦‹

  • s β€” sets the sleep time to the number of seconds given in the preceding numeric argument. It accepts a fixed point value, so sleeps shorter than one second are absolutely possible ✨. No argument? Sleep time gets set to the default value of 10 seconds.
  • a β€” sets the automatic scrolling time to the number of seconds in the preceding numeric argument. No argument? The autoscroll time is set to the default value of 30 seconds. A value of 0 disables autoscrolling entirely.
  • t and b β€” jump the display to the top or the bottom of the process list. (i.e. the first and last pages of the display.)
  • n and p β€” move the display to the next or previous page of the process list. If the next page would go past the end of the list, the first page is displayed. Same energy in reverse: if the previous page is before the beginning of the list, the last page is displayed. it loops, she's flexible πŸ’«
  • o β€” sets the number of lines of overlap between pages of data to the value in the preceding numeric argument. No argument? The overlap value defaults to 1 line.

the display-tweaking commands πŸŽ€

  • i β€” enables or disables an information line at the top of the display. That line shows: the total number of process and threads in the system, the number of threads or processes currently being shown, the sleep time, the currently displayed page number, and β€” if the display is frozen β€” an indication of that fact. πŸ₯Ά No arguments? The information line display is toggled. A zero argument disables the line. A nonzero argument enables it.
  • h β€” enables or disables the column header line at the top of the display. No arguments? Toggled. A zero argument disables the header. A nonzero argument enables the header.
  • 'f' β€” enables or disables the frozen state of the display. No arguments? The frozen state is toggled. A nonzero argument freezes the display. A zero argument unfreezes it. While frozen, ips simply waits for further commands β€” ignoring the normal sleep and autoscroll times. Automatic collection of new process data is disabled, and automatic scrolling is disabled too. BUT β€” you can still type commands while frozen to do scrolling or process status updating on demand. it's not dead, it's just chillin 😌

  • A SPACE or RETURN character updates the display immediately, and new process data will be collected for the display. This happens even if the display is currently frozen. πŸ”₯
  • r β€” refreshes the contents of the display to fix any glitches. Mostly intended for curses use when other programs output to the screen, or when the terminal emulator is misbehaving. (the terminal said "not today" and r said "bet" πŸ’…)
  • q or ESCAPE β€” quits ips. bye bestie 🫢
  • All other characters are illegal and ring the bell. πŸ”” iconic behavior, honestly.

✨ INITIALIZATION FILES AND MACROS ✨

okay bestie so here's the tea: to make everything comfy and let you customize ur output exactly how you like it, ips peeks at two init files when it starts up. 🫢

The first one it reads is the system initialization file /etc/ips.init β€” that's where the system-wide defaults for ips live. πŸ‘‘

The second one is the user initialization file $HOME/.ipsrc, chillin' in each user's home directory. That's ur personal space to tweak the system defaults however u want. 🌸

You can turn off reading ur user init file with the -noinit option. And bestie, listen: if u use it, it must be the very first option after the command name. No cap. 🚨

The contents of these files are sooo simple. Every line can be: blank, a comment, or a macro definition. Periodt. πŸ’…

  • If any line ends in a backslash, that backslash gets swapped for a space and the next line gets appended to it (line continuation, slay).
  • Comment lines have a hash mask character as their first non-blank character.
  • Comment lines and blank lines? Ignored. bye. πŸ™ˆ
⚠️ The first line of the initialization files must consist of the word #ips#. If it doesn't, an error message gets generated and the program exits. So like... don't skip that line, fr fr. 😭

Macro definitions are how u replace a single argument on the command line with a possibly huge replacement string full of many arguments. And plot twist: the replacement strings can themselves use macros, and those new macros get removed and replaced too! This keeps going until either no macros remain to be replaced, or until the allowed macro depth is exceeded. Recursion but make it fashion. πŸŒ€

Macro names are usually told apart from non-macros by starting with upper case letters. Since column names are all lowercase, there's zero problem distinguishing a column name from a macro name. ✨

There are three different types of macros in ips, and the type is determined by where the macro is used in the command line:

  1. commands β€” command macros define a list of command line options and their arguments.
  2. columns β€” column macros define a list of column names.
  3. expressions β€” expression macros define a sub-expression for the -cond, -sortexpr, and -revsortexpr options.

Because these three types mean such different things, and because a replacement string would generally make zero sense if used for a different type, the three types have independent name spaces. So yes, the same macro name could be defined three times, once per type. (But that's probably bad practice, ngl. πŸ™ˆ)

To define a macro in an initialization file, u use one of the keywords option, column, or expr, followed by the macro name and the replacement strings for the macro β€” all on one line (taking into account the whole backslash line-continuation situation). Macro names must begin with an upper case letter. πŸ’–

πŸŽ€ The option keyword

Defines a macro as being one or more command line options. The replacement string is a bunch of space-separated options and arguments, just like on the command line, including the leading hyphens for the options. Arguments for options must be contained within the macro expansion itself. And the macro expansion can itself contain macros, which get expanded into even more options. πŸ¦‹

As the single exception to the upper-case rule: if a word appears on the ips command line that isn't an option, and can't be an argument for an option, then that word β€” with its initial letter converted to upper case β€” is treated as an option macro to be expanded. ✨

An important special case of this: a word typed immediately after the ips program name. That's typically a macro name defining a particular format of display. For example, ips top would expand the option macro named Top, which could be defined to emulate the output of the top program. iconic, honestly. πŸ‘‘

πŸŽ€ The column keyword

Defines a macro as being a list of column names. The replacement string is a bunch of space-separated column names. The macro expansion can itself contain macros, which get expanded into even more column names. 🌸

πŸŽ€ The expr keyword

Defines a macro which is an expression used for the -cond, -sortexpr, or -revsortexpr options. The replacement string is a complete expression using numbers, strings, column names, and possibly other macros, which will also be expanded. 🧚


Here's an example of a valid initialization file, verbatim bestie, look at her:

#ips#

# The special command macro run by default
option    SysInit   -col pid parent user summary runtime command

# Definitions for other commands of interest
option    Stop -cond Stop
option    Cmd  -col pid command -sep 1
option    Env  -col pid environment -sep 1
option    Vert -vert -sep 1 -col All
option    Mytty     -cond Mytty

option    Top  -sep 1 -col pid user summary runtime \
          percentcpu command -revsort percentcpu \
          -revsort runorder -curses -clear -active

# Definitions for groups of columns
column    Run  runtime idletime percentcpu
column    Regs eip esp
column    Sigs signalcatch signalignore signalblock
column    Size residentsetsize percentmemory size
column    Stdio     stdin stdout stderr

# All columns
column    All  pid parentpid uid user gid group \
          processgroup ttyprocessgroup \
          state flags nice priority realtimepriority policy \
          systemtime usertime runtime childruntime \
          threads percentcpu runorder \
          residentsetsize size percentmemory \
          active idletime starttime age realtimer \
          eip esp waitchannel waitsymbol \
          pagefaults minorpagefaults majorpagefaults \
          pageswaps childpageswaps \
          signalcatch signalignore signalblock \
          ttyname ttydevice \
          openfiles stdin stdout stderr stdio \
          currentdirectory rootdirectory executable \
          summary program command environment

# Definitions for expressions used in conditions
expr Me   (uid == my(uid))
expr Server    (uid < 100)
expr User !Server
expr Stop (state == 'T')
expr Mytty     (ttydev == my(ttydev))

The special option macro names SysInit and UserInit are automatically expanded (if they're defined) at the start of every run of ips. These macros initialize parameters to default values. Examples of that init: specifying the default list of columns to display, and the default sleep time when looping. 😴

SysInit's definition usually lives in the system initialization file, while UserInit's usually lives in the user's initialization file. And any parameters set by these macros can still be modified by using options on the command line. πŸ’…


🌈 USEFUL MACROS 🌈

The standard supplied system initialization file /etc/ips.init contains many macros of interest. This section describes some of the standard macros provided. And remember: u can use these macros in lower case on the command line. lowercase = the move. ✨

⚠️ Warning: these macros might not actually work on ur system as described here, since they can be changed by the system administrator. The sysadmin may also have added other useful macros not described here. U should examine the macro definitions in the initialization file to make full use of ips. iykyk. πŸ”
  • The default macro SysInit adds a condition to only show ur own processes. So to see other users' processes, u must disable that condition explicitly, or use a macro that disables it. The Nocond macro removes all conditions on the selection of processes, letting u see every process. πŸ‘€
  • The user name column isn't shown by default. The Long macro changes the displayed columns to include the user name and the parent pid. πŸ’–
  • The All macro combines the Nocond and Long macros to show all processes in a nice display. slay.
  • The Pack macro shows many useful columns together, including the user and group ids, the state of stdio, and the process age. πŸŽ€
  • The Cmd and Env macros show only the process id and the command line or environment, so u can see way more of these columns than usual. πŸ¦‹
  • The Files macro shows columns related to files, like the number of open files, the status of stdio, and the current and root directories. πŸ“
  • The Cpu macro shows a snapshot display of the currently active processes. It has a two second sleep in order to detect running processes. The Top macro shows the same display format, but in a looping manner using curses, and including recently active processes. πŸ”₯
  • The width of the runtime columns is not adequate to hold really large runtimes. The Widerun macro increases the width of these columns to show larger runtimes. 🌸
  • The Wide macro makes the output width be as large as possible, allowing the showing of very long command lines or environments. 🌈
  • The Vert macro sets the output format to vertical and shows every column value. πŸ’œ
  • The Tty macro adds a condition to only show processes which are on a terminal.
  • The Mytty macro adds a condition to only show processes which are on ur own terminal. 🫢
  • The Stop macro adds a condition to show stopped processes. πŸ›‘

πŸ‘‘ OTHER FEATURES πŸ‘‘

There are several other features of ips that u can specify using command line options. These options are -default, -read, -initsleep, -noheader, -activetime, -deathtime, -synctime, -listmacros, -listcolumns, -version, -end, and -help. ✨

The -default option is useful to reset parameters that have been set by previous options. In particular, it's useful to reset parameters that have been set by the initialization files. It accepts one or more option names (without the leading hyphens). Any parameter set by the indicated option is restored to its initial state as when the ips program started. For example, -default pid removes any previous restriction on the process ids that can be shown. reset era, we love to see it. πŸ’…

The output from the -help option will briefly describe the use of the remaining options. πŸ™Œ

✨ COLUMN DESCRIPTIONS ✨

Okay bestie, some of these column names are like totally obvious, but a bunch need a lil explanation, so here we go. πŸ’…

First things first: because of the permissions on /proc, some column values might be a whole "not available for every process" situation. Columns marked as restricted only show up if the process has your own user id, you're running as root, or the ips program itself is setuid to root. Periodt.

  • state β€” shows the current state of the process. It's a single letter: 'R' is runnable, 'D' is disk I/O, 'T' is stopped, 'S' is sleeping, 'Z' is zombie, and ' ' is dead (nonexistent). πŸ’€
  • eip and esp β€” show the instruction pointer and stack pointer of the process. The instruction pointer is also known as the program counter, or PC. 🧠
  • waitchannel β€” shows the hex address within the kernel that the process is sleeping on. This is zero if the process is not sleeping. Usually, different reasons for sleeping use different addresses. 😴
  • waitsymbol β€” shows the symbolic address within the kernel that the process is sleeping on. This is blank if the process is not sleeping.
  • program and command β€” show the program name and command line of the process. The program name is just the name of the executable file without any arguments. The command line shows the arguments that the program was started with. If no command line arguments were supplied to the program, then this column shows the program name enclosed in parenthesis.
  • idletime β€” shows the number of minutes that the process has been idle. An idle process is one which has not (detectably) run at all in the indicated interval. The idle time is only known by examining processes over time, so the true idle time of a process which existed before ips was run is not known. In these cases, the idle time is simply the amount of time that ips has been running, and the times are marked with a leading plus sign.
  • active β€” shows whether or not the process has been active. It shows one of the values "active" or "idle". This column is provided mainly for use in sorting and selecting.
  • ttyname and ttydevice β€” show the controlling terminal of the process, which is usually the terminal where the user logged into. The device is the kernel's id for the terminal, and is just a number. The name is found by searching /dev for a character device which has that same id and then displaying the device name with the /dev removed.
  • user, uid, group, and gid β€” show the user ids and group ids of a process. The uid and gid are the numeric ids as used by the kernel. The user and group are the conversion of those ids to user names and group names, as found in the /etc/passwd and /etc/group files.
  • percentcpu β€” shows the percentage of CPU time that the process has used in a certain recent time interval called the sample interval. The samples are taken at a maximum rate of five times a second according to the current sleep time of the ips program. The sample interval is a sliding value so as to give an average cpu percentage over a specified number of seconds. This makes the values less 'jumpy' than instantaneous cpu percentages would give and act more like the system load averages. The sample interval is set using the -percentseconds option, which can have a value from 0 to 20. The default sample interval is 10 seconds. The percentage runtime is 100 times the quotient of the runtime used during the sample interval by the sample interval itself. Note that for a multi-threaded process on a multi-cpu system, the percentage runtime can reach multiples of 100.
  • residentsetsize β€” is the number of K of memory used by the process. Pages of a process which are not in memory are not counted by this column.
  • starttime and age β€” show the time at which the process was created. The start time is the time of day the process started, and if the process was in existence for over one day, then the number of days previously that the process was started. The age is the number of minutes that the process has existed, and is the difference between the current time and the time that the process started.
  • flags β€” shows some kernel flags associated with the process, in hex.
  • minorpagefaults, majorpagefaults, and pagefaults β€” show the number of minor page faults, major page faults, and the total page faults of the process. Minor page faults are faults on pages that do not require any disk I/O, which are copy on write or touching empty pages. Major page faults are faults which require disk I/O, such as reading in of text file pages or swap pages.
  • signalcatch, signalignore, and signalblock β€” show the state of signal handling for the process. Each of these value is a hex value, where signal N is bit number N-1 (counting from bit 0 at the right). Caught signals are those for which a signal handler is installed. Ignored signals are those for which the process is ignoring signals. Blocked signals are those which are pending delivery, but which the process has blocked from being delivered.
  • openfiles β€” displays the number of open files that the process has. This column is restricted.
  • runorder β€” shows the relative run order of the processes. The run order is a monotonically increasing value representing the number of process samplings that ips has made since it started. Processes are assigned the current run order value whenever they are seen to have been active since the last sample. Processes with a larger run order value have run more recently.
  • currentdirectory β€” gives the current working directory of the process in the kernel's internal values of device number and inode number, separated by a colon. The device number is in hex, and the inode number is in decimal. This column is restricted.
  • rootdirectory β€” gives the root directory of the process in the kernel's internal values of device number and inode number, separated by a colon. The device number is in hex, and the inode number is in decimal. This column is restricted.
  • executable β€” gives the device number and inode number of the executable file for the process, separated by a colon. The device number is in hex, and the inode number is in decimal. This column is restricted.
  • realtimer β€” shows the amount of time that the process wants to sleep before being woken up. This is either just the number of seconds, or else is the number of seconds and parts of seconds. This value does not decrement as time passes, so you don't know when the sleep time will expire.
  • stdin, stdout, and stderr β€” show the file names associated with the stdin, stdout, or stderr file descriptors of the process. These columns are restricted.
  • stdio β€” shows a summary of the files associated with the stdin, stdout, or stderr file descriptors of the process. This is in the form of a three character string with one character for each of the stdin, stdout, and stderr file descriptors. The character is 'T' for a terminal, 'P' for a pipe, 'S' for a socket, 'N' for /dev/null, 'F' for some other file, and '-' for a closed file descriptor (or if the information is unavailable). This column is restricted.
  • summary β€” shows many flag characters which summarize some of the state of the process. This consists of a string of 14 characters, where each character is either a dash or a letter. A letter indicates the specified condition is true for that character position, whereas a dash indicates that the condition is false for that character position. Here's the breakdown, bestie:
    • Character 1 β€” is the state of the process, except that if the process is sleeping, then it is 'A' for recently active, or 'I' for idle, and if the process has died (i.e., no longer existent), then it is '-'.
    • Character 2 β€” is 'W' if the process has no resident memory, and is therefore swapped out.
    • Character 3 β€” is 'N' if the process has been niced, and is 'H' if the process has been given as higher priority than normal.
    • Character 4 β€” is 'S' if the process is a session id leader.
    • Character 5 β€” is 'P' if the process is a process group leader.
    • Character 6 β€” is 'T' if the process has a controlling terminal.
    • Character 7 β€” is 'F' if the process is a foreground process, which means that its process group matches its controlling terminal's process group.
    • Character 8 β€” is 'I' if the process has no parent, meaning it is owned by init.
    • Character 9 β€” is 'h' if the process is catching SIGHUP or 'H' if the process is ignoring SIGHUP.
    • Character 10 β€” is 't' if the process is catching SIGTERM or 'T' if the process is ignoring SIGTERM.
    • Character 11 β€” is 'U' if the process has your user id.
    • Character 12 β€” is 'G' if the process has your group id.
    • Character 13 β€” is 'R' if the process is running as root.
    • Character 14 β€” shows the age of the process. It is 'N' for a new process, 'M' for a process one minute old, 'F' for a process five minutes old, 'T' for a process ten minutes old, 'H' for a process one hour old, 'D' for a process one day old, and 'W' for a process one week old.

πŸ”₯ PERFORMANCE πŸ”₯

okay bestie, here's the tea on speed: ips is lazy on purpose and that's actually iconic of it. Some data only gets collected if the columns using that data are used. And "used" here means any of these three: displaying, selecting on, or sorting by the column. So if you skip columns you don't need, you literally save the time it would've taken to collect that data. free performance, no cap. πŸ’…

Most process status comes from scanning the /proc directory, looking for filenames that are numeric (those are the process ids, bestie). And for every single one of those processes, the file /proc/<pid>/stat has to be opened and read to collect most of the process status. every. single. one. 😭

If you asked for detailed thread info, then it's even more work: the directories /proc/<pid>/task get scanned for numeric filenames too (those are the thread ids), and for each one of those threads, the file /proc/<pid>/task/<tid>/stat must be opened and read to collect the thread status. so many little opens. so many.

And there might be additional files in /proc that need reading to get the full status you asked for.

Using the -pid option saves a ton of work, because then the scan of /proc is skipped entirely and only the process ids you specified get examined. And using -noself avoids looking at our own process. small W but a W.

Using the -my, -user, -group, and -noroot options saves time too: it skips the reading and parsing of process status for the processes that got eliminated, and it stops collection of other data for those eliminated processes. bye bye unnecessary work ✨

The -top and -cond options may save time by eliminating the display of process information. but, and this is important bestie, the information is still collected. it's giving "we did the homework but didn't turn it in". 🫢

The -synctime option changes the interval on which the full process status is collected for inactive processes. (go peek at the RISKS section below, it's right there.) Setting this to a shorter time interval will increase the runtime. shorter sync = more churn = more time. periodt.

Now let's do the column-by-column receipts, because each one has its own little cost:

  • The command column requires the opening and reading of /proc/<pid>/cmdline whenever the process has changed state, or when the synctime has expired.
  • The environment column requires the opening and reading of /proc/<pid>/environ whenever the process has changed state, or when the synctime has expired.
  • The active, idletime, and percentcpu columns and the -active option require that the ips program sample the processes twice before displaying anything, with a small sleep between the two samples. So there will be a delay before seeing anything. sorry bestie, it's gotta look twice. πŸ™ˆ
  • The ttyname column requires the reading of /dev to find the list of character devices. This work adds a delay to the program before anything is displayed. It is only required once per run, so, tiny mercy. πŸŽ€
  • The openfiles column requires the reading of all the files in /proc/<pid>/fd whenever the process has changed state, or when the synctime has expired.
  • The stdin, stdout, stderr, and stdio columns require the link values of one or more of the /proc/<pid>/fd/<fd> files to obtain their information whenever the process has changed state, or when the synctime has expired.
  • The currentdirectory column requires the reading of the /proc/<pid>/cwd file whenever the process has changed state, or when the synctime has expired.
  • The rootdirectory column requires the reading of the /proc/<pid>/root file whenever the process has changed state, or when the synctime has expired.
  • The waitsymbol column requires the reading of the /proc/<pid>/wchan file whenever the process has changed state, or when the synctime has expired.
  • The executable column requires the reading of the /proc/<pid>/exe file whenever the process has changed state, or when the synctime has expired.

πŸ’€ RISKS πŸ’€

okay so this is the part where we're honest. The determination of whether a process has been active since the last sample is not completely foolproof. Some of the process data is only collected when a process has been active, or else has not been collected for a while, and so there is a small risk that the data is obsolete. The columns which are not necessarily collected on every update are the ones which require examining /proc files other than the main status file. These columns include the command line, the environment, the current directory, and the number of opened files.

The ips program checks many process status values to determine whether or not a process has been active since the last sampling. If any of these differ from the last sampling, then the process is active. So here's the whole checklist, bestie: the process state, runtime, flags, page faults, start time, stack pointer, instruction pointer, and wait channel. New processes are always active, and processes whose state is 'R' or 'D' are always active. no debate.

It is possible that a process which wakes up for only a short time, does very little, and then goes back to sleep will appear to be inactive. (The kernel only has a 1/100 second runtime resolution, and so the small runtime of the process might not have been seen by the kernel.) the kernel literally blinked and missed it 😭

The -synctime option can be used to reduce or expand this risk of showing obsolete data. It accepts the number of seconds at which the complete status of the process is collected even when it is idle. It defaults to one minute. Setting the synctime to zero produces a status with no obsolete data. zero = always fresh, always re-reading, always working. your call. ✨

The list of user names, group names, and device names are only collected when ips is first started. Changes to the password file, group files, or device files will not be seen while the program is running. so if you edited those mid-run, congrats, ips doesn't know and doesn't care. 🫢

The data collected by ips is dynamic. It can change even while the status is being collected for a single process. So the data shown is only a snapshot and is never absolutely consistent. it's a selfie, not a portrait. πŸ“Έ


🚧 LIMITS 🚧

The following are some limits to the operation of ips. These are compile-time constants, and could be increased if required by recompiling the program. so, fixable, but you're gonna have to build it yourself, bestie.

  • You can only specify 100 process ids for the -pid option.
  • You can only specify 100 user names or ids for the -user option.
  • You can only specify 100 group names or ids for the -group option.
  • You can only have 1000 arguments on a command line.
  • The maximum output width is 31K characters, where K is 1024.
  • The maximum command string length is 10K.
  • The maximum environment string length is 20K.
  • The maximum program name string length is 32. This length is imposed by the kernel, which only has a buffer of this size. blame the kernel, not us πŸ’…
  • The maximum separation between columns is 20 spaces.
  • The maximum depth of expansion of option macros is 20.
  • The maximum depth of expansion of expression macros is 20.
  • The maximum number of seconds for calculating cpu percentages is 20 seconds.

πŸ› BUGS πŸ›

Listen, we love ips, but let's be real about its little quirks. πŸ™ˆ

The -clear option clears the screen by outputting the ANSI escape sequence for clearing the screen. If your terminal does not understand this escape sequence, then this option will not work correctly. your terminal has to speak the language, bestie.

Proportional spaced fonts do not work correctly in the X11 display mode. not it's vibe. πŸ’€

Using both of the -vert and -top options together without any argument does nothing useful. The number of processes shown will be dependent on the screen height, but the output will not be limited to the screen height, since each process status prints on multiple lines. so... it just does a thing that isn't the thing you wanted.

Pagination of output when using the -vert option is not correct.

There are no quoting characters for macro definitions, so you cannot create single arguments which contain blanks. This means that if you use the -cond, -sortexpr, or -revsortexpr options in the macro definition file, then the following expression must not contain any blanks. However, you can use blanks in the definition of an expression macro. loophole found, loophole used. πŸŽ€

The specification of a window position for X11 using the -geometry option does not work correctly.

This program is dependent on the layout of the /proc file system, which changes depending on the kernel version. This particular version of ips works for kernel version 2.6.32. so yeah, if your kernel moved on, ips is still texting from 2.6.32 like nothing happened. 😭


🌈 FUTURES 🌈

wishlist time, and honestly, same. ✨

I would like to allow macros to accept arguments enclosed in parenthesis, and have those arguments substituted into the replacement string at the locations matching parameter names for the macro.

I would like to allow user-defined columns where the user can define the format of the data to be displayed using the results of expressions on other column data. user-defined columns? yes please, that's main character energy. πŸ‘‘


πŸ’– CREDITS πŸ’–

Some of the knowledge on how to process and display the data from /proc was obtained by reading the procps version 0.97 code by Michael K. Johnson. ty king 🫢

The pattern matching code was adapted from code written by Ingo Wilken. also ty. ✨


πŸ‘‘ AUTHOR πŸ‘‘

David I. Bell dbell@tip.net.au


and that's a wrap on the whole page, bestie!! πŸŽ‰ this was IPS(1), dated 8 January 2026 β€” written by David I. Bell (hi sir, ily, thanks for the manpage πŸ™). now go forth, read your processes, and don't let the obsolete data catch you slipping. no cap. πŸ’…πŸ’–βœ¨

πŸ“¦ where this page comes from