
RedHat 派生ディストリビューション (CentOS) を使用して、通常のユーザー (UID が 500 を超える) とグループ (およびシャドウ ファイル) のリストをバックアップ サーバーにプッシュしておきたいと考えています。
同期はメイン サーバーからバックアップ サーバーへの一方向のみです。
LDAP や NIS を実際に扱う必要はありません。
必要なのは、バックアップ サーバーを最新の状態に保つために毎晩実行できる簡単なスクリプトだけです。
メイン サーバーはバックアップ システムに SSH で接続できます。
なにか提案を?
編集:
これまでの提案に感謝しますが、私の説明が不十分だったと思います。
私は、UID が 500 以上システム
/サービス ユーザー (UID が 500 未満) は両方のシステムで異なる場合があります。
そのため、ファイル全体を同期することはできません。
答え1
awk を使用すると、ID が 500 以上のユーザー/グループを抽出できます。また、ユーザー ID 65534 を除外する自由も取りました。この ID は、多くの場合、「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、または選択したファイル転送方法を使用して、ファイルをバックアップ システムにコピーします。これらのファイルは、復元する必要がある場合に、「クリーンな」passwd、group、または shadow ファイルの末尾に追加できます (つまり、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 アドレス。
root
パスワードを入力せずにローカル サーバーのユーザーからの着信 SSH セッションを受け入れるようにリモート サーバーを設定する必要があります。
コマンダー・キーンこのページの回答でその方法については触れられていますが、パスワードなしのSSHログイン詳細な手順については、こちらをご覧ください。
使い方
このスクリプトはリモートの各ファイルをコピーしますパスワード、グループ、影、gシャドウファイルをリモート サーバーからローカル サーバーの一時的な場所に移動します。
次に、これらの一時ファイルをすべての「通常の」ユーザーから削除し、システム ユーザーへの参照のみを保持します。
次のステップは、各ローカルバージョンを確認することです。パスワード、グループ、影、gシャドウそして、対応する一時ファイルに「通常の」ユーザーのみを追加し、それらをそれぞれリモート サーバーにアップロードして、古いユーザーを置き換えます。
警告
何かを試みる前に、必ずコピーを取っておいてください パスワード、グループ、影、gシャドウローカル サーバーとリモート サーバーの両方で。
安全
ファイルの所有権と属性は保持されます。同期が成功したかどうかに関係なく、
一時ファイルは保存され、削除されます。 ローカル サーバーは、バックアップにパスワードなしでアクセスできる必要があります (ただし、その逆は不可)。これは、ユーザー アカウントの構成ファイル (それ以外の場合は制限されます) を取得するために必要です。/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の同期を改善するためにコードを更新しました