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

时间:2022-01-05 02:20:11

We have a number of Red Hat linux servers in our IT environment. I am being asked by my team members to write a script (preferably shell script) to change a user's password on each one of those in a single go, using SSH.

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

I have tried to find a solution but many of the scripts I found are using Expect. We do not have Expect installed on our servers and the system admins have refused to let us install it. Also, the users do not have root access so passwd --stdin or chpasswd cannot be used.

我试图找到一个解决方案,但我发现的许多脚本都使用Expect。我们不希望在服务器上安装,系统管理员也拒绝让我们安装。另外,wd用户没有根访问权限,因此无法使用passwd -stdin或chpasswd。

Is there any way a script can be written so that a user can run it and change the password of only his own user on all the servers in a list?

是否可以编写一个脚本,以便用户可以运行它,并在列表中的所有服务器上只修改自己用户的密码?

16 个解决方案

#1


17  

The remote machine(s) do not need expect installed. You can install expect on a local workstation or VM (virtualbox) or whichever *nix box, and write a wrapper that calls this .ex (expect) script (there may be small changes from distro to distro, this tested on CentOS 5/6):

远程机器不需要安装expect。您可以在本地工作站或VM (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

#2


12  

You do not need root access to use passwd.

您不需要root访问才能使用passwd。

This shoud work just fine.

这个应该没问题。

passwd <<EOF
old password
new password
new password
EOF

#3


10  

You should try pssh (parallel ssh at the same time).

您应该尝试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'

#4


6  

Building on squashbuff's example, I tried the following, which worked well for me:

以squashbuff为例,我尝试了以下方法,效果很好:

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

Security wise, Could be improved to take input without echoing to the screen OR saving the plaintext to disk.

在安全性方面,可以改进在不回显屏幕或将明文保存到磁盘的情况下接收输入。

#5


4  

echo "name:password" | chpasswd

#6


3  

Another possibility: change it manually on one server. Get the encrypted password out of /etc/shadow. Now, do something like this:

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

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

Of course, 'encrypted_passwd" is what you got out of /etc/shadow where you manually changed the password. And $HOST_LIST is a list of hosts where you want the password changed. That could be created simply with:

当然,“encrypted_passwd”是您从/etc/shadow获得的,您在其中手动更改密码。$HOST_LIST是要更改密码的主机列表。只要:

export HOST_LIST="server1 server2 server15 server67"

Or perhaps with a file (as others have suggested):

或者可能有一个文件(正如其他人建议的那样):

export HOST_LIST=`cat host_list.txt`

Where the file "host_list.txt" has a list of all the systems where you want the password changed.

文件”host_list。txt“有一个列表,列出了您希望修改密码的所有系统。

Edit: if your version of passwd doesn't support the -p option, you might have the 'usermod' program available. The example above remains the same, simply replace 'passwd' with 'usermod'.

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

Furthermore, you might consider the useful tool pdsh, which would simplify the above example to something like this:

此外,您可以考虑有用的工具pdsh,它可以将上述示例简化为以下内容:

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

One last "gotcha" to look out for: the encrypted password likely contains the dollar sign character ('$') as a field separator. You'll probably have to escape those in your for loop or pdsh command (i.e. "$" becomes "\$").

最后一个需要注意的问题是:加密密码可能包含美元符号字符('$')作为字段分隔符。您可能需要转义for循环或pdsh命令(例如。“$”变成了“美元\”)。

#7


2  

  1. Install sshpass on any of the server from where you want to execute the script.

    在希望执行脚本的任何服务器上安装sshpass。

    yum -y install sshpass
    
  2. Prepare a text file in which you have to pass details like Host, User Name, Password and Port. (Based on your requirement).

    准备一个文本文件,其中必须传递诸如主机、用户名、密码和端口等详细信息。(根据您的要求)。

    192.168.1.2|sachin|dddddd|22
    
  3. Prepare a script file using below details.

    准备一个脚本文件使用下面的细节。

    #!/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
    

#8


1  

An alternative you may want to present to your peers would be to have them use password-less authentication. They'd generate a public/private key pair and register their public key in the ~/.ssh/authorized_keys file on each of the servers they log into.

您可能希望向您的同行提供的另一种选择是让他们使用无密码的身份验证。它们将生成一个公钥/私钥对,并在~/中注册它们的公钥。ssh/authorized_keys文件在他们登录的每个服务器上。

#9


1  

Can you use Perl?

你可以使用Perl吗?

Here there is an script that changes the password in a set of hosts.

这里有一个脚本,可以在一组主机中更改密码。

If requires some Perl modules (Net::OpenSSH::Parallel, Expect and their dependencies) installed on the local machine running the script but nothing on the remote servers where the password has to be changed.

如果需要在运行脚本的本地机器上安装一些Perl模块(Net::OpenSSH::Parallel, Expect和它们的依赖项),那么在必须更改密码的远程服务器上就不需要安装任何Perl模块。

#10


1  

Have you tried App::Unix::RPasswd

你试过应用程序::Unix::RPasswd吗

#11


1  

The passmass script (man page) that comes with Expect doesn't require Expect to be installed on the remote machines.

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

#12


0  

Thought I should put my solution in an answer field - not sure if this should be a part of the question..

我想我应该把我的答案写在回答栏里——不确定这是不是问题的一部分。

OK, I have put together a partially working solution using Dennis' suggestion.

好的,我已经用Dennis的建议提出了一个部分可行的解决方案。

servers.txt looks like:

服务器。txt看起来像:

server1
server2
server3
.
.
.

I am using:

我用:

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

This produces:

这产生:

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.

So here, I still need to type my old password once for each server. Can this be avoided?

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

#13


0  

If you have ssh, why have passwords in the first place? Push the user's public ssh key to all the servers they're authorized to use and be done with it. This also lets you easily grant and revoke access all you want.

如果您有ssh,那么为什么首先要有密码呢?将用户的公共ssh密钥推到他们授权使用的所有服务器上,并将其完成。这还允许您轻松地授予和撤销访问权限。

At a previous $dayjob, where we had literally tens of thousands of servers, they had a database of which engineers were allowed on which servers, and the installation of ssh keys was an automated process. Almost NOBODY had a password on ANY machine.

在之前的$dayjob中,我们有成千上万的服务器,他们有一个数据库,允许工程师在其中使用服务器,ssh密钥的安装是一个自动的过程。几乎没有人在任何机器上有密码。

#14


0  

echo -e "wakka2\nwakka2\n" | passwd root

回波- wd "wakka2\nwakka2\n" | pass根源

#15


0  

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

if the password is encrypted, or

如果密码加密,或

cat /tmp/passwords | ssh $server sudo chpasswd

if the password is not encrypted.

如果密码没有加密。

/tmp/passwords should have format of "user:password"

/tmp/密码应具有“用户:密码”的格式

#16


-2  

The real question is why were they not using some sort of name services? NIS/Yellow Pages or LDAP and you're not having to manually change passwords across a bunch of servers. A user changes their password once and it's done across the domain master.

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

#1


17  

The remote machine(s) do not need expect installed. You can install expect on a local workstation or VM (virtualbox) or whichever *nix box, and write a wrapper that calls this .ex (expect) script (there may be small changes from distro to distro, this tested on CentOS 5/6):

远程机器不需要安装expect。您可以在本地工作站或VM (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

#2


12  

You do not need root access to use passwd.

您不需要root访问才能使用passwd。

This shoud work just fine.

这个应该没问题。

passwd <<EOF
old password
new password
new password
EOF

#3


10  

You should try pssh (parallel ssh at the same time).

您应该尝试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'

#4


6  

Building on squashbuff's example, I tried the following, which worked well for me:

以squashbuff为例,我尝试了以下方法,效果很好:

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

Security wise, Could be improved to take input without echoing to the screen OR saving the plaintext to disk.

在安全性方面,可以改进在不回显屏幕或将明文保存到磁盘的情况下接收输入。

#5


4  

echo "name:password" | chpasswd

#6


3  

Another possibility: change it manually on one server. Get the encrypted password out of /etc/shadow. Now, do something like this:

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

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

Of course, 'encrypted_passwd" is what you got out of /etc/shadow where you manually changed the password. And $HOST_LIST is a list of hosts where you want the password changed. That could be created simply with:

当然,“encrypted_passwd”是您从/etc/shadow获得的,您在其中手动更改密码。$HOST_LIST是要更改密码的主机列表。只要:

export HOST_LIST="server1 server2 server15 server67"

Or perhaps with a file (as others have suggested):

或者可能有一个文件(正如其他人建议的那样):

export HOST_LIST=`cat host_list.txt`

Where the file "host_list.txt" has a list of all the systems where you want the password changed.

文件”host_list。txt“有一个列表,列出了您希望修改密码的所有系统。

Edit: if your version of passwd doesn't support the -p option, you might have the 'usermod' program available. The example above remains the same, simply replace 'passwd' with 'usermod'.

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

Furthermore, you might consider the useful tool pdsh, which would simplify the above example to something like this:

此外,您可以考虑有用的工具pdsh,它可以将上述示例简化为以下内容:

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

One last "gotcha" to look out for: the encrypted password likely contains the dollar sign character ('$') as a field separator. You'll probably have to escape those in your for loop or pdsh command (i.e. "$" becomes "\$").

最后一个需要注意的问题是:加密密码可能包含美元符号字符('$')作为字段分隔符。您可能需要转义for循环或pdsh命令(例如。“$”变成了“美元\”)。

#7


2  

  1. Install sshpass on any of the server from where you want to execute the script.

    在希望执行脚本的任何服务器上安装sshpass。

    yum -y install sshpass
    
  2. Prepare a text file in which you have to pass details like Host, User Name, Password and Port. (Based on your requirement).

    准备一个文本文件,其中必须传递诸如主机、用户名、密码和端口等详细信息。(根据您的要求)。

    192.168.1.2|sachin|dddddd|22
    
  3. Prepare a script file using below details.

    准备一个脚本文件使用下面的细节。

    #!/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
    

#8


1  

An alternative you may want to present to your peers would be to have them use password-less authentication. They'd generate a public/private key pair and register their public key in the ~/.ssh/authorized_keys file on each of the servers they log into.

您可能希望向您的同行提供的另一种选择是让他们使用无密码的身份验证。它们将生成一个公钥/私钥对,并在~/中注册它们的公钥。ssh/authorized_keys文件在他们登录的每个服务器上。

#9


1  

Can you use Perl?

你可以使用Perl吗?

Here there is an script that changes the password in a set of hosts.

这里有一个脚本,可以在一组主机中更改密码。

If requires some Perl modules (Net::OpenSSH::Parallel, Expect and their dependencies) installed on the local machine running the script but nothing on the remote servers where the password has to be changed.

如果需要在运行脚本的本地机器上安装一些Perl模块(Net::OpenSSH::Parallel, Expect和它们的依赖项),那么在必须更改密码的远程服务器上就不需要安装任何Perl模块。

#10


1  

Have you tried App::Unix::RPasswd

你试过应用程序::Unix::RPasswd吗

#11


1  

The passmass script (man page) that comes with Expect doesn't require Expect to be installed on the remote machines.

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

#12


0  

Thought I should put my solution in an answer field - not sure if this should be a part of the question..

我想我应该把我的答案写在回答栏里——不确定这是不是问题的一部分。

OK, I have put together a partially working solution using Dennis' suggestion.

好的,我已经用Dennis的建议提出了一个部分可行的解决方案。

servers.txt looks like:

服务器。txt看起来像:

server1
server2
server3
.
.
.

I am using:

我用:

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

This produces:

这产生:

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.

So here, I still need to type my old password once for each server. Can this be avoided?

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

#13


0  

If you have ssh, why have passwords in the first place? Push the user's public ssh key to all the servers they're authorized to use and be done with it. This also lets you easily grant and revoke access all you want.

如果您有ssh,那么为什么首先要有密码呢?将用户的公共ssh密钥推到他们授权使用的所有服务器上,并将其完成。这还允许您轻松地授予和撤销访问权限。

At a previous $dayjob, where we had literally tens of thousands of servers, they had a database of which engineers were allowed on which servers, and the installation of ssh keys was an automated process. Almost NOBODY had a password on ANY machine.

在之前的$dayjob中,我们有成千上万的服务器,他们有一个数据库,允许工程师在其中使用服务器,ssh密钥的安装是一个自动的过程。几乎没有人在任何机器上有密码。

#14


0  

echo -e "wakka2\nwakka2\n" | passwd root

回波- wd "wakka2\nwakka2\n" | pass根源

#15


0  

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

if the password is encrypted, or

如果密码加密,或

cat /tmp/passwords | ssh $server sudo chpasswd

if the password is not encrypted.

如果密码没有加密。

/tmp/passwords should have format of "user:password"

/tmp/密码应具有“用户:密码”的格式

#16


-2  

The real question is why were they not using some sort of name services? NIS/Yellow Pages or LDAP and you're not having to manually change passwords across a bunch of servers. A user changes their password once and it's done across the domain master.

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