More elegant "ps aux | grep -v grep" - linux

When I check list of processes and 'grep' out those that are interesting for me, the grep itself is also included in the results. For example, to list terminals:
$ ps aux | grep terminal
user 2064 0.0 0.6 181452 26460 ? Sl Feb13 5:41 gnome-terminal --working-directory=..
user 2979 0.0 0.0 4192 796 pts/3 S+ 11:07 0:00 grep --color=auto terminal
Normally I use ps aux | grep something | grep -v grep to get rid of the last entry... but it is not elegant :)
Do you have a more elegant hack to solve this issue (apart of wrapping all the command into a separate script, which is also not bad)

The usual technique is this:
ps aux | egrep '[t]erminal'
This will match lines containing terminal, which egrep '[t]erminal' does not! It also works on many flavours of Unix.

Use pgrep. It's more reliable.

This answer builds upon a prior pgrep answer. It also builds upon another answer combining the use of ps with pgrep. Here are some pertinent training examples:
$ pgrep -lf sshd
1902 sshd
$ pgrep -f sshd
1902
$ ps up $(pgrep -f sshd)
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1902 0.0 0.1 82560 3580 ? Ss Oct20 0:00 /usr/sbin/sshd -D
$ ps up $(pgrep -f sshddd)
error: list of process IDs must follow p
[stderr output truncated]
$ ps up $(pgrep -f sshddd) 2>&-
[no output]
The above can be used as a function:
$ psgrep() { ps up $(pgrep -f $#) 2>&-; }
$ psgrep sshd
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1902 0.0 0.1 82560 3580 ? Ss Oct20 0:00 /usr/sbin/sshd -D
Compare with using ps with grep. The useful header row is not printed:
$ ps aux | grep [s]shd
root 1902 0.0 0.1 82560 3580 ? Ss Oct20 0:00 /usr/sbin/sshd -D

You can filter in the ps command, e.g.
ps u -C gnome-terminal
(or search through /proc with find etc.)

One more alternative:
ps -fC terminal
Here the options:
-f does full-format listing. This option can be combined
with many other UNIX-style options to add additional
columns. It also causes the command arguments to be
printed. When used with -L, the NLWP (number of
threads) and LWP (thread ID) columns will be added. See
the c option, the format keyword args, and the format
keyword comm.
-C cmdlist Select by command name.
This selects the processes whose executable name is
given in cmdlist.

Disclaimer: I'm the author of this tool, but...
I'd use px:
~ $ px atom
PID COMMAND USERNAME CPU RAM COMMANDLINE
14321 crashpad_handler walles 0.01s 0% /Users/walles/Downloads/Atom.app/Contents/Frameworks/Electron Framework.framework/Resources/crashpad_handler --database=
16575 crashpad_handler walles 0.01s 0% /Users/walles/Downloads/Atom.app/Contents/Frameworks/Electron Framework.framework/Resources/crashpad_handler --database=
16573 Atom Helper walles 0.5s 0% /Users/walles/Downloads/Atom.app/Contents/Frameworks/Atom Helper.app/Contents/MacOS/Atom Helper --type=gpu-process --cha
16569 Atom walles 2.84s 1% /Users/walles/Downloads/Atom.app/Contents/MacOS/Atom --executed-from=/Users/walles/src/goworkspace/src/github.com/github
16591 Atom Helper walles 7.96s 2% /Users/walles/Downloads/Atom.app/Contents/Frameworks/Atom Helper.app/Contents/MacOS/Atom Helper --type=renderer --no-san
Except for finding processes with a sensible command line interface it also does a lot of other useful things, more details on the project page.
Works on Linux and OS X, easily installed:
curl -Ls https://github.com/walles/px/raw/python/install.sh | bash

Using brackets to surround a character in the search pattern excludes the grep process since it doesn't contain the matching regex.
$ ps ax | grep 'syslogd'
16 ?? Ss 0:09.43 /usr/sbin/syslogd
18108 s001 S+ 0:00.00 grep syslogd
$ ps ax | grep '[s]yslogd'
16 ?? Ss 0:09.43 /usr/sbin/syslogd
$ ps ax | grep '[s]yslogd|grep'
16 ?? Ss 0:09.43 /usr/sbin/syslogd
18144 s001 S+ 0:00.00 grep [s]yslogd|grep

Depending on the ultimate use case, you often want to prefer Awk instead.
ps aux | awk '/[t]erminal/'
This is particularly true when you have something like
ps aux | grep '[t]erminal' | awk '{print $1}' # useless use of grep!
where obviously the regex can be factored into the Awk script trivially:
ps aux | awk '/[t]erminal/ { print $1 }'
But really, don't reinvent this yourself. pgrep and friends have been around for a long time and handle this entire problem space much better than most ad hoc reimplementations.

Another option is to edit your .bash_profile (or other file that you keep bash aliases in) to create a function that greps 'grep' out of the results.
function mygrep {
grep -v grep | grep --color=auto $1
}
alias grep='mygrep'
The grep -v grep has to be first otherwise your --color=auto won't work for some reason.
This works if you're using bash; if you're using a different shell YMMV.

Related

Kill 'ps aux' output in one line

I have to do the same thing many times a day:
ps aux
look for process running ssh to one of my servers ...
kill -9 <pid>
I'm looking to see if I can alias process into one line. The output of ps aux is usually something like this:
user 6871 0.0 0.0 4351260 8 ?? Ss 3:28PM 0:05.95 ssh -Nf -L 18881:my-server:18881
user 3018 0.0 0.0 4334292 52 ?? S 12:08PM 0:00.15 /usr/bin/ssh-agent -l
user 9687 0.0 0.0 4294392 928 s002 S+ 10:48AM 0:00.00 grep ssh
I always want to kill the process with the my-server in it.
Does anyone know how I could accomplish this?
for pid in $(ps aux | grep "[m]y-server" | awk '{print $2}'); do kill -9 $pid; done
ps aux | grep "[m]y-server" | awk '{print $2}' - this part gives you list of pids processes that include "my-server". And this script will go through this list and kill all this processes.
I use pgrep -- if you're sure you want to kill all the processes that match:
$ kill -9 `pgrep my-server`
A simple solution is to use pkill:
sudo pkill my-server

grep for process id to get the correct value

I am using the grep command to get a specific process id, but sometimes i am getting two process ids and my output is not correct.
ps -ef |grep AS_Cluster.js
root 2711 2624 0 07:15 pts/0 00:00:00 grep AS_Cluster.js
root 14630 14625 0 Sep13 ? 00:32:36 node xx/x/xx/x/xx/AS_Cluster.js
I want to get the pid value of only node xx/xxx/xx/AS_Cluster.js this process id. Any help
on this
Use preferably pgrep(1) (probably as pgrep -f AS_cluster.js) or pipe the output of ps to some awk command (see gawk(1)) or script.
Try following
ps -ef | grep AS_Cluster.js | grep -v grep

Pidof not finding the process

I want to find out a shell script process ID using pidof or ps command or any.
All i want is only the process id of it. I have used 'pidof -x test.sh'. Which is not working. Note: I don't want to invoke the /bin/sh or /bin/bash - because the script will not work. If i invoke /bin/sh in script, pidof is working.
Please help
pgrep -f script is giving the expected result.
Thanks
Another caveat even for non-script processes:
pidof ignores:
zombie processes
processes in disk sleep
So pidof as well as killall (same codebase) unlike pgrep won't not see your process as long as it is blocked in disk i/o.
I just experienced this with pidof - found, not found, found, ...
ps -ef | grep your_search_string | awk {printf $2}
both pidof and pgrep are options to find the pid for a certain process. do not run ps -ef | grep "your_command" because you have now polluted your result with the grep match too.
use pidof -s [program] to find the parent process id.
use pidof [program] to find ALL pids (ie. python is running multiple times on your system).
use pgrep [program] to match the name of your binary that is run by python (because pidof is not well suited for this use-case).
Fox explained the difference between pidof vs pgrep quite well. see his answer
I'll copy it here for convenience:
The programs pgrep and pidof are not quite the same thing, but they
are very similar. For example:
$ pidof 'firefox'
5696
$ pgrep '[i]ref'
5696
$ pidof '[i]ref'
$ printf '%s\n' "$?"
1
As you can see, pidof failed to find a match for [i]ref. This is
because pidof program returns a list of all process IDs associated
with a program called program. On the other hand, pgrep re returns a
list of all process IDs associated with a program whose name matches
the regular expression re.
In their most basic forms, the equivalence is actually:
$ pidof 'program'
$ pgrep '^program$'
As yet another concrete example, consider:
$ ps ax | grep '[w]atch'
12 ? S 0:04 [watchdog/0]
15 ? S 0:04 [watchdog/1]
33 ? S< 0:00 [watchdogd]
18451 pts/5 S+ 0:02 watch -n600 tail log-file
$ pgrep watch
12
15
33
18451
$ pidof watch
18451

Why can't pgrep find this process?

If I execute the following, which is just a long command that will wait forever
grep 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa abcd'
then pgrep -f can't find the process, if I search for abcd which is contained in the last segment of the long command.
ps auxww|grep abcd finds the process, but I can't use it in a script, as it also finds the grep process self.
If you remove just one a then pgrep -f abcd can find the process, but I have very long command with arguments, so I have run into this pgrep limitation.
Question
What is the correct way to check for such process based on the unique string abcd?
Your edited command is found by either of these commands:
pgrep -f abcd
or even:
ps uxww | grep '[a]bcd'
Let me try that...
$ grep 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa abcd'
Now in another terminal window:
$ pgrep grep
1842
Found it, or at least some grep process:
$ ps -f $(pgrep grep)
UID PID PPID C STIME TTY TIME CMD
501 1842 1836 0 8:59AM ttys004 0:00.00 grep aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa abcd
Yup, that was the process found.
Let's try this:
$ pgrep -f 'abcd'
1842
Seems to work for me.

Inconsistency between perl grep and cli grep

I am doing the following:
#!/usr/bin/perl
use strict;
use warnings;
my $proc = `ps -ef|grep -c myscriptname`;
print $proc;
This prints 2 when I run it inside the script.
ps -ef|grep -c myscriptname on the command line just shows: 1
Why?
same for my $proc = qx/ps -ef|grep -c myscriptname/
UPDATE
To be clear I run this snippet from somerandomscript.pl
Update 2
Following the advice of edorqui I remove -c getting:
12013 15777 15776 0 14:11 pts/6 00:00:00 sh -c ps -ef | grep myscriptname
12013 15779 15777 0 14:11 pts/6 00:00:00 grep myscriptname Argument "12013 15777 15776 0 14:11 pts/6 00:00:00 sh -c ps..." isn't numeric in numeric gt (>) at somerandomscript.pl line 8
from inside the script
The ps -ef command is showing the grep itself.
To skip this behaviour, try grepping for a regex condition that does not match the grep itself:
ps -ef | grep myscript[n]ame
or whatever similar can make it:
ps -ef | grep myscriptnam[e]
Explanation
If you run a sleep command in the background:
$ sleep 100 &
[1] 9768
and then look for it with ps -ef:
$ ps -ef | grep sleep
me 9768 3673 0 14:00 pts/6 00:00:00 sleep 100
me 9771 3673 0 14:00 pts/6 00:00:00 grep --color=auto sleep
You get two lines: the process itself and the grep command looking for it. To avoid it and show just the process itselves, we can either:
$ ps -ef | grep -v grep | grep sleep
or use a regex in the code so that the grep process is not matched:
$ ps -ef | grep slee[p]
me 9768 3673 0 14:00 pts/6 00:00:00 sleep 100
because line
me 9771 3673 0 14:00 pts/6 00:00:00 grep --color=auto sleep
does not match in grep slee[p].
See explanation in a related topic.
I suposse your perl script is named "myscriptname".
When you run this script, you have a new process (perl myscriptname.pl), and it's showed by the ps -ef command. The other one is related to the grep command (it has the text you are looking for)
#fedorqui's answer is right on -- the grep is matching its own invocation in the process table, and perhaps that of its parent shell, too, though timing issues mean this does not always happen from the CLI.
However, another approach, avoiding grep in favor of perl, would be:
my $count = () = qx(ps -e -o cmd) =~ /myscriptname/mg;
# Now $count tells you the number of times myscriptname appears in the process table
See this answer for why the empty parens are used above. Note, too, that you don't need the full ps output (-f), you just want to match on the command name (-o cmd).
Take a look at the pgrep and the pkill commands. These are standard Linux commands are are way easier to use than trying to do a ps and then a grep.
Also, if you do use ps, take a look at the -o options. These let you display the columns you want, and give you a way to strip out the heading.

Resources