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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8236699/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 02:25:58  来源:igfitidea点击:

Script to change password on linux servers over ssh

linuxshellsshpasswords

提问by squashbuff

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 环境中有许多 Red Hat 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 --stdinor chpasswdcannot be used.

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

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?

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

采纳答案by Randy Katz

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):

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

回答by Dennis

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

回答by phatfingers

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 文件中注册他们的公钥。

回答by Gilles Quenot

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'

回答by salva

Can you use Perl?

你会用 Perl 吗?

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

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

If requires some Perl modules (Net::OpenSSH::Parallel, Expectand 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::ParallelExpect及其依赖项),但在远程服务器上不需要更改密码。

回答by Kris

Have you tried App::Unix::RPasswd

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

回答by squashbuff

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.

好的,我已经使用丹尼斯的建议整理了一个部分可行的解决方案。

servers.txt looks like:

server.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?

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

回答by Matt

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

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

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_pa​​sswd”是您从 /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 命令中转义那些(即“$”变成“\$”)。

回答by fsckin

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

以壁球爱好者的例子为基础,我尝试了以下方法,这对我来说效果很好:

#!/bin/bash
for server in `cat hostlist`; do
echo $server;
ssh username@$server 'passwd <<EOF
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.

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

回答by Edward Falk

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 密钥的安装是一个自动化过程。几乎没有人在任何机器上都有密码。