Get a process ID - linux

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

Related

Grep the PIDs of simulator and kill the same using kubectl

I need help with the command where I am trying to grep the PIDs of ecm simulator and kill the same using kubectl :
kubectl exec eric-service-0 -n cicd --kubeconfig /root/admin.conf -- bash -c "ps -ef | grep ecm | grep node | awk '{print $2}' "
Output of the above command:
root 9857 0 0 07:11 ? 00:00:00 bash -c /tmp/simulator/node-v8.11.3-linux-x64/bin/node /tmp/simulator/ecm_mod.js> /tmp/simulatorEcmResponse.txt
root 9863 9857 0 07:11 ? 00:00:00 /tmp/simulator/node-v8.11.3-linux-x64/bin/node /tmp/simulator/ecm_mod.js
Expected output is:
9857
9863
Then further I need to kill the PIDs:
kubectl exec eric-service-0 -n cicd --kubeconfig /root/admin.conf -- bash -c "ps -ef | grep ecm | grep node | awk '{print $2}' | xargs kill -9"
When I am executing the same within the service pod it's working but it's giving issues when I am doing via kubectl from outside.
Could anyone please let me know what I am doing wrong here?
NOTE: There are 2 PIDs which needs to be killed from the below output:
eric-service-0:/ # ps -ef | grep ecm | grep node
root 9857 0 0 07:11 ? 00:00:00 bash -c /tmp/simulator/node-v8.11.3-linux-x64/bin/node /tmp/simulator/ecm_mod.js> /tmp/simulatorEcmResponse.txt
root 9863 9857 0 07:11 ? 00:00:00 /tmp/simulator/node-v8.11.3-linux-x64/bin/node /tmp/simulator/ecm_mod.js
EDIT:
Output of the command as asked by #Cyrus below:
Posting this this as Community Wiki answer for better visibility. Solution has been provided in comments by #Cyrus.
In Short, OP wanted to Kill/interrupt some process using their PID's. OP wanted to do it from cluster level on specific pod/container which included ecm simulator.
To do it, commands below were used:
exec - execute a command in a container
-- bash - run bash inside container
ps -ef - list all process on the system
grep - serch specific pattern
awk - pattern scanning and processing language.
xargs - build and execute command lines from standard input
kill - send a signal to a process
In MANUAL you can find some information about ps flags:
To see every process on the system using standard syntax:
ps -e
ps -ef
ps -eF
ps -ely
however each flag will still give another output, like below:
-e
PID TTY TIME CMD
-ef
UID PID PPID C STIME TTY TIME CMD
Cyrus advised to use following command:
kubectl exec eric-service-0 -n cicd --kubeconfig /root/admin.conf -- bash -c "pgrep -f 'node.*ecm'"
bash -c - If the -c option is present, then commands are read from the first non-option argument command_string.
Also explain in comment:
pgrep looks through the currently running processes and lists the process IDs which match the selection criteria to stdout. From man pgrep. node.*ecm is a regex.

Problems with accessing job PID in LINUX shellscript

if I run the expression
ps -fu $USER| grep 'mount' | grep -v 'grep' | awk '{print $2}'
in the command line, I get - as expected - the PID of the processes containing "mount" in their description.
I want to achieve the following to kill certain background processes programmatically. The following code in the shell script:
#!/usr/bin/env bash
mountcmd="ps -fu $USER| grep 'mount' | grep -v 'grep' | awk '{print $2}' "
mountpid=$(eval "$mountcmd")
echo "Found existing background job PID: " "$mountpid"
does not provide the PID, but the output of echo is:
Found existing background job PID: wgeithne 6284 1 0 17:09 pts/3 00:00:00 minikube mount /u/wgeithne/bin/grafana/config:/grafana
How do I get the only the PID as output of my script?
The stupid eval trick requires additional escaping of the dollar sign in the Awk script. But really, a massively superior solution is to avoid stupid eval tricks.
Perhaps see also https://mywiki.wooledge.org/BashFAQ/050
If you really need to reinvent pidof, probably get rid of the antipatterns.
mountpids=$(ps -fu "$USER" | awk '/[m]ount/ { print $2 }')

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

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