Why can't pgrep find this process? - linux

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.

Related

Pass bash command a comment to see from pkill

I have an aribtrary bash command being run that I want to attach some identifying comment to so that I may pkill it if necessary.
For example:
sleep 1000 #uniqueHash93581
pkill -f '#uniqueHash93581'
... but the #uniqueHash93581 does not get interpreted, so pkill won't find the process.
Any way to pass this unique hash so that I may pkill the process?
Bash removes comments before running commands.
A workaround with Linux and GNU grep:
Prefix your command with a variable with a unique value
ID=uniqueHash93581 sleep 1000
Later search this variable to get the PID and kill the process
grep -sa ID=uniqueHash93581 /proc/*/environ | cut -d '/' -f 3 | xargs kill
exec the command in a subshell, and use the -a option to give it a recognizable name. For example:
$ (exec -a foobar sleep 1000) &
$ ps | grep foobar
893 ttys000 0:00.00 foobar 10
Or, just run the job in the background and save its PID.
$ sleep 1000 & pid=$!
$ kill "$pid"

Get a process ID

I read a lot of questions about this argument, but I can't solve my issue.
I need to get a specific process ID and I wrote the following test.sh script:
#!/bin/sh
PID=$(ps -ef | grep abc | grep -v grep | awk '{print $2}')
echo $PID
Running this script I get two different PIDs if the abc process is not running and three different PIDs if the abc process is running.
If I run the
ps -ef | grep abc | grep -v grep | awk '{print $2}'
command from shell I get the right result.
Modifing the test.sh script removing the last awk I noticed that the script prints the following output:
user1 22153 129551 0 15:56 pts/3 00:00:00 /bin/sh ./test.sh
user1 22155 22153 0 15:56 pts/3 00:00:00 /bin/sh ./test.sh
How is it possible and how can I ignore them?
If you know exactly what is the process called, use pidof, otherwise, you can just use pgrep, it saves your grep|grep|awk....
Note that, when you ps|grep regex or pgrep regex there could be multiple entries in your result.
Do not use these tools, use the right tool meant for this, command pidof with the POSIX compatible -s flag which according to the man page says,
-s Single shot - this instructs the program to only return one
pid.
Using the above,
processID=$(pidof -s "abc")
I am not a big fan of parsing the process table. It could be inaccurate. For the same reason as "why not parse ls" You may want to look at the command pgrep
My suggestion is doing
pgrep -u user1 abc

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

How to find a PID of a process whose name I don't know exactly?

I can get the PID of a specific process name by
pidof$(ps -C netns)
but what if I don't know the name of the process exactly?
I can't type something like
pidof$(ps -C net*)
so is there any wildcard character, or is there another solution?
Use the -A (all processes) option and filter the result through grep:
pidof $(ps -A | grep "net*")
Just use pgrep -l, eg:
$ pgrep -l sh
1821 sshd
2590 ssh-agent
2658 sh
2677 bash
3025 gvfsd-trash
14785 ksh93
17723 ksh93
try the following and see if you can discover the process as such
This will give you all processes for all users, in a full-format listing
ps auxf
where :
axu = To see every process on the system using BSD syntax
f = fullformat
if the list is too long you can filter if you have an idea of the process name
For example the command below will show you the pids for chrome.
ps auxf | grep chrome
you can use grep and pip :
pidof$(ps -c |grep yor_pattern)

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