简体   繁体   English

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

[英]Script to change password on linux servers over ssh

We have a number of Red Hat linux servers in our IT environment.我们的 IT 环境中有许多 Red Hat linux 服务器。 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.我的团队成员要求我编写一个脚本(最好是 shell 脚本),以使用 SSH 一次性更改每个用户的密码。

I have tried to find a solution but many of the scripts I found are using Expect.我试图找到解决方案,但我发现的许多脚本都在使用 Expect。 We do not have Expect installed on our servers and the system admins have refused to let us install it.我们的服务器上没有安装 Expect,系统管理员拒绝让我们安装它。 Also, the users do not have root access so passwd --stdin or chpasswd cannot be used.此外,用户没有 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?有什么方法可以编写脚本,以便用户可以运行它并在列表中的所有服务器上仅更改自己用户的密码?

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

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

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'

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 <&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.安全方面,可以改进以在不回显到屏幕或将明文保存到磁盘的情况下进行输入。

echo "name:password" | chpasswd

Another possibility: change it manually on one server.另一种可能性:在一台服务器上手动更改它。 Get the encrypted password out of /etc/shadow.从 /etc/shadow 中获取加密密码。 Now, do something like this:现在,做这样的事情:

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.编辑:如果您的 passwd 版本不支持 -p 选项,您可能有可用的“usermod”程序。 The example above remains the same, simply replace 'passwd' with '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 (ie "$" becomes "\\$").您可能必须在 for 循环或 pdsh 命令中转义那些(即“$”变成“\\$”)。

  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

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

I just implemented a small tool that changes password for many users/hosts at once.我刚刚实现了一个小工具,可以一次更改许多用户/主机的密码。 It's java based application so it works on both Windows and Linux.它是基于 Java 的应用程序,因此它适用于 Windows 和 Linux。 It's free, enjoy :)它是免费的,享受:)

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

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::ParallelExpect及其依赖项),但在远程服务器上不需要更改密码。

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

If you have ssh, why have passwords in the first place?如果你有 ssh,为什么首先要有密码? Push the user's public ssh key to all the servers they're authorized to use and be done with it.将用户的公共 ssh 密钥推送到他们有权使用的所有服务器并完成使用。 This also lets you easily grant and revoke access all you want.这也让您可以轻松地授予和撤消您想要的所有访问权限。

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.在之前的 $dayjob 中,我们实际上拥有数万台服务器,他们有一个数据库,其中允许工程师使用哪些服务器,并且 ssh 密钥的安装是一个自动化过程。 Almost NOBODY had a password on ANY machine.几乎没有人在任何机器上都有密码。

echo -e "wakka2\\nwakka2\\n" | echo -e "wakka2\\nwakka2\\n" | passwd root密码根

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/passwords 的格式应该是“user:password”

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?这可以避免吗?

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. NIS/黄页或 LDAP,您不必在一堆服务器上手动更改密码。 A user changes their password once and it's done across the domain master.用户更改密码一次,并在域主机上完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM