Online Book Reader

Home Category

Classic Shell Scripting - Arnold Robbins [172]

By Root 942 0
dupusers dupids unique-ids old-new-list

Here is what chown-files looks like:

$ cat chown-files

find / -user ben -print | xargs chown 301

find / -user jhancock -print | xargs chown 300

find / -user abe -print | xargs chown 4

find / -user tj -print | xargs chown 5

find / -user dorothy -print | xargs chown 6

find / -user toto -print | xargs chown 7

Remember the old-new-list file?

$ cat old-new-list

ben 201 301

jhancock 200 300

abe 105 4

tj 105 5

dorothy 110 6

toto 110 7

You may have noted that both abe and tj start out with the same UID. Similarly for dorothy and toto. What happens when we run chown-files? Won't all of tj's files end up belonging to the new UID 4? Won't all of toto's files end up belonging to the new UID 6? Haven't we just created the mess that we thought we had avoided?

The answer is that we're safe, as long as we run these commands separately on each system, before we put the new /etc/passwd file in place on each system. Remember that originally, abe and dorothy were only on u1, and that tj and toto were only on u2. Thus, when chown-files runs on u1 with the original /etc/passwd in place, find will never find tj's or toto's files, since those users don't exist:

$ find / -user toto -print

find: invalid argument `toto' to `-user'

Things will fail similarly, but for the opposite pair of users, on u2. The full merge-systems.sh script is presented in Example 11-5.

Example 11-5. The merge-systems.sh program

#! /bin/sh

sort u1.passwd u2.passwd > merge1

awk -f splitout.awk merge1

awk -F: '{ print $3 }' merge1 | sort -n -u > unique-ids

rm -f old-new-list

old_ifs=$IFS

IFS=:

while read user passwd uid gid fullname homedir shell

do

if read user2 passwd2 uid2 gid2 fullname2 homedir2 shell2

then

if [ $user = $user2 ]

then

printf "%s\t%s\t%s\n" $user $uid $uid2 >> old-new-list

echo "$user:$passwd:$uid2:$gid:$fullname:$homedir:$shell"

else

echo $0: out of sync: $user and $user2 >&2

exit 1

fi

else

echo $0: no duplicate for $user >&2

exit 1

fi

done < dupusers > unique2

IFS=$old_ifs

count=$(wc -l < dupids) # Total duplicate ids

# This is a hack, it'd be better if POSIX sh had arrays:

set -- $(newuids.sh -c $count unique-ids)

IFS=:

while read user passwd uid gid fullname homedir shell

do

newuid=$1

shift

echo "$user:$passwd:$newuid:$gid:$fullname:$homedir:$shell"

printf "%s\t%s\t%s\n" $user $uid $newuid >> old-new-list

done < dupids > unique3

IFS=$old_ifs

sort -k 3 -t : -n unique[123] > final.password

while read user old new

do

echo "find / -user $user -print | xargs chown $new"

done < old-new-list > chown-files

chmod +x chown-files

rm merge1 unique[123] dupusers dupids unique-ids old-new-list

Other Real-World Issues

There are some other issues that are likely to come up in the Real World. For the sake of brevity we wimp out, and instead of writing code, we simply discuss them here.

First, and most obvious, is that the /etc/group file is also likely to need merging. With this file, it's necessary to:

Make sure that all the groups from each individual system exist in the merged /etc/group file, and with the same unique GID. This is completely analogous to the username/UID issue we just solved, only the format of the file is different.

Do a logical merge of users in the same group on the different systems. For example:

floppy:x:5:tolstoy,camus In u1 /etc/group

floppy:x:5:george,betsy In u2 /etc/group

When the files are merged, the entry for group floppy needs to be:

floppy:x:5:tolstoy,camus,george,betsy Order of users doesn't matter

The GID of all files must be brought into sync with the new, merged /etc/group file, just as was done with the UID. If you're clever, it's possible to generate the find ... | xargs chown ... command to include the UID and GID so that they need to be run only once. This saves machine processing time at the expense of additional programming time.

Second, any large system that has been in use for some time will have files with UID or GID values that no longer (or never

Return Main Page Previous Page Next Page

®Online Book Reader