LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Server
User Name
Password
Linux - Server This forum is for the discussion of Linux Software used in a server related context.

Notices


Reply
  Search this Thread
Old 04-27-2016, 01:25 AM   #1
Tridibesh
Member
 
Registered: Jan 2010
Location: India
Distribution: Opensuse 13.2 x86_64
Posts: 33

Rep: Reputation: 1
grep upto specific keyword from a file under Redhat 6


I am trying to write a script for checking the SAN path status in Linux nodes under the multipath. For checking the multipath status, I am sorting out the mpath names and looping the multipath -ll output with the mpath name to process the output. By this I'm able to check the status of all the LUNs. But problem is if the server has many LUNs, it is taking long time to execute the script because of looping the multipath -ll command multiple times. So I was thinking if I can redirect the multipath -ll output to a file and then process the mpath output instead of looping the multipath -ll output it will speed up the execution time. I can grep out information for the specific mpath device from that file with the -A option in grep command if the no of following lines are same for all the LUNs. But here problem is some mpath may have 2 underline devices or 4 or 8 devices. So following lines count will be different for each mpath device. So only if I can grep until the next occurrence of mpath keyword, I can accomplish my purpose. So if anyone can help me with how to do (may be via grep or sed or awk or any other method) so I will be very grateful to him.

example output of multipath -ll command output:-

