A script to change password for all other servers

Hey Gurus,

I have this requirement to change the password for other servers remotely from one server. So, I installed public keys on all servers and wrote the following script to do the job. Something appears to be wrong with my loop, as it only changes one server and ignores the rest. I'm testing the script with a test data file with about 5 servers in it. The data file is the command-line argument to the script. Can you please tell me what's wrong and how to fix it?

As always, I truly appreciate this community effort. You guys are truly awesome; thank you very much.

#!/bin/bash
##data file name is passed in as argument to .sh script
filename="$1"
while  read -r line
do
        ##newPassword and username are placeholders
        ssh $line 'echo -e "TestPW\nTestPW" | passwd SomeUser'
done < "$filename"

Hi,

I think that this behaviour is being caused by the use of a 'while read' loop to drive the 'ssh' command. The way input is read in and processed in this particular script may not actually be what you'd expect. Instead of it looping nicely around, the entirety of your arguments end up being passed to 'ssh' in one glob, and it's just doing the first one.

Maybe try a 'for' loop instead ? So something like:

##data file name is passed in as argument to .sh script
filename="$1"
for server in `cat $1`
do
        ##newPassword and username are placeholders
        ssh $server 'echo -e "TestPW\nTestPW" | passwd SomeUser'
done

See if that works, and let us know how you get on.

1 Like

maybe -n option for ssh is missing as its a script... Otherwise ssh is tempted to read StdIN which here is void...

1 Like

@drysdalk, I copied and pasted your version, it just hangs, I never get the prompt back.

@vbe, it does work just the way it is, but it only processes one server and not all in the list.

Thanks guys.

Hi,

(Edit)

Just checking, but are you running it with the filename as an argument ? e.g. ./script.sh serverlist.txt or something like that ? The script takes the first argument ($1) as the filename to be read and processed.

I ask becasue if you were just running ./script.sh on its own will never return a prompt, which is what you describe. In that usage case it would be sitting waiting for you to type in the input yourself, and would only proceed with execution after you did a Ctrl-D or otherwise indicated the end of input.

It's also possible of course that the issue is with the ssh or passwd parts of the script now as well. You may need different flags to passwd, something like passwd --stdin on a Red Hat-style system.

1 Like

Yeah, I'm running it exactly like that,

root@testserver1# ./pwchange.sh pwchange.dat

and my pwchange.dat is formatted as follows:

server1
server2
server3
server4
server5

With the while loop, it did read the pwchange.dat file, but it only changed the password for one server. And I got the prompt back.
With the for loop, ctrl-D does nothing, but ctrl-C breaks out of the script and give me the prompt back w/o doing anything.

Also, my environment is a mix of Solaris 10 and Linux (RHEL & SUSE). My script with the while loop does change one password, it changes either Solaris or Linux server. So, looks like the ssh & passwd commands are both OK.

So you havent tried ssh -n ... as I said ssh will read the first line but then it will expect things to coem from standard input unless you specify -n option

Hello,

OK, thanks for the feedback. If you try running it with the '-x' flag to Bash, which will make it show you each step as it executes, where does it hang ? So you'd want to run bash -x ./pwchange.sh pwchange.dat and see the line it's freezing on.

1 Like

@vbe, thanks for the follow up. ssh -n hangs too. but, here is something interesting though. When I comment out all the servers except one in the .dat file, this is what I get:

root@tstnglbz1 # ./pwchange.sh pwchange.dat
ssh: #dr-prdcatap1: temporary name resolution failure
ssh: #munsbxlinux1: temporary name resolution failure
ssh: #munsbxlinux2: temporary name resolution failure
New password: Retype new password: Changing password for user mchavoshi.
passwd: all authentication tokens updated successfully.

So, ssh is tried for each server, but it fails name resolution because obviously it doesn't know what to do with #, but it does attempt all of them and it does change that one server who is not commented out correctly. STRANGE! But, when I uncomment all the servers in the .dat file, then it hangs.

BTW, in this instance my .dat file looked like the following:

#dr-prdcatap1
#munsbxlinux1
#munsbxlinux2
munsbxlinux3

---------- Post updated at 02:52 PM ---------- Previous update was at 02:48 PM ----------

root@tstnglbz1 # bash -x ./pwchange.sh pwchange.dat
+ filename=pwchange.dat
++ cat pwchange.dat
+ for server in '`cat $1`'
+ ssh -n dr-prdcatap1 'echo -e "TestPW12345!\nTestPW12345!" | passwd mchavoshi'

Hi,

That at least is easy to explain. You can't really 'comment out' input. So what is happening is that 'ssh' is attempting to connect to the hosts whose names start with a hash symbol, and DNS resolution is failing for what are invalid hostnames. If you want them not to be considered by the script, you'd have to remove them entirely. Commenting out only works in scripts, and not in the input files handled by scripts (unless you yourself write the appropriate code to handle that).

In terms of the part of the script that is hanging, it does seem it's something to do with the actual core 'passwd' section itself. Before digging any further: if you manually try to run echo -e "TestPW12345!\nTestPW12345!" | passwd mchavoshi on the target server yourself at a Bash prompt, and not as part of a script, does it actually work, or does it hang even when you run it yourself ?

1 Like

that command by itself on the command line works perfect. Please see below:

