One-liner to retrieve path from netstat port - bash

I'm looking to create a one liner that, given a port number (2550) uses the returned value from netstat would allow me to then run the resulting output against ps -ef to return the path of the process in question. I have:
ps -ef | grep $(netstat -tonp | grep 2550 | awk '{split($7,a,"/"); print a[1]}')
and whilst I know
netstat -tonp | grep 2550 | awk '{split($7,a,"/"); print a[1]}'
returns the expected resulted, the subsequent grep tells me that there is no such file or directory (but, if I do the ps -ef | grep **) it works just fine... I'm obviously missing something... well, obvious, but I can't see what?

try something like (it takes the first PID/port corresponding, not all):
Port=2550;ps -f --pid $( netstat -tonp | awk -F '[ \t/]+' -v Port=$Port '$0 ~ "([0-9]+[.:]){4}" Port { PID= $7;exit}; END { print PID+0 }' ) | sed 's/^\([^ \t]*[ \t]*\)\{7\}//'
the last sed is assuming a ps reply like this (space are important):
usertest 4408 4397 0 09:43 pts/6 00:00:00 ssh -p 22 -X -l usertest 198.198.131.136
for every PID and with no ending sed:
Port=2550; ps -ef | awk -v PIDs="$( netstat -tonp | awk -F '[ \t/]+' -v Port=${Port} '$0 ~ (":" Port) { print $7}' )" 'BEGIN{ split( PIDs, aTemp, /\n/); for( PID in aTemp) aPID[ aTemp[PID] ] }; $2 in aPID { sub( /^([^ \t]*[ \t]*){7}/, ""); print}'

This will give you the pids:
<sudo> netstat -tulpen | awk '$4 ~ /:2550$/{sub("/.*","",$NF);print $NF}'
You can use xargs to pass the pid to ps:
netstat -tulpen | awk '$4 ~ /:2550$/{sub("/.*","",$NF);print $NF}' | xargs -P 1 ps -o pid,cmd -p

Related

How to grep first match and second match(ignore first match) with awk or sed or grep?

