Script
Name | Description | Last Modified Date | Download |
---|
SPManage.ps1 | Remote SharePoint Farm Management | 22/07/2012 | SPManage.ps1 |
How it works
The script connects to the local farm and identifies each server. Â Alternatively servers can be loaded from a configuration file.
Commands can then be issued on each server automatically via a remote power shell session. Â Commands are either built in as switches or you can execute your own commands using the -Command switch.
Note: PowerShell Remoting is a technology that allows for remote administration of computers. Â Using it has security implications which should be considered before enabling. Â Please consult additional sources if you are not sure about appropriate security measures when using PowerShell Remoting.
Script Help PS > .\SPManage.ps1 -Help
SPManage v1.1 - Script Help
This script uses powershell remoting which must be enabled on the servers
Parameters:
-ServerType ('All', 'APP', 'WFE' - Default is ALL) This is only usable if you are on a local SP 2010 Farm otherwise use -configFile
-UserName (If on a different domain or if you require a different user account set this value eg; MyDomain\MyUser
-Password (The password if specifying a UserName)
-Command (An optional command to execute remotely. eg; {Get-Process})
-ConfigFile (An xml file that contains a list of servers)
-Credential (Pass in Get-Credential if you don't want to type in a plain text password)
-Ping (ICMP echo executed to all servers)
-VerifyRemoting (Creates a remote session to confirm remoting is available)
-QueryDiskSpace (Enumerates logical drives on each server)
-QueryWebApps (Enumerates SP2010 Web Applications and Application Pools (Local Query))
-QueryFarm (Enumerates servers within the SP2010 farm (Local Query))
-RestartSPServices (Restarts all SP2010 Services including User Code Host. Security note: If you don't want user code host running do not call this command.)
-StopSPServices (Stops all SP2010 Services including User Code Host and Search.
-StartSPServices (Starts all SP2010 Services including User Code Host. Security note: If you don't want user code host running do not call this command.)
-IISReset (Runs IISReset on all servers)
-ClearSessions (Clears any existing remote sessions with the servers - not normally needed as script cleans up)
-NoSP (If the command being issued does not require the SharePoint snappin, use this switch to improve performance)
-Silent (Don't prompt for Un Safe Commands)
-Help (This output)
Server configuration:
Each server in the farm must allow PS Remoting.
run: winrm quickconfig (This will allow remote management on HTTP)
run: winrm quickconfig -transport:SSL (This will allow remote management on HTTPS)
run: winrm s winrm/config/client '@{TrustedHosts="RemoteComputer"}' (Adds a trusted computer to the server config)
Cross Domain:
If your client computer is on another domain, you may need to run an additional command on the remote server(s) to allow.
run:
New-Itemproperty -name LocalAccountTokenFilterPolicy -path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -propertyType DWord -value 1
(This will allow the remote computer to be controlled from a machine on another domain)
Examples:
.\SPManage.ps1 -Ping #Simple ping test
.\SPManage.ps1 -VerifyRemoting #Creates a remote session on each server
.\SPManage.ps1 -ServerType:App -VerifyRemoting #Creates a remote session on each Application server
.\SPManage.ps1 -UserName "DOM\User" -Password "MyPass" -VerifyRemoting #Uses a username and password to connect to the remote servers
.\SPManage.ps1 -configFile devfarm.xml -Credential (Get-Credential) -VerifyRemoting #Uses a config file to connect to servers
.\SPManage.ps1 -Command {get-process} #Gets the running processes for all servers in the farm
.\SPManage.ps1 -IISReset #Issues IISReset using remote powershell session
.\SPManage.ps1 -RestartSPServices #Restarts all SP2010 Services on each server
.\SPManage.ps1 -ServerType App -RestartSPServices #Restarts all SP2010 Services on the application servers
Notes:
Sessions are cleaned up at the end of the script.
If a session already exists with the remote computer the script will attempt to use it.
You don't need to specify a username and password if your account has correct permissions
This script must be run from an elevated PowerShell session.
Be aware of the double hop issue when trying to execute SharePoint commands remotely. If the database is not on the same server the call will fail.
Example Config File (For use when you are not running on a server in the SP Farm. Specify -configFile parameter)
<?xml version="1.0" ?>
<Config>
<Servers>
<Server Address="SPSERVER01" />
<Server Address="SPSERVER02" />
</Servers>
</Config>
Â
SPManage.ps1
Download Script:Â SPManage.ps1
#SharePoint Farm management script
#Written By: Tim Wheeler (https://codemonkeysoftware.atlassian.net)
#.\SPManage.ps1 -Help (for information on this script)
param (
[Parameter(Position=0)]
[ValidateSet('All','APP','WFE')]
[System.String]$ServerType = "All",
$Command,
$UserName,
$Password,
$configFile,
$Credential,
[switch] $Ping,
[switch] $IISReset,
[switch] $ClearSessions,
[switch] $QueryDiskSpace,
[switch] $RestartSPServices,
[switch] $StopSPServices,
[switch] $StartSPServices,
[switch] $VerifyRemoting,
[switch] $NoSP,
[switch] $Silent,
[switch] $QueryFarm,
[switch] $QueryWebApps,
[switch] $Help
)
if($userName -ne $null)
{
$plainTextPassword = $Password
$secureStringPassword = ConvertTo-SecureString $plainTextPassword -AsPlainText -force
$Credential = New-Object System.Management.Automation.PSCredential ($UserName, $secureStringPassword)
}
$version = "1.1"
#region Help and Feedback
function Message([string] $computerName, $message)
{
Write-Host "$computerName : $message"
}
function Help()
{
Write-Host
Write-Host ("SPManage v" + $version +" - Script Help")
Write-Host
Write-Host "This script uses powershell remoting which must be enabled on the servers"
Write-Host ""
Write-Host "Parameters:"
Write-Host " -ServerType ('All', 'APP', 'WFE' - Default is ALL) This is only usable if you are on a local SP 2010 Farm otherwise use -configFile"
Write-Host " -UserName (If on a different domain or if you require a different user account set this value eg; MyDomain\MyUser"
Write-Host " -Password (The password if specifying a UserName)"
Write-Host " -Command (An optional command to execute remotely. eg; {Get-Process})"
Write-Host " -ConfigFile (An xml file that contains a list of servers)"
Write-Host " -Credential (Pass in Get-Credential if you don't want to type in a plain text password)"
Write-Host " -Ping (ICMP echo executed to all servers)"
Write-Host " -VerifyRemoting (Creates a remote session to confirm remoting is available)"
Write-Host " -QueryDiskSpace (Enumerates logical drives on each server)"
Write-Host " -QueryWebApps (Enumerates SP2010 Web Applications and Application Pools (Local Query))"
Write-Host " -QueryFarm (Enumerates servers within the SP2010 farm (Local Query))"
Write-Host " -RestartSPServices (Restarts all SP2010 Services including User Code Host. Security note: If you don't want user code host running do not call this command.)"
Write-Host " -StopSPServices (Stops all SP2010 Services including User Code Host and Search."
Write-Host " -StartSPServices (Starts all SP2010 Services including User Code Host. Security note: If you don't want user code host running do not call this command.)"
Write-Host " -IISReset (Runs IISReset on all servers)"
Write-Host " -ClearSessions (Clears any existing remote sessions with the servers - not normally needed as script cleans up)"
Write-Host " -NoSP (If the command being issued does not require the SharePoint snappin, use this switch to improve performance)"
Write-Host " -Silent (Don't prompt for Un Safe Commands)"
Write-Host " -Help (This output)"
Write-Host
Write-Host "Server configuration:"
Write-Host "Each server in the farm must allow PS Remoting."
Write-Host "run: winrm quickconfig (This will allow remote management on HTTP)"
Write-Host "run: winrm quickconfig -transport:SSL (This will allow remote management on HTTPS)"
Write-Host "run: winrm s winrm/config/client '@{TrustedHosts=`"RemoteComputer`"}' (Adds a trusted computer to the server config)"
Write-Host ""
Write-Host "Cross Domain:"
Write-Host "If your client computer is on another domain, you may need to run an additional command on the remote server(s) to allow."
Write-Host "run: "
write-host "New-Itemproperty -name LocalAccountTokenFilterPolicy -path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -propertyType DWord -value 1"
Write-Host "(This will allow the remote computer to be controlled from a machine on another domain)"
Write-Host
Write-Host "Examples:"
Write-Host ".\SPManage.ps1 -Ping #Simple ping test"
Write-Host ".\SPManage.ps1 -VerifyRemoting #Creates a remote session on each server"
Write-Host ".\SPManage.ps1 -ServerType:App -VerifyRemoting #Creates a remote session on each Application server"
Write-Host ".\SPManage.ps1 -UserName `"DOM\User`" -Password `"MyPass`" -VerifyRemoting #Uses a username and password to connect to the remote servers"
Write-Host ".\SPManage.ps1 -configFile devfarm.xml -Credential (Get-Credential) -VerifyRemoting #Uses a config file to connect to servers"
Write-Host ".\SPManage.ps1 -Command {get-process} #Gets the running processes for all servers in the farm"
Write-Host ".\SPManage.ps1 -IISReset #Issues IISReset using remote powershell session"
Write-Host ".\SPManage.ps1 -RestartSPServices #Restarts all SP2010 Services on each server "
Write-Host ".\SPManage.ps1 -ServerType App -RestartSPServices #Restarts all SP2010 Services on the application servers"
Write-Host
Write-Host "Notes:"
Write-Host "Sessions are cleaned up at the end of the script."
Write-Host "If a session already exists with the remote computer the script will attempt to use it."
Write-Host "You don't need to specify a username and password if your account has correct permissions"
Write-Host "This script must be run from an elevated PowerShell session."
Write-Host "Be aware of the double hop issue when trying to execute SharePoint commands remotely. If the database is not on the same server the call will fail."
Write-Host
Write-Host "Example Config File (For use when you are not running on a server in the SP Farm. Specify -configFile parameter)"
Write-Host "<?xml version=`"1.0`" ?>"
Write-Host "<Config>"
Write-Host "<Servers>"
Write-Host " <Server Address=`"SPSERVER01`" />"
Write-Host " <Server Address=`"SPSERVER02`" />"
Write-Host "</Servers>"
Write-Host "</Config>"
}
if($Help)
{
Help;
return;
}
#endregion
#region SharePoint Commands
function GetFarmServers()
{
$farm = Get-SPFarm
if($farm -eq $null)
{
throw "Cannot connect to local farm"
}
if($ServerType -ieq "All")
{
return $farm.Servers | where-object {$_.Role -ne "Invalid" }
}
if($ServerType -ieq "APP")
{
return $farm.Servers | where-object {$_.Role -ieq "Application" }
}
if($ServerType -ieq "WFE")
{
return $farm.Servers | where-object {$_.Role -ieq "WebFrontEnd" }
}
}
function QueryFarmCommand()
{
$farm = Get-SPFarm
if($farm -eq $null)
{
throw "Cannot connect to local farm"
}
Write-Host
Write-Host "Farm Details"
Write-Host
$farm.Servers | sort $_.Role | Ft -AutoSize:$true @{Expression={$_.Role};Label="Role"}, @{Expression={$_.Address};Label="Address";}, @{Expression={$_.Status};Label="Status"}
}
#endregion
#region SharePoint Windows Services
function RestartSharePointServices()
{
StopSharePointServices
StartSharePointServices
}
function StartSharePointServices()
{
$serviceRestart = {
net start "SharePoint 2010 User Code Host";
net start "SharePoint 2010 Timer";
net start "SharePoint 2010 Administration";
net start "SharePoint Server Search 14";}
RemoteExecuteCommand $servers $serviceRestart $false $true "Stopping SharePoint Services (2010)"
}
function StopSharePointServices()
{
$serviceRestart = {
net stop "SharePoint 2010 User Code Host";
net stop "SharePoint 2010 Timer";
net stop "SharePoint 2010 Administration";
net stop "SharePoint Server Search 14";}
RemoteExecuteCommand $servers $serviceRestart $false $true "Stopping SharePoint Services (2010)"
}
#endregion
#region IO Functions and Config
function LoadSPSnappin($session)
{
if($NoSP -eq $false)
{
RemoteExecute $session {Add-PSSnapin "Microsoft.SharePoint.PowerShell"} "Loading SharePoint Snappin"
}
}
function Get-ScriptDirectory
{
$Invocation = (Get-Variable MyInvocation -Scope 1).Value
$dir = Split-Path $Invocation.MyCommand.Path
return $dir
}
function Set-Directory($location)
{
[IO.Directory]::SetCurrentDirectory((Convert-Path($location)))
}
function LoadConfiguration($configFile)
{
if(![IO.File]::Exists($configFile))
{
throw "Could not configuration file: $configFile. Script Terminated."
}
write-host "Found configuration file: $configFile"
try
{
$config = [xml] (get-content -Path $configFile)
write-host -ForegroundColor Green "Configuration Loaded Successfully"
return $config.Config
}
catch
{
Write-Error "Configuration file $config found but could not be loaded. May not be valid XML"
throw
}
}
#endregion
#region Ping / Verify Command
function VerifyRemotingCommand($servers)
{
[bool] $failure = $false;
foreach($server in $servers)
{
Write-Host "Attempting to create a remote PowerShell session in" $server.Address
$session = $null
$session = GetRemoteSession $server
if($session -ne $null -and $session.Availability -eq "Available")
{
Write-Host -NoNewline ($server.Address + " : ")
Write-Host -ForegroundColor Green "Success"
}
else
{
$failure = $true
throw "Failed"
}
trap
{
Write-Host -ForegroundColor Red ($server.Address + " : Remote PowerShell command failed. " + $_.Exception.Message)
continue;
}
}
if($failure)
{
throw "One or more servers would not except a remote PowerShell session"
}
}
function PingCommand($servers)
{
[bool] $failure = $false;
foreach($server in $servers)
{
if(!(Ping $server.Address $Credential))
{
$failure = $true;
}
# trap
# {
# Write-Host -ForegroundColor Red ($server.Address + ": Ping command failed. " + $_.Exception.Message)
# continue;
# }
}
if($failure)
{
throw "One or more PING commands failed"
}
}
function Ping([string] $computerName)
{
Write-Host -NoNewline "PING: $computerName"
$result = Test-Connection -ComputerName $computerName -ErrorAction:Stop -Count 2 -Quiet;
if($result)
{
Write-Host " Connection Successful"
}
else
{
Write-Host -ForegroundColor Red " Connection Failed"
}
return $result;
}
#endregion
#region Remoting Session Managment
#clears any sessions it can find between this computer and the remote computer
function ClearSessions([string] $computerName)
{
$session = Get-PSSession -ComputerName $computerName -ErrorAction:SilentlyContinue
while($session -ne $null)
{
Message $session.ComputerName "Removing session"
Remove-PSSession $session.Id
$session = Get-PSSession -ComputerName $computerName -ErrorAction:SilentlyContinue
}
}
#Only clears sessions in the sessionWatch variable
function ClearCurrentSessions()
{
#ensures PowerShell Session Cleanup
foreach($key in $sessionWatch.Keys)
{
$session = $sessionWatch[$key]
if($session -ne $null)
{
Write-Host "Exiting remote session " $session.Id
Remove-PSSession $session.Id
}
}
$sessionWatch.Clear();
}
function GetRemoteSession($server)
{
$computerName = $server.Address;
if($sessionWatch.ContainsKey($computerName))
{
return $sessionWatch[$computerName];
}
$session = Get-PSSession -ComputerName $computerName -ErrorAction:SilentlyContinue
if($session -ne $null -and $session.Availability -eq "Available")
{
$sessionWatch.Add($computerName, $session);
return $session;
}
if($Credential -ne $null)
{
$session = New-PSSession -ComputerName $computerName -Credential $Credential -ErrorAction:Stop
}
else
{
$session = New-PSSession -ComputerName $computerName -ErrorAction:Stop
}
$sessionWatch.Add($computerName, $session);
return $session
}
#endregion
#region Command Execution
function RemoteExecuteCommand($servers, $command, [bool] $job, [bool] $requiresSP, [string] $comment)
{
$jobWatch = @{};
$jobWatch.Clear();
foreach($server in $servers)
{
$session = GetRemoteSession $server
if($requiresSP)
{
LoadSPSnappin $session
}
if($job)
{
$pendingJob = RemoteExecuteJob $session $command $comment
$jobWatch.Add($session.ComputerName,$pendingJob)
}
else
{
RemoteExecute $session $command $comment
}
trap
{
Write-Host -ForegroundColor Red ($computerName + ": $Command : " + $_.Exception.Message)
break;
}
}
if($job)
{
foreach($id in $jobWatch.Keys)
{
Message $id "Receiving Job"
$pendingJob = $jobWatch[$id]
while($pendingJob.State -eq "Running")
{
Sleep 1
Receive-Job -InstanceId $pendingJob.InstanceId
}
Write-Host
$pendingJob | Wait-Job | Receive-Job
Remove-Job $pendingJob.InstanceId # | Out-Null
}
$jobWatch.Clear()
}
}
function RemoteExecute($session, $script, $comment)
{
Message $session.ComputerName $comment
Invoke-Command -Session $session -ScriptBlock $script
}
function RemoteExecuteJob($session, $script, $comment)
{
Message ($session.ComputerName + " [Job]") $comment
return Invoke-Command -AsJob -Session $session -ScriptBlock $script
}
function LocalExecute($script, $comment)
{
Message $env:ComputerName $comment
Invoke-Command -ScriptBlock $script
}
#Provides a confirmation prompt
function SafeFunction($question)
{
if(!$Silent)
{
if((Read-Host $question) -ine "Y")
{
Write-Host "Cancelled"
return $false;
}
}
return $true;
}
#endregion
$sessionWatch = @{};
$sessionWatch.Clear();
try
{
cls
$servers = $null;
if($configFile -eq $null)
{
#Gets the servers depending on ServerType (All, App, WFE)
$servers = GetFarmServers
}
else
{
$scriptDir = Get-ScriptDirectory
$config = LoadConfiguration ([System.IO.Path]::Combine($scriptDir,$configFile))
$servers = $config.Servers.Server
if($servers -eq $null -or $servers.Count -eq 0)
{
throw "No servers to process, please check config file."
}
}
if($ClearSessions)
{
$servers | ForEach-Object { ClearSessions $_.Address }
}
if($Ping)
{
PingCommand $servers
}
if($VerifyRemoting)
{
VerifyRemotingCommand $servers
}
if($QueryFarm)
{
$query = {QueryFarmCommand}
LocalExecute $query "Query Farm (Local)"
}
if($QueryWebApps)
{
$query = {Get-SPWebApplication | Ft -AutoSize:$true @{Expression={$_.DisplayName};Label="Name"}, @{Expression={$_.Url};Label="Url";}, @{Expression={$_.ApplicationPool.Name};Label="App Pool"}, @{Expression={$_.ApplicationPool.Status};Label="Status"}}
#RemoteExecuteCommand $servers $query $true $true "Query Web Applications"
LocalExecute $query "Query Web Applications (Local)"
}
if($IISReset)
{
$q = "Are you sure you want to execute IISReset on selected servers? Press Y to confirm."
if(SafeFunction($q))
{
RemoteExecuteCommand $servers {& IISReset} $true $false "IISRESET"
}
}
if($Command -ne $null)
{
$q = "Are you sure you want to execute a custom command on all servers in config $configFile ? Press Y to confirm."
if(SafeFunction($q))
{
RemoteExecuteCommand $servers $Command $true (!$NoSP) $Command.ToString().Trim()
}
}
if($QueryDiskSpace)
{
$query = { gwmi win32_logicaldisk -filter "drivetype=3" | Ft -AutoSize:$true @{Expression={$_.deviceid};Label="Device"},@{Expression={"{0:0.0}" -f ($_.size/1gb)};Label="Size (GB)"}, @{Expression={"{0:0.0}" -f ($_.freespace/1gb)};Label="Free Space (GB)"}, @{Expression={"{0:0.0}" -f (([int64]$_.size - [int64]$_.freespace)/1gb)};Label="Used (GB)"}, @{Expression={"{0:0}%" -f ((([int64]$_.size - [int64]$_.freespace) * 100.0)/$_.size)};Label="Used Percentage"}}
RemoteExecuteCommand $servers $query $false $false "Query Disk Space"
}
if($RestartSPServices)
{
RestartSharePointServices
}
if($StopSPServices)
{
StopSharePointServices
}
if($StartSPServices)
{
StartSharePointServices
}
Write-Host "Complete (Use switch -Help for script information)"
}
finally
{
ClearCurrentSessions
}
Â
Â
Â