root@tstnglbz1 # ssh -n munsbxlinux3 'echo -e "TestPW12345!\nTestPW12345!" | passwd mcha>
New password: Retype new password: Changing password for user mchavoshi.
passwd: all authentication tokens updated successfully.
root@tstnglbz1 #

Hi,

OK, thanks. And it works on all four servers if done manually, and not just munsbxlinux3 ?

1 Like

My shift ended an hour ago. I will test all 4 servers tomorrow and will let you know. Thanks so much for your assistance. Have a good evening.

Id guess that passwd is refusing to take input from a non-terminal.

On *nix servers I find usermod(8) to be much more reliable for this sort of thing e.g.:

#!/bin/bash
##data file name is passed in as argument to .sh script
filename="$1"
crypt_pass=$(openssl passwd "TestPW")
for server in $(cat "$filename")
do
        ##newPassword and username are placeholders
        ssh $server usermod -p "$crypt_pass" SomeUser
done

Note: if you use openssl passwd (i.e. no password on the command line).
It will prompt on the terminal for password and a verification which is preferable to hard-coding it in the script as it won't be visible to utilities like ps

1 Like

Is the chpasswd utility available on your system? man chpasswd :

1 Like

@Rudic, as previously stated, there is nothing wrong with the way it changes the password. There is something wrong with the loop. Everything the way it is, correctly changes one password for one server, but it doesn't catch the rest of the servers.

---------- Post updated at 10:00 AM ---------- Previous update was at 09:44 AM ----------

Well, good thinking, NO, when I ran the command by itself on the command line, giving it the server name manually, it hung for Solaris 10 box (prdcatap1).

prdcatap1: Solaris 10
munsbxlinux1: SUSE 11.4
munsbxlinux2: RHEL 6.7
munsbxlinux3: RHEL 7.2

root@tstnglbz1 # ssh -n dr-prdcatap1 'echo -e "TestPW12345!\nTestPW12345!" | passwd mcha>
root@tstnglbz1 # ssh -n munsbxlinux1 'echo -e "TestPW12345!\nTestPW12345!" | passwd mcha>
New password: BAD PASSWORD: it is too simplistic/systematic
Retype new password: Changing password for mchavoshi.
Password has been already used.
Password changed.
root@tstnglbz1 # ssh -n munsbxlinux2 'echo -e "TestPW12345!\nTestPW12345!" | passwd mcha>
New password: BAD PASSWORD: it is too simplistic/systematic
Retype new password: Changing password for user mchavoshi.
passwd: all authentication tokens updated successfully.
root@tstnglbz1 # ssh -n munsbxlinux3 'echo -e "TestPW12345!\nTestPW12345!" | passwd mcha>
New password: Retype new password: Changing password for user mchavoshi.
passwd: all authentication tokens updated successfully.

Hi,

Good to know that the problem is now identified and that you have a working solution for the Linux systems, at least. As for the Solaris one, you'll most likely have to find an alternative way of re-setting the password for that one host, or find one other common method that works across all platforms. The 'chpasswd' and 'usermod' ideas mentioned by RudiC and Chubler_XL would certainly be the best place to start.

I don't readily have access to a Solaris system to test things on myself just now, but will have a play about this evening if I can if you're still in need of an answer then.

1 Like

OK guys, thanks so much @drysdalk for your excellent trouble shooting idea (running every command individually on the command line). The script works perfect, the way it is, it only hangs on stupid Solaris and since the Solaris box was on the top of the data file, it would hang on it and not go further. I removed the Solaris box from my data file and everything ran just fine. Please see below. I guess the problem now gets reduced to how to do this **** on Solaris?
Thanks, everyone, you guys are great.

 root@tstnglbz1 # ./pwchange.sh pwchange.dat
New password: BAD PASSWORD: it is too simplistic/systematic
Retype new password: Changing password for mchavoshi.
Password has been already used.
Password changed.
New password: BAD PASSWORD: it is too simplistic/systematic
Retype new password: Changing password for user mchavoshi.
passwd: all authentication tokens updated successfully.
New password: Retype new password: Changing password for user mchavoshi.
passwd: all authentication tokens updated successfully.
root@tstnglbz1 #

---------- Post updated at 11:17 AM ---------- Previous update was at 10:11 AM ----------

So, apparently (as far as I can tell) Solaris doesn't have the chpasswd command and doesn't support "usermod -w" switch to change passwords non-interactively. Strange, but true (again, as far as I can tell).

Hi,

I've looked into this a bit further, although I don't myself have a full Oracle Solaris system to test on; rather, at home I have a system running Tribblix, an Illumos distro. So there will certainly be some differences beween that and Oracle's Solaris, which I can't really legitimately run for free at the moment due to the licensing requirements it has.

Anyway, I tend to agree that based on both my own findings on my system and what I've read elsewhere that you're going to have to find a more complicated solution here. An expect script might be the kind of road you have to go down, or a Perl script or somesuch. As an absolute last resort you could do something that directly manipulates /etc/passwd and /etc/shadow , but I can't stress how strongly enough I recommend not doing that.

1 Like

Apparently, Solaris & Linux are a lot different and NOT just a little. I couldn't get the simple scp command to work on Solaris and it worked perfectly on all flavors of Linux.

scp -r tstnglbz1:/export/home/mchavoshi/bin

.