Soluzione 1:
Puoi utilizzare awk per estrarre utenti/gruppi con ID di 500 o superiore. Mi sono anche preso la libertà di escludere l'ID utente 65534, che è spesso riservato all'utente "nessuno" (a seconda della distribuzione; nessun indizio se CentOS lo fa):
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
Quindi utilizzare rsync, scp o il metodo di trasmissione file preferito per copiare i file sul sistema di backup. Questi file possono quindi essere aggiunti alla fine di un passwd, un gruppo o un file shadow "pulito" quando è necessario ripristinarli (ad esempio:solo utenti/gruppi di sistema predefiniti, per evitare duplicazioni involontarie di ID/nome utente).
cat passwd.new >> /etc/passwd
cat group.new >> /etc/group
cat shadow.new >> /etc/shadow
Soluzione 2:
NIS/NIS+ sono stati inventati proprio per questo motivo.
Ma sono un po 'brutti e l'autenticazione centralizzata (LDAP/Kerberos/SMB/ecc.) è un'idea molto migliore se puoi farlo. Per configurare NIS/NIS+ avrai bisogno di:
Pacchetti:
yp-tools ypbind ypserv portmap
e un /etc/yp.conf con qualcosa come:
domain example.org server nis.example.org
ypserver nis.example.org
e poi in /etc/sysconfig/network:
NISDOMAIN=example.org
E sono diventato pigro, ecco un buon howto:http://www.wains.be/index.php/2007/02/28/setting-up-nis-under-centos-4/ che ti guiderà attraverso di esso.
Personalmente per il backup farei semplicemente il backup dell'intera directory /etc/ e finirò con esso. Sono solo pochi mega al massimo.
Soluzione 3:
usa cppw e 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.
Soluzione 4:
Ci sono molti modi e soluzioni qui, ma per rispondere alla domanda originale ci sono tre passaggi:
-
Crea una chiave SSH senza password sul server:
ssh-keygen -b 4096
-
Copia .ssh/id_rsa.pub in .ssh/authorized__keys2 sul client:
scp ~/.ssh/id_rsa.pub client:.ssh/authorized_keys2
-
Aggiungi qualcosa di simile al tuo /etc/crontab (o modifica con crontab -e):
0 0 * * * scp /etc/{passwd,shadow,group} [email protected]:/var/mybackupdir
Soluzione 5:
Bene, pensavo che esistesse qualcosa che potevo usare senza dover implementare la mia soluzione, ma dovevo fare qualcosa in fretta.
Di seguito è riportato uno script che farà proprio ciò di cui avevo bisogno.
Istruzioni
Perché funzioni, basta modificare le poche variabili di configurazione per l'UID minimo e massimo da considerare come normale utente e il nome o l'indirizzo IP dell'host remoto.
Devi aver configurato il server remoto per accettare le sessioni SSH in entrata dal root
del server locale utente senza dover inserire una password.
Il Comandante Keen ha accennato a come si fa nella sua risposta in questa pagina, ma puoi anche fare riferimento all'accesso SSH senza password per istruzioni dettagliate.
Come funziona
Quello che fa lo script è copiare ciascuna delle passwd remote , gruppo , ombra , gshadow file dal server remoto a una posizione temporanea sul server lcoal.
Quindi rimuove questi file temporanei da tutti gli utenti "normali", mantenendo solo i riferimenti agli utenti di sistema.
Il passaggio successivo consiste nell'esaminare ciascuna delle versioni locali di passwd , gruppo , ombra , gshadow e aggiungendo solo gli utenti "normali" ai loro file temporanei corrispondenti, quindi caricandoli nuovamente sul server remoto per sostituire quello vecchio.
Avviso
Prima di tentare qualsiasi cosa, assicurati di fare una copia della tua passwd , gruppo , ombra , gshadow sia sul server locale che su quello remoto.
Sicurezza
La proprietà e gli attributi del file vengono mantenuti.
I file temporanei vengono salvati in /tmp
ed eliminato, indipendentemente dal fatto che la sincronizzazione sia andata a buon fine o meno.
Il server locale deve avere root
senza password accedere al backup (ma non viceversa). Questo è necessario per poter ottenere i file di configurazione degli account utente (che sono altrimenti limitati).
Il Codice
Questo è un primo tentativo ed è un po' disordinato (codice non bellissimo) ma fa il suo lavoro abbastanza bene e qualcun altro potrebbe trovarlo utile.
È uno script Perl che ha solo una dipendenza dal Net::SCP
modulo per copiare i file in modo sicuro tra i server.
#!/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;
}
}
Aggiornamento 21 MAGGIO 2010:codice aggiornato per migliorare la sincronizzazione dell'ID gruppo