90% of on the fly scripting, three basic loops

One of the cool things about a robust shell such as ksh is that you can build command on the fly by adding a command one piece at a time and running it to check how you are doing. At the end, you just add an execution command and you are done. This is called REPL style coding and is one of the big advantages of shell versus something like perl, which is often associated with System Administration.

In this example, I want to remove all of the special EMC disks from my system that aren’t in a volume group. I know that is OS specific stuff, but really I am just processing a list. Here is my criteria:

  1. hdisk4 none None (exclude, this is not a power device)
  2. hdiskpower9 00c7286c92245797 oraclevg active (exclude, in use)
  3. hdiskpower12 00c7286c7f7e4c28 None (include, not in use)

So I start with a simple list command:

lspv
hdisk0 00c7286c0997490f rootvg active
hdisk1 00c9738ea12e9e1b rootvg active
hdisk4 none None

hdisk17 none None
hdisk24 none None
hdiskpower3 00c7286c1b6cd3f2 None
hdisk25 none None
hdisk26 none None

hdisk71 none None
hdiskpower11 00c7286c922353ea oraclevg active
hdiskpower15 00c7286c9222cc96 oraclevg active

Now, because I use the vi control set on my shell, I type [ESC-k], but if you were using a different
shell or command structure, you might just hit up arrow. This calls back your old command. In this shell, I then hit [shift-a] to go to end of line and enter edit mode, where I add a pipe and grep:

# lspv | grep power
hdiskpower3 00c7286c1b6cd3f2 None
hdiskpower1 00c7286c6afbe0f7 None
hdiskpower5 00c7286c11a34c03 None
hdiskpower6 none None
hdiskpower7 none None
hdiskpower8 00c7286cb2779a47 satavg active
hdiskpower0 none None
hdiskpower2 none None
hdiskpower4 none None
hdiskpower12 00c7286c7f7e4c28 None
hdiskpower13 00c7286c7f7ee6e1 None
hdiskpower14 00c7286c804ffa93 None
hdiskpower9 00c7286c92245797 oraclevg active
hdiskpower10 00c7286c9223d7f3 oraclevg active
hdiskpower11 00c7286c922353ea oraclevg active
hdiskpower15 00c7286c9222cc96 oraclevg active
hdiskpower18 00c7286cd3c4a22d None

Now, I have a much more manageable list, I repeat this to now only find disks not in a volume group. There is probably a more precise command that piping two greps into each other, but remember this is a throw away script that you will be typing in very fast while visually inspecting your data along the way:

# lspv | grep power | grep None
hdiskpower3 00c7286c1b6cd3f2 None
hdiskpower1 00c7286c6afbe0f7 None
hdiskpower5 00c7286c11a34c03 None
hdiskpower6 none None
hdiskpower7 none None
hdiskpower0 none None
hdiskpower2 none None
hdiskpower4 none None
hdiskpower12 00c7286c7f7e4c28 None
hdiskpower13 00c7286c7f7ee6e1 None
hdiskpower14 00c7286c804ffa93 None
hdiskpower18 00c7286cd3c4a22d None

Now for the loop, you can go two ways with this, a while loop or ‘xargs’. I never can remember all of
the flags for xargs, so I usually only use it if I can without flags, but what I need is to ignore fields two and three at this point (even though we used field three as a grep criteria. Anyhow, here is the while loop. As before, bring back your old command and go to the end of the line:

# lspv | grep power | grep None | while read DISK TRASH
>

Even though you have hit enter, the while loop isn’t logically done. What we have done so far is
start the loop and read the first field into the variable DISK and the other stuff into TRASH. This is
a handy way to say, just give me the first field. If you have more fields than variables, they all end up in the last. If you need the second field, just do this instead ( while read TRASH PVID TRASH ).

# lspv | grep power | grep None | while read DISK TRASH
> do
>

Logic still not done until we get to ‘done’, you can now add as many lines as you want to act on
$DISK.

# lspv | grep power | grep None | while read DISK TRASH
> do
> echo $DISK
> rmdev -dl $DISK
> done

hdiskpower3
hdiskpower3 deleted
hdiskpower1
hdiskpower1 deleted
hdiskpower5
hdiskpower5 deleted
hdiskpower6
hdiskpower6 deleted
hdiskpower7
hdiskpower7 deleted
hdiskpower0
hdiskpower0 deleted
hdiskpower2
hdiskpower2 deleted
hdiskpower4
hdiskpower4 deleted
hdiskpower12
hdiskpower12 deleted
hdiskpower13
hdiskpower13 deleted
hdiskpower14
hdiskpower14 deleted
hdiskpower18
hdiskpower18 deleted

If you think the while loop and second shell is a little cumbersome, then introduce awk and xargs:

# lspv | grep power | grep None | awk ‘{ print $1 }’ | xargs -n1 rmdev -dl

Here is a third way to accomplish this if you are a big fan of back-tick:

for DISK in `lspv | grep power | grep None | awk ‘{print $1}’`
do
rmdev-dl $DISK
done

This command is a little more awkward because if you crafted it in a REPL fashion while checking your logic and data, you would probably start with:

lspv | grep power | grep None | awk ‘{print $1}’

Then you would have to go to both the beginning and end of the line, to wrap this is a backquote.

Here are some other ideas for isolating only the first field of data:

lspv | grep power | grep None | sed ‘s/ .*//g’
lspv | grep power | grep None | cut -c 0-12

Ultimately, I almost always pick the while loop though, because it is just so fast and you can load or discard all sorts of variables on the fly. Just put an echo before your command if you aren’t sure of how it will look and bring the whole thing back and take it out when you are ready to run. Here is a case when a for loop is cool:

# for X in hdiskpower6 hdiskpower7 hdiskpower8
> do
> extendvg oraclevg1 $X
> done

Leave a Reply

Your email address will not be published. Required fields are marked *