From: James on
Hi all,

I have a Unix box: a group called "testgrp", gid=321
dozens of users belonging to this group, e.g. tuser01 (uid=241),
tuser02 (uid=257), ... not sequential...

Now I have to rearrange gid and uids to keep them consistent
with other systems, i.e. testgrp's gid will be changed to 7000,
tuser01's uid=7001, tuser02's uid=7002, etc...
All files owned by the group and users also need to be updated
accordingly.

The way I am currently implemented is
update gid first
1) find /!(tmp|var|proc) -group testgrp -o -group 321 -print >
filelist1
2) groupmod -g 7000 testgrp
3) cat filelist1 | xargs chgrp testgrp
update uid
4) find /!(tmp|var|proc) -user tuser01 -o -user 241 -print > filelist2
5) usermod -u 7001 -g testgrp tuser01
6) cat filelist2 | xargs chown tuser01:testgrp
7) repeat 4)-6) for each user

Now the problems are
a) machine is a little busy and the hard drive is 300G, so each "find"
takes about 30 minutes.
b) we have a dozen of such groups and over 200 users to be updated
in the above way.

I wondered if some redundancies could be removed from the above
process, or there is any faster way to do it.

Many thanks,

James

From: Thomas J. on
James schrieb:

> Hi all,
>
> I have a Unix box: a group called "testgrp", gid=321
> dozens of users belonging to this group, e.g. tuser01 (uid=241),
> tuser02 (uid=257), ... not sequential...
>
> Now I have to rearrange gid and uids to keep them consistent
> with other systems, i.e. testgrp's gid will be changed to 7000,
> tuser01's uid=7001, tuser02's uid=7002, etc...
> All files owned by the group and users also need to be updated
> accordingly.
>
> The way I am currently implemented is
> update gid first
> 1) find /!(tmp|var|proc) -group testgrp -o -group 321 -print >
> filelist1
> 2) groupmod -g 7000 testgrp
> 3) cat filelist1 | xargs chgrp testgrp
> update uid
> 4) find /!(tmp|var|proc) -user tuser01 -o -user 241 -print > filelist2
> 5) usermod -u 7001 -g testgrp tuser01
> 6) cat filelist2 | xargs chown tuser01:testgrp
> 7) repeat 4)-6) for each user
>
> Now the problems are
> a) machine is a little busy and the hard drive is 300G, so each "find"
> takes about 30 minutes.
> b) we have a dozen of such groups and over 200 users to be updated
> in the above way.
>
> I wondered if some redundancies could be removed from the above
> process, or there is any faster way to do it.
>

I dont know if the following is faster, but there is only one find....

find /!(tmp|var|proc) -group testgrp -ls | awk '!( $11 ~ /^\.$/){print
"chown " $5":testgrp "$11;}'

this will give you a list of chown-commands you can execute after
groupmod and usermod

hope this helps

Thomas

From: John W. Krahn on
James wrote:
>
> I have a Unix box: a group called "testgrp", gid=321
> dozens of users belonging to this group, e.g. tuser01 (uid=241),
> tuser02 (uid=257), ... not sequential...
>
> Now I have to rearrange gid and uids to keep them consistent
> with other systems, i.e. testgrp's gid will be changed to 7000,
> tuser01's uid=7001, tuser02's uid=7002, etc...
> All files owned by the group and users also need to be updated
> accordingly.
>
> The way I am currently implemented is
> update gid first
> 1) find /!(tmp|var|proc) -group testgrp -o -group 321 -print >
> filelist1
> 2) groupmod -g 7000 testgrp
> 3) cat filelist1 | xargs chgrp testgrp
> update uid
> 4) find /!(tmp|var|proc) -user tuser01 -o -user 241 -print > filelist2
> 5) usermod -u 7001 -g testgrp tuser01
> 6) cat filelist2 | xargs chown tuser01:testgrp
> 7) repeat 4)-6) for each user
>
> Now the problems are
> a) machine is a little busy and the hard drive is 300G, so each "find"
> takes about 30 minutes.
> b) we have a dozen of such groups and over 200 users to be updated
> in the above way.
>
> I wondered if some redundancies could be removed from the above
> process, or there is any faster way to do it.

(UNTESTED):

#!/usr/bin/perl

$< and die "Must be root to run this program.\n";

my $group = 'testgrp';
my %gids = (
321 => { name => $group, num => 7000 },
);

my %uids = (
241 => { name => 'tuser01', num => 7001 },
257 => { name => 'tuser02', num => 7002 },
# etc.
);


use File::Find;

my %hard_links;
find sub {
return if $File::Find::dir =~ m!^/(?:tmp|var|proc)!;

my ( $dev, $ino, $mode, $nlink, $uid, $gid,
$rdev, $size, $atime, $mtime, $ctime ) = lstat;

# ignore symlinks or block/character special files
-l _ || -b _ || -c _ and return;

# ignore if hard linked and already modified
$nlink > 1 && $hard_links{ $dev, $ino }++ and return;

# change the UID and GID or keep the current value
chown $uids{ $uid }{ num } || -1, $gids{ $gid }{ num } || -1, $_
or warn "Cannot chown '$_' $!" and return;

# optionally put back original atime and mtime
#utime $atime, $mtime, $_
# or warn "Cannot touch '$_' $!";

# start at root /
}, '/';


for my $gid ( keys %gids ) {
system 'groupmod', '-g', $gids{$gid}{num}, $gids{$gid}{name}
and warn "Cannot change group '$gids{$gid}{name}' $?";
}

for my $uid ( keys %uids ) {
system 'usermod', '-u', $uids{$uid}{num}, '-g', $group, $uids{$uid}{name}
and warn "Cannot change user '$uids{$uid}{name}' $?";
}

__END__



John
--
use Perl;
program
fulfillment
From: Bruce Barnett on
"James" <jzheng22(a)gmail.com> writes:

> Hi all,
>
> I have a Unix box: a group called "testgrp", gid=321
> dozens of users belonging to this group, e.g. tuser01 (uid=241),
> tuser02 (uid=257), ... not sequential...
>
> Now I have to rearrange gid and uids to keep them consistent
> with other systems, i.e. testgrp's gid will be changed to 7000,
> tuser01's uid=7001, tuser02's uid=7002, etc...


I had to do this 15 years ago when we started using NFS and has a
hundred servers.

It can be a tricky problem.
For instance, some people's UID's can conflict.
Joe is 100, and Bill is 101, but on the other system it's reversed.
So one might have to change the UID to a "neutral" number first.

I ended up writing a C program that takes as input two /etc/passwd
files. It first makes sure there is no conflict/collisions before it
changes the UID's.

Then it does a recursive parse through the diretory structure,
renumbering UID's. Nowadays I'd use perl.

I don't remember if it did /etc/group changes.

I'm not sure I can find it. I'll take a look if you are interested.

--
Sending unsolicited commercial e-mail to this account incurs a fee of
$500 per message, and acknowledges the legality of this contract.