Bash - pipe multiple grep and print output - linux

I am writing a shell script which will grep a document for certain words and then displaying the found words in colour output.
echo $(egrep -wi --color=always 'error|exception' $logFile)
now I want to combine this grep with another one to exclude a few results
For this I want to pipe above command to a grep command to exclude certain patterns
grep -vi '<status>error</status>'
For some reason this fails when I try to execute the command
echo $(egrep -wi --color=always 'error|exception' $logFile | $(grep -v '<STATUS>ERROR</STATUS>') )
or even if I try
echo $(egrep -wi --color=always 'error|exception' $logFile | grep -v '<STATUS>ERROR</STATUS>')
What am I doing wrong? Why is this failing?

The problem seems append only with egrep, --color=always, and -i.
egrep -wi --color=always 'error|exception' /tmp/log.log | grep -v '<STATUS>ERROR</STATUS>'
doesn't work but
egrep -w --color=always 'error|exception' /tmp/log.log | grep -v '<STATUS>ERROR</STATUS>'
and
egrep -wi --color 'error|exception' /tmp/log.log | grep -v '<STATUS>ERROR</STATUS>'
and
grep -wi --color=always 'error|exception' /tmp/log.log | grep -v '<STATUS>ERROR</STATUS>'
does...
But I don't know why your solution does'nt work...
In shell script:
result=`grep -wi --color=always 'error|exception' /tmp/log.log | grep -v '<STATUS>ERROR</STATUS>'`
echo $result

Related

Unable to use grep for a command and excecute the shell script?

I have created a shell script to execute 5 commands from a file called elist.txt
ps -ef | grep user | grep 'process -s 9000' | cut -c -15 | cut -c 10-
ps -ef | grep user | grep 'process -s 9001' | cut -c -15 | cut -c 10-
ps -ef | grep user | grep 'process -s 9002' | cut -c -15 | cut -c 10-
ps -ef | grep user | grep 'process -s 9003' | cut -c -15 | cut -c 10-
The shell script is as follows
export PATH="/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/user/.local/bin:/home/user/bin"
input="/home/user/script/list.txt"
while IFS= read -r line
do
echo $($line)
done < "$input"
output:
error: garbage option
Usage:
ps [options]
Try 'ps --help <simple|list|output|threads|misc|all>'
or 'ps --help <s|l|o|t|m|a>'
for additional help text.
For more details see ps(1).
You can do this too. People usually do not recommend to use eval at all.
export PATH="/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/user/.local/bin:/home/user/bin"
input="/home/user/script/list.txt"
while IFS= read -r line
do
bash -c "$line"
done < "$input"
Regards!
I would use this script with eval which is a similar solution described in this answer https://stackoverflow.com/a/6002329/6778826
export PATH="/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/user/.local/bin:/home/user/bin"
input="/home/user/script/list.txt"
while read -r line
do
eval "$line"
done <$input

Linux use grep command

I know use ps -ef | grep test| grep -v grep |wc -l can list the num of process test,and now i plan to list the test processes belong to user :forme.is this right as below :
ps -ef | grep test|grep -x forme| grep -v grep |wc -l
For a start, grep test| grep -v grep can be replaced with grep '[t]est'. See here for an explanation.
Secondly, if you want to limit the processes to a single user, that's what the -u option to ps is for:
ps -fu forme | grep '[t]est' | wc -l
And, finally, grep already has a -c option to count lines, so you can ditch the wc part of the pipeline:
ps -fu forme | grep -c '[t]est'

Concatenating xargs with the use of if-else in bash

