
使用 RedHat 衍生發行版 (CentOS),我想保留推送到備份伺服器的常規用戶(UID 超過 500)和群組(和影子檔案)的清單。
同步只是單向的,從主伺服器到備份伺服器。
我真的不想處理 LDAP 或 NIS。
我所需要的只是一個可以每晚運行以保持備份伺服器更新的簡單腳本。
主伺服器可以透過 SSH 存取備份系統。
有什麼建議嗎?
編輯:
感謝到目前為止您的建議,但我認為我的表達還不夠清楚。
我只考慮同步普通用戶UID 等於或大於 500。
兩個系統上的系統/服務使用者(UID 低於 500)可能不同。
所以恐怕你不能只同步整個文件。
答案1
您可以使用 awk 提取 ID 為 500 或更大的使用者/群組。我還冒昧地排除了用戶 id 65534,該用戶通常是為「nobody」用戶保留的(取決於發行版;不知道 CentOS 是否這樣做):
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
然後使用 rsync、scp 或您選擇的檔案傳輸方法將檔案複製到備份系統。當您需要復原這些檔案時,可以將這些檔案附加到「乾淨」的密碼、群組或影子檔案的末端(即:僅限預設系統使用者/群組,以防止無意中重複 ID/使用者名稱)。
cat passwd.new >> /etc/passwd
cat group.new >> /etc/group
cat shadow.new >> /etc/shadow
答案2
NIS/NIS+ 正是因為這個原因而發明的。
但它們有點醜陋,而且集中式(LDAP/Kerberos/SMB/等)身份驗證是一個更好的主意,如果你能做到的話。要設定 NIS/NIS+,您需要:
套餐:
yp-tools ypbind ypserv portmap
和 /etc/yp.conf ,其中包含以下內容:
domain example.org server nis.example.org
ypserver nis.example.org
然後在 /etc/sysconfig/network 中:
NISDOMAIN=example.org
我很懶,這裡有個很好的方法:http://www.wains.be/index.php/2007/02/28/setting-up-nis-under-centos-4/這將引導您完成它。
就我個人而言,為了備份,我只需備份整個 /etc/ 目錄並完成它。最多也就幾兆而已。
答案3
使用 cppw 和 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.
答案4
好吧,我認為有一些現有的東西我可以使用,而不必推出自己的解決方案,但我必須快速做一些事情。
下面的腳本可以滿足我的需要。
指示
為了讓它工作,只需更改最小和最大 UID 的幾個配置變數即可被視為普通的使用者和遠端主機名稱或 IP 位址。
您必須將遠端伺服器設定為接受來自本機伺服器使用者的傳入 SSH 會話,root
而無需輸入密碼。
基恩指揮官在本頁的答案中暗示了它是如何完成的,但您也可以參考無密碼 SSH 登入取得詳細說明。
怎麼運作的
該腳本的作用是複製每個遠端密碼,團體,陰影,影子檔案從遠端伺服器複製到 lcoal 伺服器上的暫存位置。
然後,它從所有「普通」使用者中刪除這些臨時文件,僅保留對系統使用者的參考。
下一步是檢查每個本地版本密碼,團體,陰影,影子並將“普通”用戶附加到相應的臨時文件中,然後將每個用戶上傳回遠端伺服器以替換舊的。
警告
在嘗試任何操作之前,請確保您複製了一份 密碼,團體,陰影,影子在本地和遠端伺服器上。
安全
文件所有權和屬性被保留。無論同步是否成功,
都會儲存並刪除臨時檔案。 本機伺服器必須具有備份的無密碼存取權限(但反之則不然)。這是必要的,以便我們可以獲得使用者帳戶設定檔(否則會受到限制)。/tmp
root
程式碼
這是第一次嘗試,有點混亂(程式碼不漂亮),但它做得很好,其他人可能會發現它很有用。
這是一個 Perl 腳本,僅依賴Net::SCP
模組在伺服器之間安全地複製檔案。
#!/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;
}
}
2010 年 5 月 21 日更新:更新程式碼以改善群組 ID 同步