script help please

I wrote script for importing massive amount of volume groups on HP-UX. This is related to ServiceGuard and making sure the alternate nodes have the correct VG information after a change to the primary. Everything works great except for one problem, the paths do not match up between the nodes so that c19t5d0 on the primary looks like c36t5d0 on the alternate. I tried to solve this by using the vgimport -s option but this brought in all the PV links too. Because we use Powerpath we do not want the PV links.

This is the part I am stuck on. What I want is to be able to create a disk file for use with vgimport -f using the lvmtab after doing the vgimport -s. I will then export and reimport again using the correct devices. The script I've got already is big enough so I'd like this part to be as efficient as possible.

For example I want to find all of the disks belonging to vgabc but I do not want the PV links:

root:> strings /etc/lvmtab
/dev/vgaaa
/dev/dsk/c8t9d0
/dev/dsk/c8t9d2
/dev/dsk/c8t9d4
/dev/dsk/c9t9d0
/dev/dsk/c9t9d2
/dev/dsk/c9t9d4
/dev/vgabc
/dev/dsk/c8t9d1
/dev/dsk/c8t9d3
/dev/dsk/c9t9d1
/dev/dsk/c9t9d3
/dev/vgbbb
/dev/dsk/c8t7d0
...etc

Should output only as based on variable <vgabc>:
/dev/dsk/c8t9d1
/dev/dsk/c8t9d3

so that I can write this to the disks file. The first thing I'll have to do is figure out which devices only belong to <vgabc>. Next figure out which of those devices are redundant and only print each disk once without the alternate paths. Also, several VGs have more than one PV link so I cannot assume that I can just cut the number of devices in half.

Any help would be much appreciated.

I don't have access to an HP box anymore, but I think you just remove lvmtab and run vgscan. vgscan should see any attached disks, create the volume group device files and rebuild lvmtab. It will find alternate links (I think). But if the atlernate links are not connected, it can't find them.

Well, see, that's the problem. The alternate paths are connected so when I do a vgscan I get all the devices. Because of EMC's Powerpath we do not want the alternate paths in the lvmtab.

Note: below that vgbbb refers to same disk twice

> cat rev_dsk
#! /bin/bash

#remove any existing work files
rm tmp_*

#assumes file disklist exists; listing from lvm
while read zf
   do
   chkvar=$(echo "$zf" | cut -c6-8)
   echo $chkvar
   if [ "$chkvar" = "dsk" ]
      then
         echo "$zf" >> "$vgrp"
      else
         filevar=$(echo "$zf" | cut -c6-)
         vgrp="tmp_""$filevar"
   fi
done < disklist 

for yf in tmp_*
   do
   sort -u "$yf" > "$yf"".srt"
done

The group with a duplicate:

And the resulting file from a sort -u

Thank you for the reply Joeyg but I think you might have missed something in my post.

In the lvmtab you will find a disk such as:
/dev/dsk/c8t13d0

If there is an alternate path to this same disk it may show as:
/dev/dsk/c9t13d0

This is the same disk but not the same device file. I am not looking for duplicate lines in this file but need to figure out which device files are for the same disk. Basically, for every VG there will be a number of unique device files. The number of devices is too large because there are multiple paths to the same disk. I need to work one VG at a time and this is not simply a text file I can edit. So I will need to identify via a variable which VG I want to work on, figure out which devices belong to it based on this output and then write only the unique disks, not devices, to a file.

How do you know that

/dev/dsk/c8t13d0
and
/dev/dsk/c9t13d0

are the same?

Are you impying:
(a) ignore value immadiately after the c
(b) only consider the t and d data

Any of these could be one digit or two digits, therefore not simply a cut at character positions. (If I understand where you are going with this.)

Because a change made to /dev/dsk/c8t13d0 is then visible on /dev/dsk/c9t13d0.

from this original file:

based on this coding:

> cat rev_dsk
#! /bin/bash

#remove any existing work files
rm tmp_*

#assumes file disklist exists; listing from lvm
while read zf
   do
   chkvar=$(echo "$zf" | cut -c6-8)
#   echo $chkvar
   if [ "$chkvar" = "dsk" ]
      then
         devvar=$(echo "$zf" | cut -c10-)
         diskvar=$(echo "$devvar" | cut -d"t" -f2)
         echo "t""$diskvar" >> "$vgrp"
      else
         filevar=$(echo "$zf" | cut -c6-)
         vgrp="tmp_""$filevar"
   fi
done < disklist 

for yf in tmp_*
   do
   sort -u "$yf" > "$yf"".srt"
done

If this is along the correct lines, the script could probably also tell the "c" values (=c8 and c9) for any volume group. Before going to that extent, and not sure if you need, want to see if this brings you in the correct direction.

If none of the replies thus far have helped you, please be more specific. I've read through this thread several times and I'm still not sure what you are looking for.

You're using terms such as Powerpath, vgimport, PV links, etc., all of which mean nothing at all to me.

If you can, explain it in generic way, posting lines of sample input file(s) and desired output, and any rules which need to be applied to get us from A to B without having to understand your infrastructure.

Thanks,
Shawn

OK let me try to be as direct as possible:
I have a list. See example above. On one line will be the name of the Volume Group. All of the lines after that will be devices belonging to that Volume Group until a new Volume Group is reached in the list. See example above. It is easy to tell the difference between devices and Volume Groups because the devices will all start with /dev/dsk.

I want to output all of the devices pertaining to a specified Volume Group. Only the disks belonging to that Volume Group and nothing else. I will specify via a variable which Volume Group I am looking for.

Secondly, there may be multiple I/O paths to any device but the number of paths can vary. In this case, a single disk will have two or more device files starting with /dev/dsk in this list. I only want to list one device file for each physical disk. See example and sample output above. This can be distinguished by the controller id. The c represents the controller, i.e. c9t13d2 is the same physical disk as c4t13d2 but the I/O path is to a different controller.

For each unique Volume Group I want to output to a file only the unique disks for that Volume Group. I do not care which controller is used (the c number), only that the disks are unique (the t and d numbers, aka. target and device numbers).

I am sorry to have confused anyone with the technical reasoning behind this but I knew that if I did not state my purpose that people would want to know why I was doing it so that they may try to come up with alternative solutions. Hopefully this makes sense because I'm not sure how else to explain it.

Thank you everyone for your responses so far. By the way, this is an HP-UX server and there is no bash installed. Everything I do is therefore written in ksh or Posix shell (which is pretty much similar to ksh).

Well after a few days of thought this is what I was able to come up with. Please let me know if you can think of a cleaner or more efficient way of doing this.

#!/usr/bin/ksh
VG="vgabc"

for i in `strings /etc/lvmtab | awk 'BEGIN {x=0}
{
if ($0 ~ /'$VG'/ ) {getline; ++x}
if ($0 !~ /dsk/ ) {exit}
if (x == 1) { split($0, t_d_ , "dsk"); split(t_d_[2],t,"t"); split(t[2],d,"d"); print "t"d[1]"d"d[2]}
}' | sort -n | uniq`
do
strings /etc/lvmtab | grep $i | sort | head -n 1
done