AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 18444
Accepted
Renaud Bompuis
Renaud Bompuis
Asked: 2009-06-03 20:04:12 +0800 CST2009-06-03 20:04:12 +0800 CST 2009-06-03 20:04:12 +0800 CST

服务器间用户密码列表的简单单向同步

  • 772

使用 RedHat 衍生发行版 (CentOS),我想保留普通用户列表(UID 超过 500),并将组(和影子文件)推送到备份服务器。
同步是单向的,从主服务器到备份服务器。

我真的不想处理 LDAP 或 NIS。
我只需要一个简单的脚本,它可以每晚运行以保持备份服务器的更新。
主服务器可以通过 SSH 连接到备份系统。

有什么建议吗?

编辑:
感谢到目前为止的建议,但我认为我还不够清楚。
我只关注同步UID 大于或等于 500的普通用户。
两个系统上的系统/服务用户(UID 低于 500)可能不同。
因此,恐怕您不能只同步整个文件。

synchronization linux user-management
  • 7 7 个回答
  • 26794 Views

7 个回答

  • Voted
  1. goldPseudo
    2009-06-03T21:42:32+08:002009-06-03T21:42:32+08:00

    您可以使用 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
    
    • 10
  2. Kurt
    2009-06-03T20:41:34+08:002009-06-03T20:41:34+08:00

    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
  3. Vish
    2009-06-04T06:45:12+08:002009-06-04T06:45:12+08:00

    使用 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.
    
    • 3
  4. Commander Keen
    2009-06-03T20:32:33+08:002009-06-03T20:32:33+08:00

    这里有很多方法和解决方案,但是要回答原始问题,需要三个步骤:

    1. 在服务器上创建一个无密码的 SSH 密钥:

      ssh-keygen -b 4096

    2. 将 .ssh/id_rsa.pub 复制到客户端上的 .ssh/authorized__keys2 :

      scp ~/.ssh/id_rsa.pub client:.ssh/authorized_keys2 

    3. 在 /etc/crontab 中添加类似这样的内容(或使用 crontab -e 进行编辑):

      0 0 * * * scp /etc/{passwd,shadow,group} root@backupbox:/var/mybackupdir 

    • 2
  5. Best Answer
    Renaud Bompuis
    2009-06-04T03:41:44+08:002009-06-04T03:41:44+08:00

    好吧,我认为我可以使用现有的东西而不必推出自己的解决方案,但我必须快速做一些事情。

    下面是一个脚本,可以满足我的需要。

    指示

    要使其正常工作,只需将最小和最大 UID 的几个配置变量更改为普通用户和远程主机名或 IP 地址。

    您必须设置远程服务器以接受来自本地服务器root用户的传入 SSH 会话,而无需输入密码。
    指挥官 Keen在此页面上的回答中暗示了它是如何完成的,但您也可以参考无密码 SSH 登录以获取详细说明。

    这个怎么运作

    该脚本所做的是将远程服务器上的每个远程passwd、group、shadow、gshadow文件复制到 lcoal 服务器上的临时位置。
    然后它从所有“普通”用户中删除这些临时文件,只保留对系统用户的引用。

    下一步是检查passwd、group、shadow、gshadow的每个本地版本,并将“普通”用户附加到相应的临时文件中,然后将每个用户上传回远程服务器以替换旧的。

    警告

    在您尝试任何事情之前,请确保 在本地和远程服务器上复制您的passwd、group、shadow、gshadow 。

    安全

    文件所有权和属性被保留。无论同步成功与否,都会
    保存并删除临时文件。 本地服务器必须对备份具有无密码访问权限(但不能反过来)。这是必要的,因此我们可以获得用户帐户配置文件(否则会受到限制)。/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 的同步

    • 2
  6. Zoredache
    2009-06-03T20:08:38+08:002009-06-03T20:08:38+08:00

    您只需要部分同步意味着脚本必须要复杂得多,因此更有可能出现某种错误。就个人而言,我会花一些时间来调查简单地修复这些其他帐户需要付出多少努力。我不知道我们在谈论多少服务,但我猜想,在更改调整服务帐户的 ID 后,您所要做的就是更新某些文件的所有者。

    如果你想做一些非常简单的事情,你可以设置像rdist ( intro ) 来简单地将文件推送到你想要的其他服务器。为了保证这一点的安全,您需要设置基于密钥的 ssh 访问以供 rdist 进程使用。

    • 0
  7. user3146
    2009-06-03T20:22:55+08:002009-06-03T20:22:55+08:00

    我在 crontab 条目中使用 rsync 来执行完成相同任务的简单备份。不幸的是,我不是通过 ssh 来做的。我的 crontab 条目如下所示:

    0 4 * * 0 rsync -av --delete /etc/ /backup/etc/

    实际上,我的 crontab 启动了我的 NAS 服务器,即您在上面看到的第二条路径,通过网络唤醒,然后做了几个备份,这只是其中之一。然后 Cron 给我发一封电子邮件,让我知道备份了什么,即同步了哪些文件等。

    我没有考虑过通过 ssh 执行此操作,但我希望这会有所帮助。

    • 0

相关问题

  • 你最喜欢的 Linux 发行版是什么?[关闭]

  • 您如何优化新用户设置?

  • 更改 PHP 的默认配置设置?

  • 保护新的 Ubuntu 服务器 [关闭]

  • (软)Ubuntu 7.10 上的 RAID 6,我应该迁移到 8.10 吗?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    从 IP 地址解析主机名

    • 8 个回答
  • Marko Smith

    如何按大小对 du -h 输出进行排序

    • 30 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    Windows 中执行反向 DNS 查找的命令行实用程序是什么?

    • 14 个回答
  • Marko Smith

    如何检查 Windows 机器上的端口是否被阻塞?

    • 4 个回答
  • Marko Smith

    我应该打开哪个端口以允许远程桌面?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    MikeN 在 Nginx 中,如何在维护子域的同时将所有 http 请求重写为 https? 2009-09-22 06:04:43 +0800 CST
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    0x89 bash中的双方括号和单方括号有什么区别? 2009-08-10 13:11:51 +0800 CST
  • Martin Hope
    kch 如何更改我的私钥密码? 2009-08-06 21:37:57 +0800 CST
  • Martin Hope
    Kyle Brandt IPv4 子网如何工作? 2009-08-05 06:05:31 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve