views:

51

answers:

2

I need to scan the output of iostat -En on a Solaris machine such that when a disk with errors is found, two lines about that disk are sent to the final output. This works fine so far using

iostat -En | grep 'Errors: [1-9]' -A 1

but when I try to not include CD/DVD devices, I hit a wall. The contaxt flags (-A|B|C) don't seem to work with -v so I can't use this:

-bash-4.0$ iostat -En | grep -B 1 -vi "CD/DVD" | grep 'Errors: [1-9]' -A 1
c0t3d0           Soft Errors: 2 Hard Errors: 0 Transport Errors: 0
Vendor: TSSTcorp Product: CD/DVDW TS-L632D Revision: SR02 Serial No:

I don't think there should be any output here because the line containing "CD/DVD" and the line before it should be removed. It would be simple enough to write this as a script in any language but it has to be a single command that can be run on hosts without additional scripts installed so I suppose perl -e can be used. I don't know any perl so I haven't tried this approach.

Some example iostat -En output:

-bash-4.0$ iostat -En
c0t0d0           Soft Errors: 0 Hard Errors: 0 Transport Errors: 0
Vendor: SEAGATE  Product: ST973402SSUN72G  Revision: 0603 Serial No: *removed*
Size: 73.40GB <73400057856 bytes>
Media Error: 0 Device Not Ready: 0 No Device: 0 Recoverable: 0
Illegal Request: 0 Predictive Failure Analysis: 0
c0t3d0           Soft Errors: 2 Hard Errors: 0 Transport Errors: 0
Vendor: TSSTcorp Product: CD/DVDW TS-L632D Revision: SR02 Serial No:
Size: 0.00GB <0 bytes>
Media Error: 0 Device Not Ready: 0 No Device: 0 Recoverable: 0
Illegal Request: 2 Predictive Failure Analysis: 0
c0t1d0           Soft Errors: 0 Hard Errors: 0 Transport Errors: 0
Vendor: SEAGATE  Product: ST973402SSUN72G  Revision: 0603 Serial No: *removed*
Size: 73.40GB <73400057856 bytes>
Media Error: 0 Device Not Ready: 0 No Device: 0 Recoverable: 0
Illegal Request: 0 Predictive Failure Analysis: 0

In this case, I should not have any output because the only device with errors is an optical drive and I don't care about those.

c0t1d0           Soft Errors: 0 Hard Errors: 1 Transport Errors: 0
Vendor: SEAGATE  Product: ST973402SSUN72G  Revision: 0603 Serial No: *removed*

This is the output I am looking for. Any ideas?

+1  A: 

try nawk

iostat -En | nawk '/Errors: [1-9]/{ getline line; if (line!~/CD|DVD/) print line}
ghostdog74
Your solution worked with one small problem; it did not include the first line (c0t0d0 Soft Errors...) which was a small fix -- I just changed `print line}` to `{print; print line}}`
puddingfox
+1  A: 

grep -v pattern prints all lines that don't match a pattern, but grep -B 1 -v pattern also prints out all lines before lines that don't match a pattern, including lines that do match the pattern.

For example, if file contains:

ABCD
DEFG
GHIJ

Then grep -v D file gives you:

GHIJ

but grep -B1 -v D file gives you:

DEFG
GHIJ

The kind of processing you want is too complex for grep.

mobrule
ok thanks. i decided to use awk like ghostdog74 suggested
puddingfox