I've got two test files, namely, ttt.txt and ttt2.txt, the Content of which is shown as below:
#ttt.txt
(132) 123-2131
543-732-3123
238-3102-312
#ttt2.txt
1
2
3
I've already tried the following commands in bash and it works fine:
if grep -oE "(\(\d{3}\)[ ]?\d{3}-\d{4})|(\d{3}-\d{3}-\d{4})" ttt1.txt ; then echo "found"; fi
# with output 'found'
if grep -oE "(\(\d{3}\)[ ]?\d{3}-\d{4})|(\d{3}-\d{3}-\d{4})" ttt2.txt ; then echo "found"; fi
But when I combine the above command with xargs, it complains error '-bash: syntax error near unexpected token `then''. Could anyone give me some explanation? Thanks in advance!
ll | awk '{print $9}' | grep ttt | xargs -I $ if grep --quiet -oE "(\(\d{3}\)[ ]?\d{3}-\d{4})|(\d{3}-\d{3}-\d{4})" $; then echo "found"; fi
$ is a special character in bash (it marks variables) so don't use it as your xargs marker, you'll only get confused.
The real problem here though is that you are passing if grep --quiet -oE "(\(\d{3}\)[ ]?\d{3}-\d{4})|(\d{3}-\d{3}-\d{4})" $ as the argument to xargs, and then the remainder of the line is being treated as a new command, because it breaks at the ;.
You can wrap the whole thing in a sub-invocation of bash, so that xargs sees the whole command:
$ ll | awk '{print $9}' | grep ttt | xargs -I xx bash -c 'if grep --quiet -oE "(\(\d{3}\)[ ]?\d{3}-\d{4})|(\d{3}-\d{3}-\d{4})" xx; then echo "found"; fi'
found
Finally, ll | awk '{print $9}' | grep ttt is a needlessly complicated way of listing the files that you're looking for. You actually you don't need any of the code above, just do this:
$ if grep --quiet -oE "(\(\d{3}\)[ ]?\d{3}-\d{4})|(\d{3}-\d{3}-\d{4})" ttt*; then echo "found"; fi
found
Alternatively, if you want to process each file in turn (which you don't need here, but you might want when this gets more complicated):
for file in ttt*
do
if grep --quiet -oE "(\(\d{3}\)[ ]?\d{3}-\d{4})|(\d{3}-\d{3}-\d{4})" "$file"
then
echo "found"
fi
done

Greping folder names but exluding "#domain.com"

Is it possible to exclude a domain from a grep? What I have tried below doesn't seem to work.
ls -l /var/www/folder | grep -E -o --exclude-dir="#somedomain.com" --color "\b[a-zA-Z0-9.-]+#[a-zA-Z0-9.-]+\.[a-zA-Z0-9.-]+\b">>test.txt
how about this
ls -l /var/www/folder | grep -v "#somedomain.com"
test case:
$ mkdir -p /tmp/test && cd $_
$ touch {a,b,c,d}#domain.com
$ touch {e,f}#somedomain.com
$ ls
domain.com b#domain.com c#domain.com d#domain.com e#somedomain.com f#somedomain.com
$ ls -1 | grep -v "#somedomain.com"
a#domain.com
b#domain.com
c#domain.com
d#domain.com
Here is what the man page says for -v
-v, --invert-match
Invert the sense of matching, to select non-matching lines. (-v is specified by POSIX.)
-l /var/www/folder | grep --invert-match "#somedomain.com" | grep -E -o --color "\b[a-zA-Z0-9.-]+#[a-zA-Z0-9.-]+.[a-zA-Z0-9.-]+\b">>test.txt

Killing a process

I have a for loop to get the list of PID's and kill each PID. I want to display the entire line of PS output and write it to the /tmp/outfile . But from each line of PS output each field(PID,PPID,...) is written along with a new line in the /tmp/outfile. So if PS output has three lines as output i want to log these three lines into /tmp/outfile but it's breaking each field in the line and adding a new line. how can i do it.
for list in `ps -ef | grep "${process_name}" | grep -v "${SCRIPTNAME}" | grep -v grep`
do
echo "$list" >> $CUSTOM_TMP/test5566
PID=`echo $list | awk '{print $2}'`
kill -TERM "$list"
done
Your for loop does not iterate the lines but each individual field.
Also your kill command was slightly wrong.
Just change your code to something like:
ps -ef | grep "${process_name}" | grep -v "${SCRIPTNAME}" | grep -v grep | while read list
do
echo "$list" >> $CUSTOM_TMP/test5566
PID=`echo $list | awk '{print $2}'`
kill -TERM "$PID"
done
Isn't it easier to use the killall command for what you are trying to do?
No need for a loop at all. And this uses tee to write your temp file.
list=$(ps -ef | grep "${process_name}" | grep -v "${SCRIPTNAME}" | grep -v grep | tee $CUSTOM_TMP/test5566 | awk '{printf "%s ", $2')
kill -TERM $list
You want to run ps before looping:
ps -ef | grep $"{process_name}" | grep -v "${SCRIPTNAME}" | grep -v grep > $CUSTOM_TMP/test5566 2>/dev/null
for PID in `cat $CUSTOM_TMP/test5566 | awk '{print $2}'`; do
kill -TERM $PID
done
rm -f $CUSTOM_TMP/test5566
I would also insert some sanity, possibly using wc to make sure the file actually got some data from ps.
Just move the awk part to the top line, otherwise your code is fine.
for list in `ps -ef | grep "${process_name}" | grep -v "${SCRIPTNAME}" | grep -v grep | awk '{print $2}`
do
echo "$list" >> $CUSTOM_TMP/test5566
PID=`echo $list`
kill -TERM "$list"
done
For a one liner - if your system has pgrep --
pgrep -d ' ' ${process_name} > kill.log && kill -TERM $(< kill.log)

Resources