Script to take a list of hostnames to ssh into and run commands?

Windows 10 script (either PS or cmd) script to ssh into a list of hostnames (running centos) and run a few commands, then logout. Run through each hostname in list until it is done?

Is this possible?

Could do this in bash, if you've got Linux subsystem installed.

for host in $(cat $1)
do
    ssh $host echo "echo on remote host"
done

Script syntax looks like:

remoterun ~/hosts.txt

I don't really have knowledge of PS/cmd, but I'm not sure that it's easy to do because of the way PS and cmd are built. They feel really clunky to me.

1 Like

PowerShell was made to be as friendly to Linux and Bash users as possible. Many common Bash commands are aliased to the equivalent PowerShell commands. ls will list files in a directory for example. It's actual command is Get-Child (I hate this naming convention with a passion, but everything in PowerShell is done that way).

Here's an example of a script I use to convert files in Handbrake to another format:

$search = GCI $PSScriptRoot -Include *.mkv, *.mp4 -recurse -Exclude *_HEVC*;
$output = '';

If (!(Test-Path -Path ..\Uploading))
{
    New-Item -ItemType directory -Path ..\Uploading;
}

foreach ($file in $search)
{
	$newfilename = $file.BaseName + "_HEVC" + $file.Extension -replace ".mp4",".mkv";
	$newfile = $file.DirectoryName + "\" + $newfilename; 

	HandBrakeCLI.exe -P -e x265 --encoder-preset slow -x strong-intra-smoothing=0:rect=0 -q 16.0 --vfr --all-audio -E copy -B 160 --all-subtitles -i $file -o $newfile -f av_mkv;
}

So if you used that as a template, since all it does is get a list of paths using Get-Child, then runs a command using the information from that list of paths, you could easily do what you wanted.

First you need a list of host names or their IP addresses. If you can generate that into a text file, then you can just use that in place of a file listing.

An example:

$hosts = [System.IO.File]::OpenText("hosts.txt"); #hosts.txt is your text file; 
# needs to be in same location as where you are running this command from.
$output = ''; #Just stating the variable for logging purposes.

try{
    for() #Overall, this for repeats through the txt file running SSH commands on
    { #each host.
        $host = $hosts.ReadLine() #Uses ReadLine function to read 1 line
        if ($host -eq $null) { break } #If the line is equal to null, it breaks
        ssh $host <do other stuff> #Your SSH command to login
        <do more stuff> #Commands to run once SSH'd in
        <exit ssh session> #Exits the session.
    }
finally {
    $reader.Close() #Closes the reader safely. Something something open files and
} #data loss.

That's just a powershell script. @KenPC

A shorter way to do it:

$reader = [System.IO.File]::OpenText("hosts.txt") #Opens file for reading
while($null -ne ($host = $reader.ReadLine())) { #While line does not equal NULL
    ssh $host #ssh into host
    <do stuff> #do commands
    <exit ssh session> #exit ssh session
} #will repeat until NULL line is hit (end of file)

Just copy/paste that into a text file with the extension .ps1 and it should run using PowerShell.

If you want to run tests while editing it, definitely use PowerShell's ISE. https://msdn.microsoft.com/en-us/powershell/scripting/core-powershell/ise/introducing-the-windows-powershell-ise

It's built into Windows 10. Should come up alongside PowerShell if you search PowerShell.

1 Like

thanks! but i'm going to have to log into the machines using my account and elevate to su before doing the command I need to run on each box.

I have a sudo command I need to run on 50+ centos machines :frowning:

1 Like

At this point, you should really be using Ansible.

5 Likes

thanks, i'll have to look into that

1 Like

Another vote for Ansible. Article on running it with windows subsystem for linux: https://www.jeffgeerling.com/blog/2017/using-ansible-through-windows-10s-subsystem-linux

Another alternative is running a linux vm for Ansible. Seems heavy, but worth it in the long run.

1 Like

Yeah, with that many machines, the only way to efficiently manage them is via something along the lines of this. Ansible is agentless, but chef has better file-consistency management.

All in all, I'd go with Ansible and just stick through the learning curve.

I actually have all of them connected to a spacewalk server i built, but in order to enable the remote command feature, all of the clients had to have that feature enabled. which required a command ran as su.

I ended up logging into all of them and doing it manually. Carpal tunnel should be coming soon. lol. I was just looking for a quick dirty way to do it quicker.

I can run bulk remote commands now all at once. Thanks anyways huys. I'll still be looking at ansible

Oh, lol that would explain a lot.

I would just go ahead and start manually SSHing or set up key exchange with your local user and run a script.