2011-11-23 156 views
17

我们的IT环境中有许多Red Hat Linux服务器。我的团队成员要求我写一个脚本(最好是shell脚本),以便使用SSH在单步执行中更改每个用户的密码。通过ssh在Linux服务器上更改密码的脚本

我试图找到一个解决方案,但我发现许多脚本都使用Expect。我们的服务器上没有安装Expect,系统管理员拒绝让我们安装它。另外,用户没有root权限,因此无法使用passwd --stdinchpasswd

是否有任何方式可以编写脚本,以便用户可以在列表中的所有服务器上运行并更改他自己的用户的密码?

+1

更改系统管理员? – TLP

+0

不幸的是没有一个选项.. :) – squashbuff

回答

16

远程机器不需要安装。您可以在本地工作站或虚拟机(virtualbox)或任何* nix盒子上安装期望,并编写一个调用此.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 
+0

使用此代码,你会想让这段代码类似./passwdWrapper,然后在你的bash文件中添加 ./passwdWrap $ user $ password $ server $ newpassword – Loren

11

你不需要root权限就可以使用passwd

这应该工作得很好。

passwd <<EOF 
old password 
new password 
new password 
EOF 
+0

谢谢丹尼斯,根据您的文章,密码一旦用户登录到所需的服务器,效果很好。但是,我有一个存储在servers.txt文件中的服务器列表,我想运行一个脚本,提供一次旧密码和新密码,然后该脚本应该在该列表中的所有服务器上更改我的密码。有什么想法呢? – squashbuff

+1

'ssh user @ server'command to change password''就是这样做的。 – Dennis

+0

谢谢丹尼斯,我已经对我的问题进行了编辑,显示了我所尝试的内容。目前还没有,但这是一个好的开始。谢谢.. :) – squashbuff

1

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

+0

谢谢,我已经使用公钥/私钥进行身份验证,但即使使用无密码身份验证,当密码在2个月后过期(在我的情况下),我仍然必须登录到每个服务器,使用“passwd”键入旧密码并输入两次新密码。这有点低效。这就是为什么我试图把这个解决方案放在一起。 – squashbuff

+0

优秀。这简化了事情。 – phatfingers

+0

你可能在这些服务器上有sudo,对吧?如果您向脚本授予sudo权限以更改其密码,则该脚本可以使用--stdin参数为其帐户运行passwd。 – phatfingers

9

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

cat>~/ssh-hosts<<EOF 
[email protected] 
[email protected] 
[email protected] 
EOF 

pssh -h ~/pssh-hosts 'printf "%s\n" old_pass new_pass new_pass | passwd' 
+0

谢谢,这可能是一个很好的解决方案,但是我们的服务器上也没有pssh .... :( – squashbuff

+0

)您可以在任何发行版本上运行此命令,例如Android设备,笔记本电脑和桌面。安装它在客户端,只需要ssh作为服务器端,我没有问题;)你可以迭代太简单需要一个for循环:for i in foo bar base;做ssh“$ i”“命令行”;完成 –

+0

有趣的是,我一定会考虑它。谢谢:) – squashbuff

1

您可以使用Perl吗?

Here有一个脚本可以更改一组主机中的密码。

如果需要一些Perl模块安装在运行远程服务器,其中的密码对剧本,但没有在本地机器上(Net::OpenSSH::ParallelExpect及其相关性)被改变。

+0

这可能对一些人有用。这是环境设置的特殊方式,限制了我使用这种解决方案。我无法直接从我的客户机访问这些服务器。我必须登录到停用端口转发的端口。所以脚本需要运行在jumphost上,它具有所有这些限制。谢谢你的信息。 – squashbuff

+0

@squashbuff:我目前正在研究另一个Perl模块[Net :: OpenSSH :: Gateway](https:// github。com/salva/p5-Net-OpenSSH-Gateway)允许[Net :: OpenSSH](http://search.cpan.org/perldoc?Net::OpenSSH)透明地跳过网关,但它仍然是一项工作进行中。 – salva

0

想我应该把我的解决方案在回答现场 - 不知道这应该是问题的一部分..

OK,我已经把部分工作的解决方案使用丹尼斯的建议。

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 

这将产生:

[email protected]'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. 
[email protected]'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. 

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

+0

您是否曾经找到避免为每台服务器输入一次旧密码的方法? – Lizz

+1

@Lizz我结束了使用expect。不是安全方面的理想解决方案,但必须尽快完成。查看Randy Katz接受的答案。 – squashbuff

3

另一种可能性:在一台服务器上手动更改它。从/ 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'程序可用。上面的例子保持不变,只需将'passwd'替换为'usermod'即可。

此外,你可以考虑useful tool pdsh,这将简化上述例子是这样的:

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

最后一个“疑难杂症”看出来的:加密的密码可能包含美元符号( '$')作为字段分隔符。您可能必须在for循环或pdsh命令中将其转义(即“$”变为“\ $”)。在squashbuff的例子

+1

对于passwd-0.77-4.el6(Enterprise Linux 6)或passwd-0.79-2.fc20(Fedora 20),没有'-p'选项。 –

+1

看看'usermod'程序...在CentOS(克隆RHEL)5.x和6.x上,它支持-p选项。我编辑了我的回复以包含更多细节。 – Matt

+0

工作对我很好。只是为了澄清:您必须转义您的encrypted_pa​​sswd中的所有$字符,而不是第一个。 – lobi

5

大厦,我尝试以下,这对我来说效果很好:

#!/bin/bash 
for server in `cat hostlist`; do 
echo $server; 
ssh [email protected]$server 'passwd <&ltEOF 
old_password 
new_password 
new_password 
EOF'; 
done

安全明智的,可以提高取输入,而不回显到屏幕或保存明文到磁盘。

0

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

在之前的$ dayjob中,我们拥有数万台服务器,他们拥有一个数据库,哪个工程师可以在哪台服务器上运行,并且ssh密钥的安装是一个自动化过程。几乎NOBODY在任何机器上都有密码。

+1

谢谢爱德华,但是基础设施管理已经外包,我在做出这些决定时没有任何发言权。我必须在不做大规模的基础设施变更的情况下完成此项工这不是一个选项。 – squashbuff

4
echo "name:password" | chpasswd 
+2

问题提到'chpasswd'不能使用。 –

2
  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 [email protected]$HOST \ 
          -T "echo '[email protected]' | passwd --stdin root"     \ 
          < /dev/null | tee -a output.log 
    done 
    
    exec 0<&3 
    
+0

如果有人运行'ps',密码是否可见? –

0

回声-e “wakka2 \ nwakka2 \ n” | passwd root

1

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

-2

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

+0

我在目前的环境中工作,已经有了限制。我不是域管理员,我没有发言权来解决您的解决方案所需的体系结构更改。我正在为像我这样的终端用户在同一个限制性环境中一起提供解决方案。 – squashbuff

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

如果密码被加密,或

cat /tmp/passwords | ssh $server sudo chpasswd 

如果密码没有被加密。

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

+0

正如问题中提到的,用户没有root权限。所以'sudo chpasswd'不能使用。说实话,如果系统管理员允许用户运行'sudo chpasswd',那么在我看来这是一个很大的安全问题。 – squashbuff

相关问题