> root# ps -ef | grep [j]ava | awk '{print $2,$9}'
> 45134 -Dapex=APEC
> 45135 -Dapex=JAAA
> 45136 -Dapex=APEC
I need to put the first APEC of first as First PID, third line of APEC and Second PID and last one as Third PID.
I've tried awk but no expected result.
> First_PID =ps -ef | grep [j]ava | awk '{print $2,$9}'|awk '{if ($0 == "[^0-9]" || $1 == "APEC:") {print $0; exit;}}'
Expected result should look like this.
> First_PID=45134
> Second_PID=45136
> Third_PID=45135
With your shown samples and attempts please try following awk code. Written and tested in GNU awk.
ps -ef | grep [j]ava |
awk '
{
val=$2 OFS $9
match(val,/([0-9]+) -Dapex=APEC ([0-9]+) -Dapex=JAAA\s([0-9]+)/,arr)
print "First_PID="arr[1],"Second_PID=",arr[3],"Third_PID=",arr[2]
}
'
How about this:
$ input=("1 APEC" "2 JAAA" "3 APEC")
$ printf '%s\n' "${input[#]}" | grep APEC | sed -n '2p'
3 APEC
Explanation:
input=(...) - input data in an array, for testing
printf '%s\n' "${input[#]}" - print input array, one element per line
grep APEC - keep lines containing APEC only
sed -n - run sed without automatic print
sed -n '2p' - print only the second line
If you just want the APECs first...
ps -ef |
awk '/java[ ].* -Dapex=APEC/{print $2" "$9; next; }
/java[ ]/{non[NR]=$2" "$9}
END{ for (rec in non) print non[rec] }'
If possible, use an array instead of those ordinally named vars.
mapfile -t pids < <( ps -ef | awk '/java[ ].* -Dapex=APEC/{print $2; next; }
/java[ ]/{non[NR]=$2} END{ for (rec in non) print non[rec] }' )
After read from everyone idea,I end up with the very simple solution.
FIRST_PID=$(ps -ef | grep APEC | grep -v grep | awk '{print $2}'| sed -n '1p')
SECOND_PID=$(ps -ef | grep APEC | grep -v grep | awk '{print $2}'| sed -n '2p')
JAWS_PID=$(ps -ef | grep JAAA | grep -v grep | awk '{print $2}')

How to kill process by awk?

In my makefile I have a command
kill `ps aux | awk '/process_name/' | awk '$11 ~ /special_mask/ {print $2}'`
It works through the terminal but when I try to call it through the command make my-command it returns
kill `ps aux | awk '/process_name/' | awk '1 ~ /special_mask/ {print }'`
and it can't execute kill without process id.
How could I fix it?
Makefile needs double $$ for shell commands.
You can use:
ps aux | awk '/[p]rocess_name/ && $$11 ~ /special_mask/{print $$2}' | xargs -r kill

How to reference multiple string values in array in Shell script

I am trying to store multiple string in for loop but it giving me unwanted answer.
My code is :
#!/bin/bash
declare -a arr=("ps -ef | grep icsmpgum | grep $USER | grep -v grep | awk '{print $9,$8}' | awk '{print $1}'")
for i in "${arr[#]}"
do
echo "$i"
done
The output of
ps -ef | grep icsmpgum | grep $USER | grep -v grep | awk '{print $9,$8}' | awk '{print $1}'
is :
icsmpgum
ABC
DEF
I want to refer to these 3 string values in for loop but after applying for loop as mention above it giving me output as :
Output :
ps -ef | grep icsmpgum | grep tsaprm1 | grep -v grep | awk '{print ,}' | awk '{print }'
How should I store these string values in variables ?
You need to use a command substitution, rather than quoting the command:
arr=( $(ps -ef | grep icsmpgum | grep $USER | grep -v grep | awk '{print $9,$8}' | awk '{print $1}') )
I suspect that this will work but there's a lot of further tidying up to be done; all the filtering that you want to do is possible in one call to awk:
arr=( $(ps -ef | awk -v user="$USER" '!/awk/ && /icsmpgum/ && $0 ~ user { print $9 }') )
As mentioned in the comments, there are potential risks to building an array like this (e.g. glob characters such as * would be expanded and you would end up with extra values in the array). A safer option would be to use a process substitution:
read -ra arr < <(ps -ef | awk -v user="$USER" '!/awk/ && /icsmpgum/ && $0 ~ user { print $9 }')

How to escape grep and awk within pipe in an alias?

I want to create an alias for an long command. But I'm not able to escape it correct, I guess it's a problem with the pipes.
My original command
ps aux | grep gimp | awk '{ print $2 '\011' $11 }' | grep -v 'grep'
My attempt for an alias
alias psa="ps aux | grep $1 | awk '{ print \$2 \"\011\" \$11 }' | grep -v 'grep'"
But I get an error that grep can not open file foo (when I do psa foo)
When I remove the last part | grep -v 'grep' then awkthrows the same error.
I prefer an alias before an shell script.
You need to use a function if you want to to insert arguments:
psa() {
ps aux | grep "$1" | awk '{print $2 "\t" $11 }' | grep -v grep
}
You can avoid all the escaping by using a function for this:
myps() {
ps aux | grep gimp | awk '{ print $2 "\011" $11 }' | grep -v 'grep'
}

shell command to find a process id and attach to it?

I want to attach to a running process using 'ddd', what I manually do is:
# ps -ax | grep PROCESS_NAME
Then I get a list and the pid, then I type:
# ddd PROCESS_NAME THE_PID
Is there is a way to type just one command directly?
Remark: When I type ps -ax | grep PROCESS_NAME, grep will match both the process and grep command line itself.
There is an easy way to get rid of the grep process:
ps -ax | grep PROCESS_NAME | grep -v ' grep '
(as long as the process you're trying to find doesn't include the string " grep ").
So something like this should work in a script (again, assuming there's only one copy running):
pid=$(ps -ax | grep $1 | grep -v ' grep ' | awk '{print $1}')
ddd $1 ${pid}
If you call your script dddproc, you can call it with:
dddproc myprogramname
Although I'd add some sanity checks such as detecting if there's zero or more than one process returned from ps and ensuring the user supplies an argument.
As separate commands:
% PID=`ps -ax | grep ${PROCESS_NAME} | grep -v grep | cut -d ' ' -f 1-2`
% ddd ${PROCESS_NAME} ${PID}
In one line:
% PID=`ps -ax | grep ${PROCESS_NAME} | grep -v grep | cut -d ' ' -f 1-2` && ddd ${PROCESS_NAME} ${PID}
ddd <process_name> `pgrep <process_name>`
you can use pggrep to find the process
You can use awk to both filter and get the column you want. The "exit" limits the ps results to the first hit.
function ddd_grep() {
ddd $(ps -ax | awk -v p="$1" '$4 == p { print $1; exit 0; }');
}
ddd_grep PROCESS_NAME
You may have to adjust the columns for your ps output. Also you can change the == to ~ for regex matching.
Do this way -
ddd PROCESS_NAME \`ps -ax | grep PROCESS_NAME | grep -v grep | awk '{print $1}'\`

Resources