0

I need a full path/command thats been execued to start a process thats exposed on the network - listens on tcp/udp . I did manage to get all of that using below "one liner":

netstat -nlp46|tail -n +3 |   while IFS=" " read -r -a line; 
do nb=${#line[@]}; 
PID=$(echo ${line[$((nb - 1))]} | awk -F'/' '{print $1}'); 
CMD=$(ps -ef|awk '$2 == '"$PID" |awk -F" " '{out=$8; for(i=9;i<=NF;i++){out=out""$i}; print out}');
echo $PID^$CMD; 
done

but when process contains some special characters in command line, eg thin server, script has some issues with following error

awk: line 1: missing ) near end of line

when I did run part of script against that process I had no problems

root@ftp-host02:~# PID=15000; COMMAND=$(ps -ef|awk '$2 == '"$PID" |awk '{out=$8; for(i=9;i<=NF;i++){out=out" "$i}; print out}'); 
echo $COMMAND

thin server (0.0.0.0:3000)

What I'm doing wrong here?

Thanks

1
  • Not sure exactly what is wrong with the quoting there but once you've got a list of clean pids then ps -ww -o args= -p $PID is probably an easier way to get the command line (or look at /proc/$PID/cmdline) – Paul Haldane Apr 21 '15 at 20:42
2

The error is here: awk '$2 == '"$PID"

  • if $PID is not strictly numeric, then you're doing an equality check against an unquoted string, so really, who knows how awk will interpret it?

    $ PID="3000)"
    $ echo hello | mawk '$2 == '"$PID"
    mawk: line 1: extra ')'
    

Passing the shell variable to awk as an awk variable (with the -v option) clears that up.

Cleaning up your code in other ways, we have:

netstat -nlp46 | 
tail -n +3 | 
while IFS=" " read -r -a fields; do 
    nb=${#fields[@]}
    PID=${fields[nb-1]%%/*}
    CMD=$( ps -ef | awk -v pid="$PID" '$2 == pid {out=$8; for(i=9;i<=NF;i++){out=out $i}; print out}' );
    echo "$PID^$CMD"; 
done

Notes:

  • proper indentation goes a long way towards readable code
  • the index of a numerically indexed array is already evaluated in arithmetic context so ${ary[n-1]} will work
  • You can remove a slash and all subsequent characters with shell parameter expansion, so you don't need awk to get the PID
  • you don't need to pipe awk into awk: consolidate
  • pass a shell variable into awk with the -v option
0

Could you try that:

for i in $(netstat -atnp | awk '{ print $7 }' | grep ^[0-9] | awk -F\/ '{ print $1 }'); do echo "PID: $i " $(ps faxuwwww | grep $i); done

1
  • 1
    A code snippet is not enough, it is not a real answer. – peterh Apr 21 '15 at 22:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.