mpathj (360a980003246694b552b425830593539) dm-19 NETAPP,LUN
size=12M features='3 queue_if_no_path pg_init_retries 50' hwhandler='1 alua' wp=rw
|-+- policy='round-robin 0' prio=50 status=active
| |- 1:0:3:0 sdu 65:64 active ready running
| `- 0:0:2:0 sdy 65:128 active ready running
`-+- policy='round-robin 0' prio=10 status=enabled
|- 1:0:1:0 sds 65:32 active ready running
`- 0:0:1:0 sdw 65:96 active ready running
mpathi (360002ac0000000000000033300012147) dm-3 3PARdata,VV
size=2.0G features='1 queue_if_no_path' hwhandler='0' wp=rw
`-+- policy='round-robin 0' prio=1 status=active
|- 0:0:0:10 sdi 8:128 active ready running
`- 1:0:0:10 sdr 65:16 active ready running


So from the above output of multipath -ll command how can I grep or print only the info about a specific mpath device e.g mpathi (you can see the no of lines is different for each mpath device).
 
Old 04-27-2016, 03:45 AM   #2
Turbocapitalist
LQ Guru
 
Registered: Apr 2005
Distribution: Linux Mint, Devuan, OpenBSD
Posts: 7,258
Blog Entries: 3

Rep: Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713
grep won't fit there as you point out because of the variable number of lines.

With awk it is easy and can be done in three steps.

Code:
awk '/^mpathj/ && !flag  { print; flag++; next }; /^mpath/ && flag { exit }; flag { print } ;
That represents three if-then conditions in serial, separated by semicolons. 'print' is short for 'print $0' There may be a sounder or more elegant way to do it.

That will work for either the pattern "mpathj" or "mpathi" or similar. You'll have to adapt it yourself to fit it into your actual workflow.
 
Old 04-27-2016, 05:16 AM   #3
Tridibesh
Member
 
Registered: Jan 2010
Location: India
Distribution: Opensuse 13.2 x86_64
Posts: 33

Original Poster
Rep: Reputation: 1
Thanks for the response. I am not that much good with awk command usage. Can you please explain the syntax you provided?
 
Old 04-27-2016, 05:27 AM   #4
Turbocapitalist
LQ Guru
 
Registered: Apr 2005
Distribution: Linux Mint, Devuan, OpenBSD
Posts: 7,258
Blog Entries: 3

Rep: Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713
flag is a variable. undefined it starts out as equivalent to 0. Using ++ increments it, setting it to 1.

/^mpathj/ looks for "mpathj" at the start of the input line. Actually it's the caret ^ that indicates the beginning of the line. Without it, the pattern would match "mpathj" anywhere on the line.

awk statements are separated by semicolons. By default they are if-then clauses, with the action being contained in the braces. So in pseudo-code what you are seeing above is this:

Code:
while ( $0 = readnewline ) {
        if ( $0 =~ /^mpathj/ ) then
                { 
                        print $0;   # print the current line
                        $flag++;    # increment the flag
                        next;       # skip the rest of the stuff below and start again and read the next line
                }
        if ( $0 =~ /^mpath/ AND $flag != 0 ) then
                {
                        exit;  # quit the awk program now
                }
        if ( $flag != 0 ) then
                {
                        print $0;   # print the current line
                }
}
"print" by itself is short for "print $0", which means the whole line

Try taking a look at the manual page for awk now, some parts should look familiar.
 
Old 04-27-2016, 05:38 AM   #5
Tridibesh
Member
 
Registered: Jan 2010
Location: India
Distribution: Opensuse 13.2 x86_64
Posts: 33

Original Poster
Rep: Reputation: 1
Thanks Turbocapitalist. I will have a look in the man page and will try to understand the code. If I have any doubt I will come back and will try to clear that.
 
Old 04-27-2016, 06:32 AM   #6
HMW
Member
 
Registered: Aug 2013
Location: Sweden
Distribution: Debian, Arch, Red Hat, CentOS
Posts: 773
Blog Entries: 3

Rep: Reputation: 369Reputation: 369Reputation: 369Reputation: 369
You can also do this with sed:
Code:
sed -n '/mpathj/,/mpath[a-z]/p' mpath.txt | sed '$ d'
A bit cleaner imho, but then again I'm a novice (at best!) at awk.

Given this infile:
Code:
mpathj (360a980003246694b552b425830593539) dm-19 NETAPP,LUN
size=12M features='3 queue_if_no_path pg_init_retries 50' hwhandler='1 alua' wp=rw
|-+- policy='round-robin 0' prio=50 status=active
| |- 1:0:3:0 sdu 65:64 active ready running
| `- 0:0:2:0 sdy 65:128 active ready running
`-+- policy='round-robin 0' prio=10 status=enabled
|- 1:0:1:0 sds 65:32 active ready running
`- 0:0:1:0 sdw 65:96 active ready running
mpathi (360002ac0000000000000033300012147) dm-3 3PARdata,VV
size=2.0G features='1 queue_if_no_path' hwhandler='0' wp=rw
`-+- policy='round-robin 0' prio=1 status=active
|- 0:0:0:10 sdi 8:128 active ready running
`- 1:0:0:10 sdr 65:16 active ready running
I get this result:
Code:
sed -n '/mpathj/,/mpath[a-z]/p' mpath.txt | sed '$ d'
mpathj (360a980003246694b552b425830593539) dm-19 NETAPP,LUN
size=12M features='3 queue_if_no_path pg_init_retries 50' hwhandler='1 alua' wp=rw
|-+- policy='round-robin 0' prio=50 status=active
| |- 1:0:3:0 sdu 65:64 active ready running
| `- 0:0:2:0 sdy 65:128 active ready running
`-+- policy='round-robin 0' prio=10 status=enabled
|- 1:0:1:0 sds 65:32 active ready running
`- 0:0:1:0 sdw 65:96 active ready running
In other words, only from 'mpathj' up until the line before 'mpathi'.

Best regards,
HMW
 
Old 04-27-2016, 07:24 AM   #7
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 21,103

Rep: Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117
Perhaps a slight mod to handle the situation where multiple of the mpathj stanza exist
Code:
sed -n '/mpathj/,/mpath[a-z]/{/mpath[^j]/d ; p}' mpath.txt
 
1 members found this post helpful.
Old 04-28-2016, 01:21 AM   #8
Tridibesh
Member
 
Registered: Jan 2010
Location: India
Distribution: Opensuse 13.2 x86_64
Posts: 33

Original Poster
Rep: Reputation: 1
Thanks syg00 & HMW for your kind response.
I was trying and the code worked. Now what I am trying, is creating for loop with the mpathX putting them into a variable and trying to use the variable in the code provided by you. But some how the sed command is not reading the variable properly and showing nothing as output. So can you please help how to use the mpath as variable in the sed command provided by you?

Code:
00:14:40 # sed -n '/mpathi/,/mpath[a-z]/{/mpath[^i]/d ; p}'  /tmp/mpath.txt
mpathi (360002ac0000000000000033300012147) dm-3 3PARdata,VV
size=2.0G features='1 queue_if_no_path' hwhandler='0' wp=rw
`-+- policy='round-robin 0' prio=1 status=active
  |- 0:0:0:10 sdi 8:128  active ready running
  `- 1:0:0:10 sdr 65:16  active ready running

root []@test1:(SL=1):(RC=0):/root
00:14:58 # cat /tmp/mpath.txt | grep ^mpath | awk '{print $1}'
mpathe
mpathd
mpathc
mpathb
mpatha
mpathk
mpathj
mpathi
mpathh
mpathg
mpathf

root []@test1:(SL=1):(RC=0):/root
00:16:13 # cat /tmp/mpath.txt | grep ^mpath | awk '{print $1}'>/tmp/mpath_list

root []@test1:(SL=1):(RC=0):/root
00:16:23 # for i in `cat /tmp/mpath_list`
> do
> sed -n '/"$i"/,/mpath[a-z]/{/"$i"/d ; p}' /tmp/mpath.txt
> done

root []@test1:(SL=1):(RC=0):/root
 
Old 04-28-2016, 01:55 AM   #9
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 21,103

Rep: Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117Reputation: 4117
Use double-quotes around the sed code rather than single. You don't need the internal double-quotes you added.
I don't think that will do what you want, but I'll leave you to debug your changes.
 
Old 04-28-2016, 02:23 AM   #10
Turbocapitalist
LQ Guru
 
Registered: Apr 2005
Distribution: Linux Mint, Devuan, OpenBSD
Posts: 7,258
Blog Entries: 3

Rep: Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713Reputation: 3713
Also, a simpler way to do something like this,

Code:
cat /tmp/mpath.txt | grep ^mpath | awk '{print $1}'>/tmp/mpath_list
would be like this:

Code:
awk '/^mpath/ { print $1 }' /tmp/mpath.txt > /tmp/mpath.list
That eliminates cat, which is often not needed, as well as a redundant grep. The awk language includes some pattern matching like grep.

About about the quotes, the double and single quotes work differently. The single quotes preserve the literal value of what's between them. The double quotes allow some processing. Compare:

Code:
echo "Home is $HOME for $USER."
echo "Today is $(date +%F)."

echo 'Home is $HOME for $USER.'
echo 'Today is $(date +%F).'
 
  


Reply

Tags
grep, linux, multipath, redhat, scripting


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Thorough search for a text file with a specific keyword inside educateme Linux - General 6 10-11-2013 09:34 AM
Get data from multi lined text file using awk, sed or perl - grep & cut not upto par cam34 Programming 4 07-02-2010 03:10 AM
[SOLVED] how to make grep to search a pattern in only specific file type mq15 Linux - Newbie 7 03-07-2010 09:41 AM
Grep file using last specific file patterns jeesun Programming 19 11-24-2009 09:51 PM
how to grep a "keyword" beside another keyword? xiawinter Linux - Software 7 12-29-2007 12:50 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Server

All times are GMT -5. The time now is 10:40 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration