长话短说:大型老公司,有很多 UNIX/Linux 服务器。
我接手了几年前遗留下来的一堆脚本。其中一个脚本每 $X 个月运行一次,以全局更新我们所有服务器的 root 密码。
该脚本是 Shell Script 和 Expect 的混合体,它在我们所有服务器与中央命令和控制服务器之间建立的 SSH 信任上运行。
问题是,这个脚本太乱了。Expect 命令试图解释任何 UNIX/Linux 机器上存在的“passwd”的所有可能版本 - 而且它们差别很大。
随着我们扩大和升级大量基础设施,脚本变得越来越难以管理。
我的问题是:有没有更好的方法可以做到这一点?假设已经建立了 SSH 信任,那么同时在 3000 多台服务器上更改 root 密码的最佳方法是什么?
答案1
使用木偶。
Puppet 非常灵活、易于维护并且使用 SSL。听起来可能有点过头了,你需要付出额外的努力才能建立 Puppet 系统。
但是。这很可能不是您对这些机器进行的最后一次大规模更新。当实际开始任何大规模更新程序时,Puppet 都会为您节省大量时间,并且脚本非常易读/可重用。
至少几年前对我来说,这种方法是有效的,而且我仍然能够重复使用一些 Puppet 配方(又称脚本)。我也在较小的环境中使用过它,只是确保每台机器实际上都有一个已知状态。
我已经多次证明(在许多公司),所有定制的部署脚本在一段时间后或当下一个人介入时都会变得令人头疼。只要你带着手机,旧脚本就会困扰你。
如果你觉得这听起来不错,这里有一个很棒的 Puppet 教程,包含虚拟环境帮助您入门。
答案2
我在 Solaris 上使用 Perl 模块 Authen::PAM 取得了巨大成功。以下是示例脚本:
#!/usr/bin/perl
use Authen::PAM;
my $username = 'root';
my $password = '1234567';
die qq{Error: Unknown user\n} unless getpwnam($username);
die qq{Error: You must run this as root.\n} unless ($> == 0);
my $pamh;
sub my_conv_func
{
my @res;
while ( @_ )
{
my $code = shift;
my $msg = shift;
my $ans = "";
if ($code == PAM_PROMPT_ECHO_OFF() )
{
if (($msg =~ /^New Password:/i) or ($msg =~ /^Re-enter new Password:/i))
{
$ans = $password;
}
else
{
die qq{Unknown message: $msg\n};
}
}
else
{
print qq{$msg\n};
}
push @res, (PAM_SUCCESS(), $ans);
}
push @res, PAM_SUCCESS();
return @res;
}
ref($pamh = new Authen::PAM("passwd", $username, \&my_conv_func)) || die "Error code $pamh during PAM init!";
my $res = $pamh->pam_chauthtok;
print $pamh->pam_strerror($res),"\n" unless $res == PAM_SUCCESS();
exit 0;
答案3
如果你能编写 Perl,那么模块网络::OpenSSH::并行允许轻松编写通过 SSH 在远程主机上并行执行操作的脚本。
它包含一个示例脚本用于更改可用作基础的密码。由于您似乎拥有一个异构环境,因此您希望按类型对主机进行分组,并为每个主机使用不同的对话处理子程序。
答案4
经过继续研究,我学到了一些东西......
首先,这是一项非常烦人的自动化任务,尤其是在许多不同的环境中。这个问题最正确的答案可能是@tomi 的:使用 Puppet。
最终我希望让 Puppet 来管理我们的基础设施,但现在部署到整个企业的 UNIX 服务器来更改 root 密码并不是一个可行的选择。
在阅读了大量手册页和大量的 Google-fu 之后,我设法想出了一个脚本,该脚本循环遍历目标服务器列表,打开 SSH 连接,并运行以下命令之一:
# Solaris
# Generate new pass via crypt(newpass,salt) and insert it into /etc/shadow
# AIX
$ echo "root:newpass" | chpasswd -f NOCHECK
# Linux
$ echo "newpass" | passwd root --stdin
# IBM VIO (Virtual I/O)
$ echo "echo \"padmin:newpass\" | chpasswd -f NOCHECK" | oem_setup_env
# IBM HMCs (Hardware Management Consoles)
$ chhmcusr -u hscroot -t passwd -v "newpass"
它的功能远不止运行那些命令,但上述命令才是发挥魔力的关键。
我找不到任何简单的方法来非迭代地更改 Solaris 上的密码 - 因此我们只能进行/etc/shadow
动态修改。