
Mithilfe einer von RedHat abgeleiteten Distribution (CentOS) möchte ich die Liste der regulären Benutzer (UID über 500) und Gruppen (und Schattendateien) auf einen Backup-Server übertragen.
Die Synchronisierung erfolgt nur in eine Richtung, vom Hauptserver zum Backup-Server.
Ich möchte mich nicht wirklich mit LDAP oder NIS herumschlagen müssen.
Alles, was ich brauche, ist ein einfaches Skript, das jede Nacht ausgeführt werden kann, um den Backup-Server auf dem neuesten Stand zu halten.
Der Hauptserver kann sich per SSH mit dem Backup-System verbinden.
Irgendein Vorschlag?
Bearbeiten:
Vielen Dank für die bisherigen Vorschläge, aber ich glaube, ich habe mich nicht klar genug ausgedrückt.
Ich betrachte nur die Synchronisierung normaler Benutzer, derenUID liegt bei oder über 500.
System-/Dienstbenutzer (mit UID unter 500) können auf beiden Systemen unterschiedlich sein.
Ich fürchte, Sie können daher nicht einfach alle Dateien synchronisieren.
Antwort1
Sie können awk verwenden, um Benutzer/Gruppen mit IDs von 500 oder höher zu extrahieren. Ich habe mir außerdem die Freiheit genommen, die Benutzer-ID 65534 auszuschließen, die oft für den Benutzer „nobody“ reserviert ist (je nach Distribution; keine Ahnung, ob CentOS dies tut):
awk -F: '($3>=500) && ($3!=65534)' /etc/passwd > passwd.new
awk -F: '($3>=500) && ($3!=65534)' /etc/group > group.new
awk -F: '($3>=500) && ($3!=65534) {print $1}' /etc/passwd | grep -f - /etc/shadow > shadow.new
Verwenden Sie dann rsync, scp oder die Dateiübertragungsmethode Ihrer Wahl, um die Dateien auf Ihr Backup-System zu kopieren. Diese Dateien können dann an das Ende einer „sauberen“ Passwd-, Gruppen- oder Schattendatei angehängt werden, wenn Sie sie wiederherstellen müssen (z. B. nur Standardsystembenutzer/-gruppen, um unbeabsichtigte Duplikate von ID/Benutzernamen zu verhindern).
cat passwd.new >> /etc/passwd
cat group.new >> /etc/group
cat shadow.new >> /etc/shadow
Antwort2
NIS/NIS+ wurden genau aus diesem Grund erfunden.
Sie sind jedoch ziemlich hässlich und eine zentralisierte Authentifizierung (LDAP/Kerberos/SMB/usw.) ist eine viel bessere Idee, wenn Sie sie durchführen können. Um NIS/NIS+ einzurichten, benötigen Sie:
Pakete:
yp-tools ypbind ypserv portmap
und eine /etc/yp.conf mit etwas wie:
domain example.org server nis.example.org
ypserver nis.example.org
und dann in /etc/sysconfig/network:
NISDOMAIN=example.org
Und ich wurde faul, hier ist eine gute Anleitung:http://www.wains.be/index.php/2007/02/28/setting-up-nis-under-centos-4/das Sie durch den Vorgang führt.
Ich persönlich würde zur Sicherung einfach das gesamte /etc/-Verzeichnis sichern und damit fertig sein. Es sind höchstens ein paar Megabyte.
Antwort3
verwenden Sie cppw und cpgr:
CPPW(8)
NAME
cppw, cpgr - copy with locking the given file to the
password or group file
SYNOPSIS<br>
cppw [-h] [-s] password_file
cpgr [-h] [-s] group_file
DESCRIPTION
cppw and cpgr will copy, with locking, the given file to
/etc/passwd and /etc/group, respectively. With the -s flag,
they will copy the shadow versions of those files,
/etc/shadow and /etc/gshadow, respectively.
With the -h flag, the commands display a short help message
and exit silently.
SEE ALSO
vipw(8), vigr(8), group(5), passwd(5), shadow(5), gshadow(5)
AUTHOR
cppw and cpgr were written by Stephen Frost, based on vipw
and vigr written by Guy Maor.
Antwort4
Nun, ich dachte, es gäbe bereits etwas, das ich nutzen könnte, ohne eine eigene Lösung entwickeln zu müssen, aber ich musste schnell etwas unternehmen.
Unten ist ein Skript, das genau das tut, was ich brauche.
Anweisungen
Damit es funktioniert, ändern Sie einfach die wenigen Konfigurationsvariablen für die minimale und maximale UID, die alsnormalBenutzer und der Remote-Hostname oder die IP-Adresse.
Sie müssen den Remote-Server so eingerichtet haben, dass er eingehende SSH-Sitzungen vom root
Benutzer des lokalen Servers akzeptiert, ohne ein Kennwort eingeben zu müssen.
Kommandant Keenhat in seiner Antwort auf dieser Seite angedeutet, wie es gemacht wird, aber Sie können auch aufpasswortloser SSH-Loginfür detaillierte Anweisungen.
Wie es funktioniert
Das Skript kopiert alle Remote-passwd,Gruppe,Schatten,gschattenDateien vom Remote-Server an einen temporären Speicherort auf dem lokalen Server.
Anschließend werden diese temporären Dateien von allen „normalen“ Benutzern entfernt, wobei nur die Verweise auf die Systembenutzer erhalten bleiben.
Der nächste Schritt ist die Durchsicht aller lokalen Versionen vonpasswd,Gruppe,Schatten,gschattenund hängen Sie nur die „normalen“ Benutzer an ihre entsprechenden temporären Dateien an. Anschließend laden Sie jeden von ihnen wieder auf den Remote-Server hoch, um den alten zu ersetzen.
Warnung
Bevor Sie etwas versuchen, stellen Sie sicher, dass Sie eine Kopie Ihrer passwd,Gruppe,Schatten,gschattensowohl auf dem lokalen als auch auf dem Remote-Server.
Sicherheit
Dateieigentum und -attribute bleiben erhalten.
Temporäre Dateien werden gespeichert /tmp
und gelöscht, unabhängig davon, ob die Synchronisierung erfolgreich war oder nicht.
Der lokale Server muss passwortlosen root
Zugriff auf das Backup haben (aber nicht umgekehrt). Dies ist notwendig, damit wir auf die Konfigurationsdateien der Benutzerkonten zugreifen können (die sonst eingeschränkt sind).
Der Code
Dies ist ein erster Versuch und er ist ein bisschen chaotisch (kein schöner Code), aber er funktioniert ganz gut und jemand anderes findet ihn vielleicht nützlich.
Es handelt sich um ein Perl-Skript, das nur eine Abhängigkeit hat vonNet::SCP
Modul zum sicheren Kopieren von Dateien zwischen Servern.
#!/usr/bin/perl -w
use Net::SCP qw(scp);
use strict;
use constant TRUE => (1==1);
use constant FALSE => (1==0);
#--------------------------------------------------------
# Configuration
# Modify as needed
#--------------------------------------------------------
my $remoteHost = '10.13.113.2'; # email backup server
my $minUID = 500;
my $maxUID = 30000;
my $minGID = 500;
my $maxGID = 30000;
#--------------------------------------------------------
# Internal variables, normally not to be modified.
#--------------------------------------------------------
my $systemConfigDir = '/etc';
my $tmpDir = $ENV{TMPDIR} || $ENV{TMP} || $ENV{TEMP} || '/tmp';
#--------------------------------------------------------
# Main
#--------------------------------------------------------
# STEP 1
# Get the remote files to /tmp and
# clean them of their normal users
ProcessFiles('remote');
# STEP 2
# Append the local normal users to the temp files
# and then send them back to the remote
ProcessFiles('local');
#--------------------------------------------------------
# ProcessFiles sub does one of two things:
# - if the passed argument is 'remote', then fetch each
# user account file from the remote server, then remove
# all normal users from each file, only keeping the
# system users.
# - if the passed argument is 'local', then appends all
# normal local users to the previously fetched and
# cleaned-up files, then copies them back to the remote.
#--------------------------------------------------------
sub ProcessFiles {
my $which = shift;
my $tmpfile;
my %username = ();
my %usergroup = ();
my %userUID = ();
my %userGID = ();
my @info;
foreach my $f ('passwd','group','shadow','gshadow') {
my $tmpfile = "$tmpDir/$f.REMOTE";
if ($which eq 'remote') {
# Fetch the remote file
unlink $tmpfile if -e $tmpfile;
scp("$remoteHost:$systemConfigDir/$f", $tmpfile)
or die ("Could not get '$f' from '$remoteHost'");
}
# Glob the file content
open CONFIGFILE, (($which eq 'remote') ? $tmpfile : "$systemConfigDir/$f");
my @lines = <CONFIGFILE>;
close CONFIGFILE;
# Open the temp file, either truncating it or in append mode
open TMPFILE, (($which eq 'remote') ? ">$tmpfile" : ">>$tmpfile" )
or die "Could not open '$tmpfile' for processing";
foreach my $line (@lines) {
# Skip comments, although they should be illegal in these files
next if $f =~ /^\s*#/;
@info = (split ':', $line);
if ($f eq 'passwd') {
my $uid = $info[2];
my $isnormaluser = ($uid > $minUID) && ($uid < $maxUID);
next if (($which eq 'remote') ? $isnormaluser : !$isnormaluser);
$username{$info[0]} = TRUE;
$userUID{$uid} = TRUE;
$userGID{$info[3]} = TRUE;
} elsif ($f eq 'group') {
my $gid = $info[2];
my $isnormalgroup = ($gid > $minGID) && ($gid < $maxGID);
next if (($which eq 'remote') ? $isnormalgroup : !$isnormalgroup);
$usergroup{$info[0]} = TRUE;
} elsif ($f eq 'shadow') {
next if !exists $username{$info[0]};
} else {
next if !exists $usergroup{$info[0]};
}
# Any line that reaches this point is valid
print TMPFILE $line;
}
close TMPFILE;
if ($which eq 'local') {
# send the file back
scp($tmpfile, "$remoteHost:$systemConfigDir/$f") or
die ("Could not send '$f' to '$remoteHost'");
unlink $tmpfile;
}
}
}
#--------------------------------------------------------
# Make sure we cleanup the temp files when we exit
#--------------------------------------------------------
END {
my $tmpfile;
foreach my $f ('passwd','group','shadow','gshadow') {
$tmpfile = "$tmpDir/$f.REMOTE";
unlink $tmpfile if -e $tmpfile;
}
}
Update 21. Mai 2010: Code aktualisiert, um die Synchronisierung der Gruppen-ID zu verbessern