How can I prevent 'grep' from showing up in ps results?
When I search for some process that doesn’t exist, e.g.
$ ps aux | grep fnord
wayne 15745 0.0 0.0 13580 928 pts/6 S+ 03:58 0:00 grep fnord
Obviously I don’t care about grep – that makes as much sense as searching for the ps
process!
How can I prevent grep from showing up in the results?
Turns out there’s a solution found in keychain.
$ ps aux | grep "[f]nord"
By putting the brackets around the letter and quotes around the string you search for the regex, which says, “Find the character ‘f’ followed by ‘nord’.”
But since you put the brackets in the pattern ‘f’ is now followed by ‘]’, so grep
won’t show up in the results list. Neato!
ps aux | grep $(echo fnord | sed "s/^(.)/[1]/g")
Not the most elegant solution but you could do this:
$ ps aux | grep fnord | grep -v grep
Another option I use (especially just to look if a process is running) is the pgrep
command. This will search for a matching process, but not list a grep line for the search. I like it because it is a quick way of search, without regexing or escaping anything.
pgrep fnord
Moreover, to print both the process ID and the process name that is being matched, use (thanks phemmer)
pgrep -l fnord
The ideal solution is the one presented by BriGuy
pgrep fnord
But if you do not want to do that, you can just exclude all lines that matches with grep with:
ps aux | grep -v grep | grep "fnord"
In zsh, grep fnord =(ps aux)
.
The idea is, first run ps aux
, put the result in a file, then use grep
on that file. Only, we don’t have a file, as we use zsh’s “process substitution”.
To illustrate, try
ps aux > ps.txt
grep fnord ps.txt
rm ps.txt
The result should be the same.
General comment on some of the other answers. Some are far to complicated and/or long to type. It is not only a matter of being right, it should be usable as well. But that doesn’t mean some of those solutions are bad; only, they must be wrapped within a mini-UI to make them usable.
Maybe time to use a real sequence this time. The use of pipes makes it parallel.
ps aux >f && grep tmpfs <f
Ugly because there will be a file f
, but it’s not my fault that there is no syntax for sequential processes where you still want to use the output of a previously run process.
Suggestion for the syntax of a sequential operator:
ps aux ||| grep tmpfs
The pgrep command, as others have stated, will return the PID (process ID) of processes based on name and other attributes. For example,
pgrep -d, -u <username> <string>
will give you the PIDs, delimited by a comma (,) of all processes whose name matches being run by user <username>
. You can use the -x switch before to return only exact matches.
If you want to get more information about these processes (as running the aux options from ps implies), you can use the -p option with ps, which matches based on PID. So, for example,
ps up $(pgrep -d, -u <username> <string>)
will give detailed information of all the PIDs matched by the pgrep command.
The simplest shell-agnostic way to do this would be to store it in a variable first:
PS_OUTPUT="$(ps aux)"; echo "$PS_OUTPUT" |grep fnord
From my rc files, I have a case-insensitive version that takes grep’s options:
psl() {
local PS_OUTPUT="$(ps auxww)"
echo "${PS_OUTPUT%%$'n'*}" >&2 # title, in stderr to avoid pipes
echo "${PS_OUTPUT#*$'n'}" |grep -i "${@:-^}"
}
Code walk, one bullet per line of code:
- Capture the verbose
ps
output (in alocal
variable so it is scoped to the function) - Display the first line (the title) in standard error so the results can be further filtered without affecting the title. The substitution says: take
$PS_OUTPUT
and remove everything after the first line feed (regex equiv:s/n.*$//msg
). This prevents us from grepping the title - Display the
ps
output with everything except the first line (regex equiv:s/^.*n//m
) and grep its contents with-i
(case-insensitive) and all of the options handed to this function (in the case of no pattern, use^
to match the start of each line)
Call-out: @EmanuelBerg’s grep fnord =(ps aux)
answer is by far the most elegant, though it requires zsh
. I briefly had it in my rc files, but bash complains about that syntax even despite a conditional that should prevent its evaluation.
You can do it easily, just with defining an ALIAS in your .bashrc
like this:
alias grep='grep -v grep | grep'
Here is a simple example to find PID of ssh-agent
for username without showing PID of grep
process itself:
ps xu | grep "${USER}.*[ ]/usr/bin/ssh-agent" | awk '{print $1 $2;}'
If you want for example to kill ssh-agent
for current user you might use following command:
kill `ps xu | grep "${USER}.*[ ]/usr/bin/ssh-agent" | awk '{print $2;}'`
To create a handy alias add to your ~/.bashrc or ~/.zshrc file the following code:
function function1 () {
ps xu | grep "$1.*$2" | awk '{print $1" "$2" "$11;}'
}
alias mygrep="function1"
And to use alias here are examples to force everyone to learn regular expressions:
. /etc/profile #to make alias usable
mygrep ${USER} ${PROCESS_PATH}
mygrep ${USER} "[f]nord"
mygrep "[f]nord"
mygrep ".*[s]shd"
P.S. I’ve only tested these commands on Ubuntu and Gentoo.
My answer is a variation on the typical answer for searching for “foobar” in a ‘ps’ listing. The argument of “-A” “ps” is more portable than “aux”, I believe, but this change is irrelevant to the answer. The typical answer looks like this:
$ ps -A -ww | grep [f]oobar
Instead I use this pattern:
$ ps -A -ww | grep [^]]foobar
The main advantage is that it’s easier to write scripts based on this patterns because you simply concatenate a static string “[^]]” with whatever pattern you are looking for. You don’t need to strip off the first letter of the string then insert it between the square braces and then concatenate the that back together again. When scripting in shell it’s easier to simply stick “[^]]” in front of the pattern you were lookginfor looking for. String slicing in Bash is an ugly thing, so my variation avoids that. This variation says show the lines where the pattern matches WITHOUT a leading right-square-bracket ]. Since the search pattern to exclude a square bracket actually adds the square bracket to the pattern then it will never match itself.
So you could write a portable ‘psgrep’ command as follows. Here, I make some allowance for differences between Linux, OS X BSD, and others. This adds the column headers from ‘ps’, provides a more custom ‘ps’ format that suits my needs betters, and displays processes listing extra, extra wide so that none of the command-line arguments are missed. Well, most are not missed. Java being Java, it often does things in the worst possible way, so you some java services will run past the maximum allowed length of arguments that the process table will keep track of. I believe this is 1024 characters. The command-lone length allowed to start a process is much longer, but the kernel process table doesn’t bother to keep track of anything over 1K in length. Once the command is started the command-name and argument list isn’t needed against, so what gets stored in the process table is just informational.
psgrep ()
{
pattern=[^]]${1};
case "$(uname -s)" in
Darwin)
ps -A -ww -o pid,ppid,nice,pri,pcpu,pmem,etime,user,wchan,stat,command | grep -i -e "^[[:space:]]*PID" -e ${pattern}
;;
Linux)
ps -A -ww -o pid,ppid,tid,nice,pri,pcpu,pmem,etime,user,wchan:20,stat,command | grep -i -e "^[[:space:]]*PID" -e ${pattern}
;;
*) # other UNIX flavors get a minimalist version.
ps -A -ww | grep -i -e ${pattern}
;;
esac
}
⚠ This answer is GNU-specific. See Wayne’s answer for a more general solution.
Searching for processes
If you’re just looking for fnord
processes, you can use the -C
option to select by command name:
ps -C fnord
This can be mixed with BSD- and POSIX-style format options to your liking. See the ps man page for a complete list.
Looking for someting else ?
If you need something more advanced than an exact search for a command name, don’t loose hope! This can still be done on the ps
side of the pipe. All we have to do is to tell ps
to exclude grep
processes from the result :
ps -NC grep | grep 'fnord'
-C grep
selects all grep processes, and -N
negates the selection. This can be used to search for command arguments, part of a command name, or more complex regular expressions.
Using the -x (exact match) option worked for me. I combined it with -f (full command line), so I could match my process precisely with:
pgrep -x -f "path_i_used_when_starting/cmd params_i_used"
Here’s an extended version of the grep -v grep
solution, filtering out all grep
processes that have not been running for more than a second, which is an improvement over “just discard all occurrences of grep
“.
$ ps -ef | grep -vw "00:00:00 grep" | grep <searchTerm>
respectively
$ ps aux | grep -vw "0:00 grep" | grep <searchTerm>
This may not be portable, and depends on the actual output format of your local ps
command.
You may want to combine this with a coloured grep
output for convenience:
$ alias grep='grep --color=auto'
Elaborating on @Emmanuel-Berg & @Adam-katz answers, you may use the POSIX option "-f $file" together with Bash’s "Process Substitution" "<( $cmd)":
$ ps aux | grep -f <( echo fnord)
The pattern is passed to grep
through a pseudo-file filled up by the command echo fnord
. You may use this handy form which allows for several patterns (fnord
+ syslog
), vs only one:
$ alias psgrep='ps aux | grep -f <( echo -e "$a")'
$ a="fnordnsyslog"; psgrep
For a ‘fnord’ both the regular expression [f]nord or pgrep usage may work.
But for a generic use, the regex is by far more flexible, allowing to get more information on the output in case you need to refine the search. This make the solution more reliable than the one that ‘pgrep’ offers returning just a PID
Imagine a machine where several Tomcat instances are running with processes like:
tomcat 154304 1 8 10:43 ? 00:00:59 /usr/lib/jvm/jre/bin/java -Djava.util.logging.config.file=/somewhere/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Xms512M -Xmx1024M -server -XX:+UseParallelGC -Dignore.endorsed.dirs= -classpath ....
In this case, ‘pgrep’ won’t be reliable (if usable at all) for identifying the exact process you need.
On the other hand:
ps -fea|grep "[j]ava"
probably will not be precise enough, but will allow to further process the output to refine the search
Lots of great answers here already and it probably doesn’t need another, but I just can’t help myself… So what about leveraging command substitution via a "here string"?:
grep fnord <<<$(ps aux)
This ensures that the ps aux
completes prior to the grep (via command substitution), then feeds the result into the stdin of grep (via here string), so that the grep never appears in the ps aux
output.