How to make a command with grep captured fields? - linux

I'm trying to capture a process that runs and make an strace of it in one line:
I managed to capture only the one that i want with this command
ps -ef | grep "[0-9].*[0-9] /usr/bin/python3 /home/pi/readcard.py"
outputs this:
root 676 668 99 11:00 ? 00:34:21 /usr/bin/python3 /home/pi/readcard.py
Now I'm trying to capture the process pid with this regex and use it to make another command:
ps -ef | grep "([0-9]+).*[0-9] /usr/bin/python3 /home/pi/readcard.py"
How I could make to run something like this?
sudo strace -f -p{captured_field} -s9999 -e write

Use awk for only showing the second column:
ps -ef | grep "([0-9]+).*[0-9] /usr/bin/python3 /home/pi/readcard.py" | awk '{print $2}'
This, you can use it as an input for another command, by embedding it into $(...), as follows:
sudo strace -f -p{$(ps -ef | grep "([0-9]+).*[0-9] /usr/bin/python3 /home/pi/readcard.py" | awk '{print $2}')} -s9999 -e write
Good luck

Related

.bashrc saves previous process id and does not update in alias commands

I have made an alias in .bashrc to kill my python service.py & process
alias servicestop="kill $(ps -ef | grep -w service.py | grep -v grep | awk '{print $2}')"
Whenever I run first time servicestop command it will kill the process.
but again whenever I start process python service.py &, and execute command servicestop it gives an error.
After research, I found following things.
when I run first time python service.py & process. its process id was 512.
and, command servicestop kill that process(512).
Now when I run Second time process python service.py &. its process id was 546.(definitely it will be different).
When I run command servicestop. it will give following error:
-bash: kill: (512) - No such process
That means $(ps -ef | grep -w service.py | grep -v grep | awk '{print $2}') will return the previous pid, which is already killed.
Now please suggest the solution if any possible.
so whenever I want to run servicestop command, I have to run source .bashrc command first, then run servicestop command to make it work.
Please remove the servicestop alias from your .bashrc and add :
servicestop(){
kill $(ps -ef | grep -w service.py | grep -v grep | awk '{print $2}');
}
In a way, functions in .bashrc are "aliases 2.0" : simply better
Better : same function; but with the name of script to kill as parameter :
servicestop(){
kill $(ps -ef | grep -w $1 | grep -v servicestop | awk '{print $2}');
}
Use it like that :
servicestop service.py
servicestop otherSuperService.py

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

Linux Script to selectively kill processes

I'm looking at a way to automate the following:
Run ps -ef to list all processes.
Filter out those rows containing java in the CMD column.
Filter out those rows containing root in the UID column.
For each of the filtered rows, get the PID column and run pargs <PID>.
If the output of pargs <PID> contains a particular string XYZ, the issue a kill -9 <PID> command.
To filter out rows based on specific column values, is there a better way than grep? I can use
ps -ef | awk '{print $1}' | grep <UID>
but then I lose info from all other columns. The closest thing I have right now is:
ps -ef | grep java | grep root | grep -v grep | xargs pargs | ?????
EDIT
I was able to solve the problem by using a using the following script:
ps -ef | awk '/[j]ava/ && /root/ {print $2}' | while read PID; do
pargs "$PID" | grep "Args" > /dev/null && kill -9 $PID && echo "$PID : Java process killed!"
done
both anubhava's and kojiro's answers helped me reach there. But since I can only accept one answer, I tagged kojiro's answer as the correct one since it helped me a bit more.
Consider pgrep:
pgrep -U 0 java | while read pid; do
pargs "$pid" | grep -qF XYZ && kill "$pid"
done
pgrep and pkill are available on many Linux systems and as part of the "proctools" packages for *BSDs and OS X.
You can reduce all grep by using awk:
ps -ef | awk '/[j]ava/ && /root/ {print $1}' | xargs pargs
Searching for pattern /[j]ava/ will skip this awk process from output of ps.
You can also use pkill if it is available on your system.

How do I get "awk" to work correctly within a "su -c" command?

I'm running a script at the end of a Jenkins build to restart Tomcat. Tomcat's shutdown.sh script is widely known not to work all in many instances and so my script is supposed to capture the PID of the Tomcat process and then attempt to manually shut it down. Here is the command I'm using to capture the PID:
ps -ef | grep Bootstrap | grep -v grep | awk '{print $2}' > tomcat.pid
The output when manually runs retrieves the PID perfectly. During the Jenkins build I have to switch users to run the command. I'm using "su user -c 'commands'" like this:
su user -c "ps -ef | grep Bootstrap | grep -v grep | awk '{print $2}' > tomcat.pid"
Whenever I do this however, the "awk" portion doesn't seem to be working. Instead of just retrieving the PID, it's capturing the entire process information. Why is this? How can I fix the command?
The issue is that $2 is being processed by the original shell before being sent to the new user. Since the value of $2 in the shell is blank, the awk command at the target shell essentially becomes awk {print }. To fix it, you just escape the $2:
su user -c "pushd $TOMCAT_HOME;ps -ef | grep Bootstrap | grep -v grep | awk '{print \$2}' > $TOMCAT_HOME/bin/tomcat.pid"
Note that you want the $TOMCAT_HOME to be processed by the original shell so that it's value is set properly.
You don't need the pushd command as you can replace the awk command with:
cut -d\ -f2
Note: two 2 spaces between -d\ and -f2

Getting pids from ps -ef |grep keyword

I want to use ps -ef | grep "keyword" to determine the pid of a daemon process (there is a unique string in output of ps -ef in it).
I can kill the process with pkill keyword is there any command that returns the pid instead of killing it? (pidof or pgrep doesnt work)
You can use pgrep as long as you include the -f options. That makes pgrep match keywords in the whole command (including arguments) instead of just the process name.
pgrep -f keyword
From the man page:
-f The pattern is normally only matched against the process name. When -f is set, the full command line is used.
If you really want to avoid pgrep, try:
ps -ef | awk '/[k]eyword/{print $2}'
Note the [] around the first letter of the keyword. That's a useful trick to avoid matching the awk command itself.
Try
ps -ef | grep "KEYWORD" | awk '{print $2}'
That command should give you the PID of the processes with KEYWORD in them. In this instance, awk is returning what is in the 2nd column from the output.
ps -ef | grep KEYWORD | grep -v grep | awk '{print $2}'
This is available on linux: pidof keyword
I use
ps -C "keyword" -o pid=
This command should give you a PID number.
To kill a process by a specific keyword you could create an alias in ~/.bashrc (linux) or ~/.bash_profile (mac).
alias killps="kill -9 `ps -ef | grep '[k]eyword' | awk '{print $2}'`"

Resources