Is there a ps or pgrep option or standard practice what will let me list all the running processes on a machine EXCEPT for a few specific ones I don't want to see?

Put another way -- let's say I have four processes running

% ps
PID   TTY        TIME    CMD
26712 ttys000    0:00.45 -zsh
28228 ttys001    0:00.23 -zsh
42083 ttys002    0:00.11 -zsh
42396 ttys002    0:00.16 node

and I have a text file with a few process IDs

% cat /tmp/no-interest.txty 

I want a command line invocation that will display just the process information for 42083 and 42396.

The more general problem I'm trying to solve is I want to show processes that started AFTER a certain point in time. I can get as far as building a list of currently running processes in a text file, but I'm blocked a bit on how to come up with a concise way to use this information to suppress the processes I don't want to see. I know how to do this with a short program in a variety of languages, but I'd like something I can invoke as a one liner and not have to worry about getting that program onto the specific machine I'm debugging.

  • 1
    Are the processes that you want to list related to each other? Are they, for example, in the same process group, or do they have the same parent process? Do you know one or several command names that you want to look for?
    – Kusalananda
    Jan 30, 2023 at 23:50
  • 1
    You could use this command ps -eo pid,user,start,cmd | awk '$3>"17:40"'. But there is a problem here, it will show everything from 17:40:00 till 23:59:59 (not 00:00:01). In that case you should use lstart instead start and this cmd ps -eo pid,user,lstart,cmd | awk '$5>30 || $6>="17:40"'. But again, the same problem if today is the last day of this month and you work late (to midnight and beyond) :).
    – Damir
    Jan 31, 2023 at 2:01
  • 1
    By default ps is sorted by pid and due to pid and lstart match in terms of "sorting-increasing", you could use pid of the time you are interested in. Let's say that process with 7895 pid has STARTED time you are interested in: ps -eo pid,user,lstart,cmd | awk '$1>=7895'. With this cmd you get rid of "midnight/last/next day".
    – Damir
    Jan 31, 2023 at 2:46
  • 1
    @AlanStorm, reading your question again... Do you actually need this: ps | sed "1,/$$/d"? It will suppress everything "above" your current shell (including your current shell).
    – Damir
    Feb 1, 2023 at 14:28
  • 1
    @AlanStorm, actually it seems you need this: ps | sed -n /$$/',$p' -suppress everything "above" last/current shell, print current shell and everything "below".
    – Damir
    Feb 1, 2023 at 14:52

3 Answers 3

ps | grep -vFwf /tmp/no-interest.txty

Would filter out the lines of ps which contain any of the lines (word delimited) in /tmp/no-interest.txty. Note however that it looks for them anywhere, not only in the pid field.

Since your shell seems to be zsh, if your ps accepts taking a list of pids as arguments, you could also use zsh's array subtraction operator:

to_exclude=( $(</tmp/no-interest.txty) )
all_pids=( $(ps -o pid=) )
ps -p ${all_pids:|to_exclude}

Or using an anonymous function:

to_exclude=( $(</tmp/no-interest.txty) )
() { ps -p ${@:|to_exclude}; } $(ps -o pid=)

$(</tmp/no-interest.txty) splits the contents of that file on $IFS characters. See also ${(f)"$(</tmp/no-interest.txty)"} for every non empty line in the file.

In any case, you can't rely on pid number to know their start order as pid numbers eventually wrap.

With some ps implementations, you can use:

ps -o lstart

To get the process start time with second precision (in Tue Jan 31 06:05:22 2023 format on my system which uses the ps from procps-ng; in English regardless of the locale). You can parse it with zsh's strftime builtin in the C locale:

zmodload zsh/datetime
(( cutoff = EPOCHSECONDS - 2*60*60 )) # two hours ago
ps -o pid= -o lstart= |
  while read -r pid start; do
    LC_ALL=C strftime -rs t '%a %b %d %H:%M:%S %Y' $start &&
      (( t >= cutoff )) &&
      pids+=( $pid )
(( $#pids )) && ps -p $pids

Also beware that the start time of a process is not necessarily the same as the time it (or one of its ancestors) invoked the command it's currently running, as processes can and often do run more than one command in their life time.

For instance, in sh -c 'sleep 2; exec env cmd' it's the same process that runs, sh, then env, then cmd (and it likely started of as child of your interactive shell).


want to see anything started AFTER I've hopped onto the machine.

ahahahaa! So you would probably also prefer the things that are so short-lived that your probability of intercept¹ them with a single "snapshot" of all running processes is very low.

So, instead of looking at which processes are running now, what about a log of all processes started since you you logged on?

You'll need bpftrace (installed on many system, available on basically any Linux distro). A nice script to show all attempts to start a process by executing a file:

// Taken from https://unix.stackexchange.com/a/584857/106650
// by Rui F Roberto CC-BY-SA 4.0
// Modified to log exec syscalls by Marcus Müller
  printf("Tracing exec syscalls... Hit Ctrl-C to end.\n"); 
  printf("%-9s %-6s %-16s %s\n", "TIME", "PPID", "COMM", "EVENT");

  time("%H:%M:%S ");
  printf("%-6d %s: ", pid, comm);

Less pretty, but a one-liner to copy&paste might always come in handy:

bpftrace -e 'tracepoint:syscalls:sys_enter_exec* { printf("%-6d %s: ", pid, comm); join(args->argv); }'

¹ A term from the world of spectrum analyzers and such – signals that "pop up" for a very short duration in bands and at times you don't know beforehand are pretty hard to "catch" if you have to tune through your bands sequentially and "take a snapshot" of each. Hence, signal detection people look at a sensing system and a class of signals and say things like "you get a probability of intercept of only 0.1%".

  • Oh, sweet! I've been looking for an excuse to get into BPF/eBPF and this might be it. Thank you! Feb 2, 2023 at 23:10
  • Note that the format of the OP's tty device names would seem to suggest they're not using a Linux-based OS. Probably macos Feb 3, 2023 at 8:14
  • thanks again for this answer -- while it's super useful information of interest to me it doesn't help with my very weird and specific use case, where I'm connected to the VM that Docker Desktop uses on MacOS and trying to observe the actual process that running commands on my mac starts on this VM. It appears this VM doesn't have bpftrace on it, and I'm wary of adding too many programs to this VM lest I hose it. Feb 6, 2023 at 22:45
  • Hmm you could write a small program that uses libpftrace and statically link it, I think. Never tried that before, though! Feb 7, 2023 at 7:52

To switch my comments to answer.

  • Using ps' start and awk

To list the all processes after the specific time till the end of the current day (midnight):

ps -eo pid,user,start,cmd | awk '$3>"17:40"'

To list the all processes after the specific time until the end of the next day (next day midnight):

ps -eo pid,user,lstart,cmd | awk '$5>30 || $6>="17:40"'
#cons: will not work as you would like if the next day is the first day of next month.
  • Using ps' pid and awk

Not so clever :), but you could firstly see the pid of the process started time you are interested in, and then awk (sed also, but awk is better here) to filter them.
To list all the processes from the specific time till the last process running (no matter how many hours/days between "specific time" and the last process):

ps -eo pid,user,lstart,cmd | awk '$1>=7895'

Quick explanation:

  • start and lstart - also bsdstart, start_time and stime (latter two look the same to me; lstart provides the longest time format) - ps' standard format specifiers used to display the time when command was started.
  • '$3>"17:40"' - if field 3 is greater than 17:40 print the whole line (record), default action is {print}, so we don't need to type it explicitly.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .