通过ssh在Linux服务器上更改密码的脚本

我们的IT环境中有许多红帽Linux服务器。 我的团队成员要求我写一个脚本(最好是shell脚本),使用SSH一次性更改用户的密码

我试图find一个解决scheme,但我发现许多脚本都使用Expect。 我们的服务器上没有安装Expect,系统pipe理员拒绝让我们安装它。 另外,用户没有root访问权限,因此passwd --stdinchpasswd不能使用。

有什么方法可以编写脚本,以便用户可以在列表中的所有服务器上运行并更改只有他自己的用户的密码?

远程机器不需要安装。 您可以在本地工作站或虚拟机(virtualbox)或任何一个* nix盒子上安装expect,然后编写一个叫做.ex(expect)脚本的包装器(可能会有一些从发行版到发行版的变化,在CentOS 5/6上测试过):

 #!/usr/bin/expect -f # wrapper to make passwd(1) be non-interactive # username is passed as 1st arg, passwd as 2nd set username [lindex $argv 0] set password [lindex $argv 1] set serverid [lindex $argv 2] set newpassword [lindex $argv 3] spawn ssh $serverid passwd expect "assword:" send "$password\r" expect "UNIX password:" send "$password\r" expect "password:" send "$newpassword\r" expect "password:" send "$newpassword\r" expect eof 

你不需要root权限来使用passwd

这应该工作得很好。

 passwd <<EOF old password new password new password EOF 

你应该尝试pssh (并行ssh在同一时间)。

 cat>~/ssh-hosts<<EOF user100@host-foo user200@host-bar user848@host-qux EOF pssh -h ~/pssh-hosts 'printf "%s\n" old_pass new_pass new_pass | passwd' 

以squashbuff的例子为基础,我尝试了以下的方法,对我来说效果很好:

  #!/斌/庆典
对于`cat hostlist`中的服务器; 做
 echo $ server;
 ssh username @ $ server'passwd <&ltOF
旧密码
新密码
新密码
 EOF“;
 DONE 

安全明智,可以改善输入而不回显屏幕或将明文保存到磁盘。

 echo "name:password" | chpasswd 

另一种可能性:在一台服务器上手动更改。 从/ etc / shadow获取加密的密码。 现在,做这样的事情:

 for host in $HOST_LIST; do ssh $host "passwd -p 'encrypted_passwd' user" done 

当然,'encrypted_pa​​sswd'是你从/ etc / shadow中得到的,你手动修改密码的地方,$ HOST_LIST是你想更改密码的主机列表,可以用下面的方法创建:

 export HOST_LIST="server1 server2 server15 server67" 

或者也许用一个文件(如其他人所建议的):

 export HOST_LIST=`cat host_list.txt` 

其中文件“host_list.txt”包含您想要更改密码的所有系统的列表。

编辑:如果你的passwd版本不支持-p选项,你可能有'usermod'程序可用。 上面的例子保持不变,只需用“usermod”替换“passwd”即可。

此外,你可能会考虑有用的工具pdsh ,这将简化上面的例子是这样的:

 echo $HOST_LIST | pdsh -Rssh -w- "usermod -p 'encrypted_passwd' user" 

最后一个“gotcha”要注意:加密的密码可能包含美元符号字符('$')作为字段分隔符。 你可能不得不在你的for循环或pdsh命令中(即“$”变成“\ $”)。

  1. 在要执行脚本的任何服务器上安装sshpass

     yum -y install sshpass 
  2. 准备一个文本文件,在这个文件中你必须传递主机用户名密码端口等详细信息。 (根据您的要求)。

     192.168.1.2|sachin|dddddd|22 
  3. 使用以下细节准备脚本文件。

     #!/bin/bash FILE=/tmp/ipaddress.txt Myserver="" MyUser="" MyPassword="" MyPort="" exec 3<&0 exec 0<$FILE while read line do Myserver=$(echo $line | cut -d'|' -f1) MyUser=$(echo $line | cut -d'|' -f2) MyPassword=$(echo $line | cut -d'|' -f3) MyPort=$(echo $line | cut -d'|' -f4) HOST=$Myserver USR=$MyUser PASS=$MyPassword sshpass -p $PASS ssh -p $MyPort -o StrictHostKeychecking=no $USR@$HOST \ -T "echo 'sachin@patel' | passwd --stdin root" \ < /dev/null | tee -a output.log done exec 0<&3 

您可能希望向同事展示的替代方案是让他们使用无密码身份验证。 他们会生成一个公钥/私钥对,并将其公钥登录到每个服务器上的〜/ .ssh / authorized_keys文件中。

你可以使用Perl吗?

这里有一个脚本来改变一组主机的密码。

如果需要在运行脚本的本地机器上安装一些Perl模块( Net :: OpenSSH :: Parallel , Expect及其依赖项),但是在需要更改密码的远程服务器上则不需要。

你有没有尝试过App :: Unix :: RPasswd

Expect附带的passmass脚本( 手册页 )不需要在远程机器上安装Expect。

以为我应该把我的解决方案放在答案领域 – 不知道这是否应该是问题的一部分。

好的,我已经用丹尼斯的建议组建了一个部分有效的解决方案。

servers.txt看起来像:

 server1 server2 server3 . . . 

我在用:

 for server in `cat servers.txt`; do ssh $server -l user 'passwd <<EOF old_pass new_pass new_pass EOF'; done 

这产生:

 user@server1's password: **<Type password manually>** (current) UNIX password: New UNIX password: Retype new UNIX password: Changing password for user user. Changing password for user passwd: all authentication tokens updated successfully. user@server2's password: **<Type password manually>** (current) UNIX password: New UNIX password: Retype new UNIX password: Changing password for user user. Changing password for user passwd: all authentication tokens updated successfully. 

所以在这里,我仍然需要输入一次每个服务器的旧密码。 这可以避免吗?

如果你有ssh,为什么要把密码放在第一位呢? 将用户的公用ssh密钥推送到他们有权使用的所有服务器,并完成它。 这也可以让你轻松授予和撤销访问所有你想要的。

在前一个$ dayjob,我们有成千上万的服务器,他们有一个数据库,允许哪些工程师在哪个服务器上,并且安装ssh密钥是一个自动化的过程。 几乎NOBODY在任何机器上都有密码。

echo -e“wakka2 \ nwakka2 \ n”| passwd根

 cat /tmp/passwords | ssh $server sudo chpasswd -e 

如果密码是加密的,或者

 cat /tmp/passwords | ssh $server sudo chpasswd 

如果密码未加密。

/ tmp /密码的格式应该是“user:password”

真正的问题是为什么他们不使用某种名称服务? NIS /黄页或LDAP,你不必手动更改一堆服务器的密码。 用户只需更改一次密码,然后在域主服务器上完成。