SHIFT-WIKI - Sjoerd Hooft's InFormation Technology
This WIKI is my personal documentation blog. Please enjoy it and feel free to reach out through blue sky if you have a question, remark, improvement or observation.
Cheatsheet Solaris
Summary: A cheatsheet to collect various information and commands for solaris.
Date: 3 January 2025
Shutdown & reboot
You have more than one command option that you can use. The best command is this, executed as root:
shutdown -y -i5 -g0
This will immediately shut the system down. You can also use the older command that still works:
sync;sync;init 5
You can even use:
poweroff
Reboot If you are trying to reboot the system as opposed to turning it off, you could use:
shutdown -y -i6 -g0
Or:
sync;sync;init 6
Or even:
reboot
Runlevel
Find current runlevel:
sjoerd@solaris:/etc$ who -r . run-level 3 Mar 8 10:59 3 0 S
Starting Microsoft SCOM Agent
root@solaris:/opt/microsoft/scx/bin/tools# ll total 1078 -r-xr-xr-x 1 root bin 1.9K Aug 20 2009 scx-cimd -rwxr-xr-x 1 root root 164 Aug 20 2009 scxadmin -rwxr--r-- 1 root root 180K Aug 20 2009 scxcimcli -rwxr--r-- 1 root root 124K Aug 20 2009 scxcimconfig -rwxr--r-- 1 root root 46K Aug 20 2009 scxcimmof -rwxr--r-- 1 root root 46K Aug 20 2009 scxcimmofl -rwxr-xr-x 1 root root 168 Aug 20 2009 scxsslconfig -rwxr--r-- 1 root root 103K Aug 20 2009 scxwbemexec -rw-r--r-- 1 root root 232 Aug 20 2009 setup.sh root@solaris:/opt/microsoft/scx/bin/tools# ./scx-cimd start Starting Cim server daemon
ps -ef now shows:
root 939 1 0 11:49:48 ? 0:00 /opt/microsoft/scx/bin/scxcimserver
Services mgmt
root@solaris:~# svcadm clean scx-cimd Usage: svcadm [-v] [cmd [args ... ]] svcadm enable [-rst] <service> ... - enable and online service(s) svcadm disable [-st] <service> ... - disable and offline service(s) svcadm restart <service> ... - restart specified service(s) svcadm refresh <service> ... - re-read service configuration svcadm mark [-It] <state> <service> ... - set maintenance state svcadm clear <service> ... - clear maintenance state svcadm milestone [-d] <milestone> - advance to a service milestone Services can be specified using an FMRI, abbreviation, or fnmatch(5) pattern, as shown in these examples for svc:/network/smtp:sendmail svcadm <cmd> svc:/network/smtp:sendmail svcadm <cmd> network/smtp:sendmail svcadm <cmd> network/*mail svcadm <cmd> network/smtp svcadm <cmd> smtp:sendmail svcadm <cmd> smtp svcadm <cmd> sendmail [1]+ Done /opt/MegaRaidStorageManager/MegaPopup/popup root@solaris:~# svcadm clear scx-cimd scx-cimd root@solaris:~# svcadm enable scx-cimd scx-cimd root@solaris:~# cd /lib/ Display all 241 possibilities? (y or n) root@solaris:~# cd /lib/svc/method/ root@solaris:/lib/svc/method# ./scx-cimd status Checking for service Cim server daemon Cim server daemon (804) is running root@solaris:/lib/svc/method# svcs scx-cimd STATE STIME FMRI online 11:36:08 svc:/application/management/scx-cimd:default root@solaris:/lib/svc/method#
Hardware Diagnostic
root@solarissparc:/opt/SUNWsan/bin# prtdiag System Configuration: Sun Microsystems sun4us Fujitsu Siemens PRIMEPOWER650 1-slot 8x SPARC64 V System clock frequency: 270 MHz Memory size: 24576 Megabytes ========================= CPUs ========================= Run Ecache CPU CPU Brd CPU Module MHz MB Impl. Mask --- --- ------- ----- ------ ------ ---- 0 0 0 2024 3.0 5 5.1 0 1 1 2024 3.0 5 5.0 0 2 2 2024 3.0 5 5.1 0 3 3 2024 3.0 5 5.1 0 4 4 2024 3.0 5 5.1 0 5 5 2024 3.0 5 5.2 0 6 6 2024 3.0 5 5.1 0 7 7 2024 3.0 5 5.2 ========================= IO Cards ========================= Bus Freq Brd Type MHz Slot Name Model --- ---- ---- ---------- ---------------------------- -------------------- 0 PCI 33 1 network-SUNW,hme 0 PCI 33 1 scsi-glm/disk (block) Symbios,53C875 0 PCI 33 1 scsi-glm/disk (block) Symbios,53C875 0 PCI 33 1 lpfc-pci10df,fa00/fp (fp) LP10000 0 PCI 66 1 lpfc-pci10df,fa00/fp (fp) LP10000 0 PCI 33 1 FJSV,pgtb-fjgi Broadcom,BCM5703C 0 PCI 66 1 FJSV,pgtb-fjgi Broadcom,BCM5703C 0 PCI 33 2 FJSV,pgtb-fjgi Broadcom,BCM5703C No failures found in System ===========================
root@solarisintel:~# prtdiag System Configuration: IBM IBM 3850 M2 / x3950 M2 -[72336LG]- BIOS Configuration: IBM -[A3E170AUS-1.16]- 12/21/2010 BMC Configuration: IPMI 2.0 (KCS: Keyboard Controller Style) ==== Processor Sockets ==================================== Version Location Tag -------------------------------- -------------------------- Intel Xeon MP Node 1 CPU 3 Intel Xeon MP Node 1 CPU 1 Intel Xeon MP Node 1 CPU 2 Intel Xeon MP Node 1 CPU 4 ==== Memory Device Sockets ================================ Type Status Set Device Locator Bank Locator ------- ------ --- ------------------- -------------------- DDR2 in use 1 DIMM1 Node1/Bank1/MemCard1 DDR2 in use 1 DIMM5 Node1/Bank1/MemCard1 DDR2 in use 2 DIMM2 Node1/Bank2/MemCard1 DDR2 in use 2 DIMM6 Node1/Bank2/MemCard1 DDR2 in use 3 DIMM3 Node1/Bank3/MemCard1 DDR2 in use 3 DIMM7 Node1/Bank3/MemCard1 DDR2 in use 4 DIMM4 Node1/Bank4/MemCard1 DDR2 in use 4 DIMM8 Node1/Bank4/MemCard1 DDR2 in use 5 DIMM1 Node1/Bank5/MemCard2 DDR2 in use 5 DIMM5 Node1/Bank5/MemCard2 DDR2 in use 6 DIMM2 Node1/Bank6/MemCard2 DDR2 in use 6 DIMM6 Node1/Bank6/MemCard2 DDR2 in use 7 DIMM3 Node1/Bank7/MemCard2 DDR2 in use 7 DIMM7 Node1/Bank7/MemCard2 DDR2 empty 8 DIMM4 Node1/Bank8/MemCard2 DDR2 empty 8 DIMM8 Node1/Bank8/MemCard2 DDR2 in use 9 DIMM1 Node1/Bank9/MemCard3 DDR2 in use 9 DIMM5 Node1/Bank9/MemCard3 DDR2 in use 10 DIMM2 Node1/Bank10/MemCard3 DDR2 in use 10 DIMM6 Node1/Bank10/MemCard3 DDR2 in use 11 DIMM3 Node1/Bank11/MemCard3 DDR2 in use 11 DIMM7 Node1/Bank11/MemCard3 DDR2 empty 12 DIMM4 Node1/Bank12/MemCard3 DDR2 empty 12 DIMM8 Node1/Bank12/MemCard3 DDR2 in use 13 DIMM1 Node1/Bank13/MemCard4 DDR2 in use 13 DIMM5 Node1/Bank13/MemCard4 DDR2 in use 14 DIMM2 Node1/Bank14/MemCard4 DDR2 in use 14 DIMM6 Node1/Bank14/MemCard4 DDR2 in use 15 DIMM3 Node1/Bank15/MemCard4 DDR2 in use 15 DIMM7 Node1/Bank15/MemCard4 DDR2 empty 16 DIMM4 Node1/Bank16/MemCard4 DDR2 empty 16 DIMM8 Node1/Bank16/MemCard4 ==== On-Board Devices ===================================== ==== Upgradeable Slots ==================================== ID Status Type Description --- --------- ---------------- ---------------------------- 1 available PCI Express Node1 PCI-Express Slot 1 2 available PCI Express Node1 PCI-Express Slot 2 3 available PCI Express Node1 PCI-Express Slot 3 4 available PCI Express Node1 PCI-Express Slot 4 5 in use PCI Express Node1 PCI-Express Slot 5 6 available PCI Express Node1 PCI-Express Slot 6 7 available PCI Express Node1 PCI-Express Slot 7
xauth
This sounds like you don't have the standard X applications such as "xauth" on your PATH. On Solaris this means you need to add "/usr/openwin/bin" to your PATH environment variable.
PATH
So set your path like this:
export PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/usr/openwin/bin"
Create A User
useradd sjoerd \ -c "Sjoerd Hooft Local Account" \ -d /export/home/sjoerd \ -m \ -s /usr/bin/bash useradd -c "Sjoerd Hooft Local Account" -d /export/home/sjoerd -m -s /usr/bin/bash sjoerd
Note that the /home is reserved for system usage and that local users should get a homedir in /export/home
Locking and Unlocking a user
Lock: -l Unlock: -u
user@solbox:~$ sudo passwd -l user1 passwd: password information changed for user1 user@solbox:~$ sudo passwd -u user1 passwd: password information changed for user1
With Sun Directory Server
sjoerd@solaris:/opt/SUNWdsee7/bin$ ./dsutil account-status uid=richard,ou=people,dc=prd,dc=domain Enter "cn=Directory Manager" password: "uid=richard,ou=people,dc=prd,dc=domain" is activated. sjoerd@solaris:/opt/SUNWdsee7/bin$ ./dsutil account-inactivate uid=richard,ou=people,dc=prd,dc=domain Enter "cn=Directory Manager" password: "uid=richard,ou=people,dc=prd,dc=domain" has been inactivated. sjoerd@solaris:/opt/SUNWdsee7/bin$ ./dsutil account-status uid=richard,ou=people,dc=prd,dc=domain Enter "cn=Directory Manager" password: "uid=richard,ou=people,dc=prd,dc=domain" is inactivated.
http://docs.oracle.com/cd/E19424-01/820-4809/managing-account-lockout/index.html
Change default shell of Local User
This is set in the /etc/passwd file:
user123:x:9613:2013:User 123:/home/user123:/bin/ksh
Cheatsheet Python
Summary: Python hints, tips, oneliners and best practices.
Date: 8 December 2024
Python Pipeline Tasks
- task: PythonScript@0 displayName: "Sort and print all system environments " inputs: scriptSource: 'inline' script: | import os for name, value in sorted(os.environ.items()): print(" " + name + "=" + value) - task: PythonScript@0 displayName: "Python version " inputs: scriptSource: 'inline' script: | import subprocess import os if os.environ['AGENT_OS'] == "Linux": version = subprocess.getoutput('python3 --version') elif os.environ['AGENT_OS'] == "Windows_NT": version = subprocess.getoutput('py -3 --version') else: version = "unknown" print(f"Python version is {version}") - task: PythonScript@0 displayName: "Pip version " inputs: scriptSource: 'inline' script: | import subprocess pip = subprocess.getoutput('pip --version') print(f"Pip version is {pip}") - task: PowerShell@2 displayName: "Python virtual environment" inputs: pwsh: true targetType: 'inline' script: | Write-Host "`n##[section]Start python script`n" # Create virtual environment "env" by running module venv (https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/) py -m venv env .\env\Scripts\activate.ps1 -Verbose Write-Host "`n##[section]Verify virtual environment`n" Get-Command python.exe Write-Host "`n##[section]Install packages`n" $scriptDir = "$(BUILD.SourcesDirectory)\$(BUILD.REPOSITORY.NAME)\src\$module" Write-Host "Locatie: $(Get-Location); Script dir: $scriptDir" if (Test-Path $scriptDir\requirements.txt){ Write-Host "Directory: $scriptDir; Requirements file: Present" py -m pip install -r $scriptDir\requirements.txt }else { Write-Host "Directory: $scriptDir; Requirements file: Not present. Installing from code." # install a package py -m pip install requests # install a specific version py -m pip install pandas==1.5.2 } Write-Host "`n##[section]Run python script`n" if (Test-Path $scriptDir\main.py){ Write-Host "Script: $scriptDir\main.py; Status: Present" py $scriptDir\main.py }else{ Throw "Script: not found in $scriptDir" } Write-Host "`n##[section]Install packages`n" # install a package py -m pip install requests # install a specific version py -m pip install pandas==1.5.2
Cheatsheet PowerShell
Summary: Powershell hints, tips, oneliners and best practices.
Date: 8 December 2024
Useful links
PowerShell Help
Get-Help with -Parameter is a quick way to examine the data type a given parameter expects:PS> Get-Help Get-ChildItem -Parameter Path -Path <String[]> Specifies a path to one or more locations. Wildcards are permitted. The default location is the current directory (`.`). Required? false Position? 0 Default value Current directory Accept pipeline input? True (ByPropertyName, ByValue) Accept wildcard characters? false
PowerShell History
View history of powershell commands and invoke them using “r #”
Get-History <# Output #> r 1
See all saved commands in vscodecode (Get-PSReadLineOption).HistorySavePath
PowerShell If
If statementif (($alllogs -eq "True") -AND ($result)){ Write-Host "Both statements are true" }elseif (($buildreason -eq "IndividualCI") -or ($buildreason -eq "BatchedCI") -or ($buildreason -eq "PullRequest")){ Write-Host "At least one of the statements is true" }else { Write-Host "None of the statements is true" }
PowerShell Count
Count number of strings / objects# string $een = "een" $een.Count 1 # Array $twee = @("een","twee") $twee.count 2
Length# string $een = "een" $een.Length 3 # Array $twee = @("een","twee") $twee.Length 2 $twee[0].Length 3
Measure-Object - Sometimes counting when there is only one item can fail, use measure-object instead.$een = "een" ($een | Measure-Object).Count 1 $twee = @("een","twee") ($twee | Measure-Object).Count 2
PowerShell Dates
# Dates $timestamp = Get-Date -format "yyyyMMdd-HH.mm" # 20211011-14.27 $readdate = Get-Date -format "d MMM yyyy" # 11 Oct 2021 $weekdate = Get-Date -uformat %V # Week number # 41 $monthdate = Get-Date -format "MMMM-yyyy" # May-2021
add or subtract days[datetime]$endDate = (Get-Date).AddDays(+90) [datetime]$endDate = (Get-Date).AddDays(-90)
Powershell Error Handling
Error handling explained
Try Catch Error Finally with LineNumber for troubleshooting
function Get-ScriptLineNumber { return $MyInvocation.ScriptLineNumber } try{ Write-Host "Do something that you want to catch the error of" }catch{ # Catch the error Write-Host "Full Error: $_" # Or error out after all Throw "Failed on: $actionname; Status: Failed; Line: $(Get-ScriptLineNumber); Error: $($_.Exception.Message)" }finally { <#Do this after the try block regardless of whether an exception occurred or not#> # For example, clean up remote ps sessions }
Exception.optionstry{ # Do something that you want to catch the error of Get-ChildItem \\prox-hyperv -ErrorAction Stop # [System.Net.DNS]::GetHostByName("server99") # Connect-AzAccount # Get-AzResourceGroup -Name "exampleGroup" -ErrorAction Stop }catch [System.Management.Automation.ItemNotFoundException] { Write-Host "Cannot find item." Write-Host -NoNewLine "Exception Message : " Write-Host -Foreground Red -Background Black "$($_.Exception.Message)" }catch{ # Catch the error Write-Host -Foreground Red -Background Black "Error found. Please try again, or if the error persists, contact support for evaluation. Please provide the following diagnostics:" Write-Host -NoNewLine "Exception Message : " Write-Host -Foreground Red -Background Black "$($_.Exception.Message)" # Exceptions can contain inner exceptions. This is often the case when the code you are calling catches an exception and throws a different exception. They will place the original exception inside the new exception. Write-Host -NoNewLine "Inner Exception Message : " Write-Host -Foreground Red -Background Black "$($_.Exception.InnerException.Message)" # The FullyQualifiedErrorId is the .Message property of the exception object along with the the fully-qualified name of the class where the exception originated. Write-Host -NoNewLine "Fully Qualified Error Id : " Write-Host -Foreground Red -Background Black "$($_.FullyQualifiedErrorId)" # Output provides the error type you need to catch this specific error type Write-Host -NoNewLine "Exception type : " Write-Host -Foreground Red -Background Black "$($_.Exception.GetType().fullname)" # Shows the powershell command. Does not work for .Net exceptions Write-Host -NoNewLine "Command : " Write-Host -Foreground Red -Background Black "$($_.InvocationInfo.MyCommand)" # Position of the error in the scriptblock or file Write-Host -NoNewLine "Position : " Write-Host -Foreground Red -Background Black "At line: $($_.InvocationInfo.ScriptLineNumber) char:$($_.InvocationInfo.OffsetInLine)" # Shows the faulty line. Also works for .Net exceptions Write-Host -NoNewLine "Full line : " Write-Host -Foreground Red -Background Black "$($_.InvocationInfo.Line)" # Shows the full error. Useful for troubleshooting. Provides output so use careful when returning output. Write-Host "Full Error:" Get-Error # Shows the full error for AZ cmdlets. Useful for troubleshooting. Provides output so use careful when returning output. Usually also works with non AZ cmdlets. Write-Host "Full Azure Error:" Resolve-AzError -Last }finally { #Do this after the try block regardless of whether an exception occurred or not. For example, clean up remote ps sessions, clear variables or cleanup files. }
PowerShell Input and Output
Enable logging of script
### Script Variables ### $scriptname = [System.IO.Path]::GetFilenameWithoutExtension($MyInvocation.MyCommand.Path.ToString()) $scriptlocation = Split-Path $myinvocation.mycommand.path $date = (Get-Date).ToString('yyyyMMdd-HHmm') ### Start transcript for full logging capabilities ### start-transcript -path "$scriptlocation\$scriptname-$date-logtranscript.txt" ### Stop transcript Stop-transcript
Script output and Write-Host options
# Inside a function use return or write-output return "value" Write-Output $value # Output an object without adding it to the function output Write-Host "color" -ForegroundColor Red -BackgroundColor green -noNewLine $object | Out-Host
Input password$password = Read-Host "Enter password" -asSecureString
Use padright to fill a line with one symbolWrite-Host ''.PadRight(78, '=') # Or with a variable $wide = 32 Write-Host ''.PadRight($wide, '=')
Preference Variables
Verbose Preference# Default $VerbosePreference = 'SilentlyContinue' # Override: -Verbose # Verbose output $VerbosePreference = 'Continue' # Override: -Verbose:$false
Debug Preference# Default $DebugPreference = 'SilentlyContinue' # Debug output $DebugPreference = 'Continue'
Whatif Preference# Default $WhatIfPreference = $false # Override: -WhatIf # When WhatIf is enabled, the cmdlet reports the expected effect of the command, but doesn't execute the command. $WhatIfPreference = $true # Override: -WhatIf:$false
PowerShell Variables
Set system (environment) variable$env:var="value"
Get all system (environment) variables, sorted by nameget-childitem -path env:* | Sort Name
Variables in function
Declare a variable with script scope to use it in a function$script:orgUrl = "https://dev.azure.com/getshiftingcom" $script:apiversion = "api-version=6.0" function SetBuildTag { # Load Azure DevOps API settings AzureDevOpsAPISettings foreach ($tag in $tags){ $tagurl = "$orgUrl/$env:System_Teamproject/_apis/build/builds/$env:BUILD_BUILDID/tags/$($tag)?$apiversion" } }
set variable with a dash/hyphenNew-Variable -Name "MODULE-SiteName" -Value "Incomingapi"
set system variable with a dash/hyphen[Environment]::SetEnvironmentVariable('MODULE-SiteName','Incomingapi')
Set system variables with a dash/hyphen${env:test-app_user} = "svc-test-dev" $user = ${env:test-app_user}
Remote PowerShell
Set variables
$AdminCredentials = Get-Credential $remotePort = 5986 $pso = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck $Culture = "en-US" $pso.Culture = $Culture $pso.UICulture = $Culture $sessionParams = @{} $sessionParams.Add('UseSSL', $true) $sessionParams.Add('Port', $remotePort) $sessionParams.Add('Credential', $AdminCredentials)
Start session to restart computer$session = New-PSSession -ComputerName webserverdmz.domain -EnableNetworkAccess -SessionOption $pso @sessionParams Invoke-Command -Session $session -ScriptBlock {Restart-Computer} Remove-PSSession $session
PowerShell Function Template
See here for guidelines.
function Use-AzureDevOpsApi{ #Use Get-Verb for a list of approved verbs <# .SYNOPSIS Short description .DESCRIPTION Long description .PARAMETER Pat Explain the parameter Pat. Repeat for additional parameters. .OUTPUTS Explain the powershell output, if any .EXAMPLE Pipeline example: - task: PowerShell@2 displayName: "Use Default SystemAccessToken" env: SYSTEM_ACCESSTOKEN: $(System.AccessToken) inputs: pwsh: true targetType: 'inline' script: | # Load Azure DevOps API settings Use-AzureDevOpsApi Script example: Use-AzureDevOpsApi -Pat $Pat .LINK System access token: https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#systemaccesstoken .NOTES Author : Sjoerd Hooft Version: 2022-08-03 #> [CmdletBinding()] param ( [Parameter()] [ValidateLength(52,52)] # See for more parameter validation https://poshcode.gitbook.io/powershell-practice-and-style/style-guide/function-structure [ValidateSet("dev", "tst", "acc")] [string] $Pat ) begin { Write-Host "##[section]Function: $($MyInvocation.MyCommand)" Write-Verbose "Input: $($PSBoundParameters | Out-String)" # Set Verbose switch based on PSBoundParameters $CmdLetOutput = @{Verbose = $($PSBoundParameters.Verbose)} # Collect information } process { # Do stuff } end { # Cleanup } }
PowerShell Function Validates
- Not null or empty:
[ValidateNotNullOrEmpty()]
- Latest or YYYY-MM:
[ValidatePattern("latest|20\d{2}[-]\d{2}")]
- Email:
[ValidatePattern('(.+@getshifting\.com)$')]
- Specific server name:
[ValidatePattern("web(dev|tst|acc)dmz0[12]")]
- Environment:
[ValidateSet("dev", "tst", "acc", "prd")]
- Number between:
[ValidateRange(8,100)]
- Length range:
[ValidateLength(8,12)]
- Length exactly:
[ValidateLength(8,8)]
PowerShell Modules
Check Azure powershell module depending on PS version
Write-Host "Check required PowerShell Modules `n" # The "new" PS module for Azure requires PowerShell 7 if ($($PSVersionTable.PSVersion).Major -eq 7){ if (Get-Module -ListAvailable -Name AZ) { Write-Host "PowerShell module Azure exists" } else { Write-Host "PowerShell module Azure does not exist. Start installation. " Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -Force } }else{ Throw "Powershell needs to be version 7" }
PowerShell DNS Moduleif (Get-Module -ListAvailable -Name DnsServer) { Write-Host "PowerShell module DnsServer exists" } else { Write-Host "Module DNSServer does not exist. Starting installation" Import-Module ServerManager Add-WindowsFeature -Name "RSAT-DNS-Server" }
PowerShell AD Module# Because ActiveDirectory is a 5.1 module you need to add -All if (Get-Module -ListAvailable -All -Name ActiveDirectory) { Write-Host "PowerShell module ActiveDirectory exists" } else { Write-Host "Module ActiveDirectory does not exist. Starting installation" Import-Module ServerManager Add-WindowsFeature -Name "RSAT-AD-PowerShell" –IncludeAllSubFeature }
PowerShell Pester module, remove shipped version and install latest version (Needs PS 7)
if (Get-Module -ListAvailable -Name Pester) { # Check for version 3.4 and if available remove it Get-Module -ListAvailable -Name Pester if (((((Get-Module -ListAvailable -Name Pester).Version).Major) -eq 3) -AND ((((Get-Module -ListAvailable -Name Pester).Version).Minor) -eq 4)) { Write-Host "PowerShell Module Pester is version 3.4 which is shipped along with Win10/Windows 2016. Start removal:" $module = "C:\Program Files\WindowsPowerShell\Modules\Pester" takeown /F $module /A /R icacls $module /reset icacls $module /grant "*S-1-5-32-544:F" /inheritance:d /T Remove-Item -Path $module -Recurse -Force -Confirm:$false } # Verifieer of Pester al aanwezig met minimaal versie 5 if ((((Get-Module -ListAvailable -Name Pester).Version).Major) -ne 5) { Write-Host "PowerShell module Pester is not up to date" Install-Module -Name Pester -Force -Scope CurrentUser }else{ Write-Host "PowerShell Module Pester is available with minimal version of 5:" Get-Module -ListAvailable -Name Pester } } else { Write-Host "PowerShell module Pester does not exist. Start installation. " Install-Module -Name Pester -Force -Scope CurrentUser }
IIS Administration Module, install extra version, see the version and the available commandlets. Note that this needs to be done in PowerShell 5 Administrative ShellInstall-Module -Name IISAdministration -Scope AllUsers -Force #Installs latest version next to it (1.1.0.0) Import-Module IISAdministration -RequiredVersion 1.1.0.0 $mod = Get-Module -Name IISAdministration $mod.Version $mod.ExportedCmdlets | Format-Table
Import PS ModuleImport-Module Pester
Get commands within a moduleGet-Command -module Pester
Get module for a commandGet-Command Get-Service
Remove / Unload a PowerShell moduleRemove-Module Pester
PowerShell Requires
#Requires -Version 7.0 #Requires -PSEdition Core # Requires for modules is slow because it also imports them # Requires does not work for non-PS Core modules like DNS and ActiveDirectory #Requires -Modules @{ ModuleName="Pester"; ModuleVersion="5.0" } #Requires -Modules Az #Requires -Modules AzureRmStorageTable
PowerShell ForEach
With custom PS Object and export to csv
$myCol = @() foreach ($vm in (get-vmhost esxprd101.intranet | get-vm )){ $VMInfo = "" | Select-Object VMName,VMHostName,NICCount $VMInfo.VMName = $vmview.Name $VMInfo.VMHostName = $vmview.Guest.HostName $VMInfo.NICCount = $vmview.Guest.Net.Count $myCol += $VMInfo } $myCol |Export-csv -NoTypeInformation $csvfile
PowerShell Comparison
Overview# logical and comparison # -and, -or, -not , ! : Connect expressions # -eq, -ne : Equal, not equal # -gt / -lt, -ge / -le : Greater/less than, greater or equal / less or equal # -replace # -match / -notmatch : Regular expression match # -like / -notlike : wilcard matching # -contains / -notcontains : check for value in array: $array -contains $value # -in / -notin : reverse syntax from contains: $value in $array
PowerShell Location
Change directory (alias cd)Set-Location c:\
Change directory and backPS C:\Users\sjoer> Push-Location c:\ PS C:\> Pop-Location PS C:\Users\sjoer>
Azure PowerShell
NOTE: Module AZ only works in PowerShell 7
TLS version# Set TLS version to use TLS 1.2 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Login to Azure
Login and contextConnect-AzAccount Get-AzContext -ListAvailable Set-AzContext -Name $dtapEnvironment -Subscription $azureSubscriptionName
Get TenantId$tenantId = (Get-AzContext).Tenant.Id
KeyVault
Get secret from KeyVault$adadminpass = (Get-AzKeyVaultSecret -VaultName kv-operations-global -Name "adAdminPass").SecretValue
Set secret to KeyVault$userpasswordsecure = ConvertTo-SecureString -String $userpassword -AsPlainText -Force Set-AzKeyVaultSecret -VaultName kv-operations-global -Name $username -SecretValue $userpasswordsecure
Resourcegroup Creation Time
((Invoke-AzRestMethod -Path "/subscriptions/$subId/resourcegroups?api-version=2020-06-01&`$expand=createdTime" -Method GET).Content | ConvertFrom-Json).value | Select-Object name,createdTime
Cheatsheet PowerCLI
Summary: A cheatsheet to use powerCLI, a set of powershell modules that lets you automate all aspects of vSphere management, including network, storage, VM, guest OS and more.
Date: 3 January 2025
Note that most of the snippets and code here was tested on a vSphere 5.1 environment, and also do not compy with any powershell best practices as I was simply not aware of any at the time I was working on this.
Get All WMI Classes
Get all wmi classes on all Windows Servers in your network and filter for Citrix Licensing class:
Get-ADComputer -filter {(operatingSystem -like "*windows*Server*")} | select -ExpandProperty name | foreach {Get-WmiObject -namespace "root" -Class "__Namespace" -ComputerName $_ } | where {$_.name -eq "CitrixLicensing"} | select name,pscomputername | FT
Get All LogicalDisks through WMI
IN case you need to know what drive letters are assigned throughout your network:
Get-ADComputer -filter {(operatingSystem -like "*windows*Server*")} | select -ExpandProperty name | foreach {Get-WmiObject Win32_logicalDisk -ComputerName $_ -Filter "Drivetype='3'"} | select deviceid,drivetype | FT
VM with CPU Reservation
Get-VM | Get-VMResourceConfiguration | where {$_.CPUReservationMhz -ne '0'}
And setting the CPU reservation to 0:
Get-VM | Get-VMResourceConfiguration | where {$_.CPUReservationMhz -ne '0'} | Set-VMResourceConfiguration -CPUReservationMhz 0
Get All VMs and IP Addresses
Get-VM | Select Name, @{N="IP Address";E={@($_.guest.IPAddress[0])}}
Export to CSV:
Get-VM | Select Name, @{N="IP Address";E={@($_.guest.IPAddress[0])}} | Export-Csv c:\serverandip.csv
VM with CPU Limit
Get-VM | Get-VMResourceConfiguration | where {$_.CPULimitMhz -ne '-1'}
And setting the CPU limit to unlimited:
Get-VM | Get-VMResourceConfiguration | where {$_.CPULimitMhz -ne '-1'} | Set-VMResourceConfiguration -CPULimitMhz $null
VM with Memory Reservation
Get-VM | Get-VMResourceConfiguration | where {$_.MemReservationMB -ne '0'}
And setting the memory reservation to 0:
Get-VM | Get-VMResourceConfiguration | where {$_.MemReservationMB -ne '0'} | Set-VMResourceConfiguration -MemReservationMB 0
Note that if you change the memory reservation, and there is not enough free space in the datastore the next time the VM is powered on the operation will fail. To prevent this you can see all this information with this command:
ForEach ($vm in (Get-VM | Get-VMResourceConfiguration | where {$_.MemReservationMB -ne '0'} | ForEach {$_.VM})){Get-VM $vm | Select Name,PowerState,@{N="Reservation";E={Get-VMResourceConfiguration -VM $_ | ForEach {$_.MemReservationMB}}},@{N="Datastore";E={Get-Datastore -VM $_}},@{N="Datastore Free Space";E={Get-Datastore -VM $_ | ForEach {$_.FreeSpaceMB}}}}
This is a small script to automatically remove the reservation if the datastore has enough free space:
ForEach ($vm in (Get-VM | Get-VMResourceConfiguration | where {$_.MemReservationMB -ne '0'} | ForEach {$_.VM})){ # $name = (Get-VM $vm | ForEach {$_.Name}) $powerstate = (Get-VM $vm | ForEach {$_.PowerState}) [int]$reservation = (Get-VMResourceConfiguration -VM $vm | ForEach {$_.MemReservationMB}) $datastore = (Get-Datastore -VM $vm ) [int]$dsfreespace = $datastore.FreeSpaceMB [int]$numberofds = (Get-Datastore -VM $vm |Measure-object).Count write-host "VM = $vm `n`t PowerState = $powerstate `n`t Memory Reservation = $reservation `n`t DataStore VM = $datastore `n`t Free Space on datastore = $dsfreespace `n`t Number of Datastores is $numberofds" if ((($dsfreespace - $reservation) -gt "0") -and ($numberofds -eq "1")){ Write-Host "Now removing the memory reservation $reservation for VM $vm" -ForegroundColor Green Get-VMResourceConfiguration -VM $vm | Set-VMResourceConfiguration -MemReservationMB 0 } else { Write-Host "Memory reservation ($reservation) cannot be removed because there is not enough free space on the datastore, or because the VM has multiple datastores." -ForegroundColor Red } }
Note: if you just want to view the VMs for which the change cannot be done automatically comment the other Write-Host lines out.
VM with Memory Limit
Get-VM | Get-VMResourceConfiguration | where {$_.MemLimitMB -ne '-1'}
And setting the memory limit to unlimited:
Get-VM | Get-VMResourceConfiguration | where {$_.MemLimitMB -ne '-1'} | Set-VMResourceConfiguration -MemLimitMB $null
Get All CPU and Memory Values
$startdir = "D:\sjoerd" $csvfile = "$startdir\memlimits.csv" $myCol = @() foreach ($VM in (Get-VM | Get-VMResourceConfiguration | where {$_.MemLimitMB -ne '-1'})){ $vmview = Get-VM $VM | Get-View $VMInfo = "" |select-Object VMName,CPUReservation,CPULimit,CPUShares,NumCPU,MEMSize,MEMReservation,MEMLimit,MEMShares $VMInfo.VMName = $vmview.Name $VMInfo.CPUReservation = $vmview.Config.CpuAllocation.Reservation If ($vmview.Config.CpuAllocation.Limit-eq "-1"){$VMInfo.CPULimit = "Unlimited"} Else{$VMInfo.CPULimit = $vmview.Config.CpuAllocation.Limit} $VMInfo.CPUShares = $vmview.Config.CpuAllocation.Shares.Shares $VMInfo.NumCPU = $VM.NumCPU $VMInfo.MEMSize = $vmview.Config.Hardware.MemoryMB $VMInfo.MEMReservation = $vmview.Config.MemoryAllocation.Reservation If ($vmview.Config.MemoryAllocation.Limit-eq "-1"){$VMInfo.MEMLimit = "Unlimited"} Else{$VMInfo.MEMLimit = $vmview.Config.MemoryAllocation.Limit} $myCol += $VMInfo } $myCol |Export-csv -NoTypeInformation $csvfile
VMWare Tools Version
get-vm |% { get-view $_.id } | select Name, @{ Name=";ToolsVersion";; Expression={$_.config.tools.toolsVersion}}
Get Hosts with Specific Version
get-vmhost | where-object { $_.version -eq "4.1.0" } | select name,version
Get Datastores and Used Storage for VMs within Cluster
Get-Cluster "Acceptance" | Get-VM | Select Name, @{N="Datastore";E={Get-Datastore -vm $_}}, UsedSpaceGB, ProvisionedSpaceGB | sort Name | Export-Csv F:\Scripts\Output\datastores-acceptance.csv
Get All Datastores for All Clusters and See Usage
ForEach ($cluster in get-cluster){get-cluster "$cluster" | Get-VMHost | select -first 1 | get-datastore | where {$_.name -like "?_*"} | Select Name,FreeSpaceMB,CapacityMB,@{N="Number of VMs";E={@($_ | Get-VM).Count}},@{N="VMs";E={@($_ | Get-VM | ForEach-Object {$_.Name})}},@{N="VM Size";E={@($_ | Get-VM | ForEach-Object {$_.UsedSpaceGB})}} | Export-Csv D:\sjoerd\datastore-$cluster-overview.csv}
Get Number of Paths in Use per Host within Cluster
Get-Cluster "Acceptance" | Get-VMHost | where {$_.State -eq "Connected"} | Select Name, @{N="TotalPaths";E={($_ | Get-ScsiLun | Get-ScsiLunPath | Measure-Object).Count}}
Scan Storage for all Hosts within Cluster
ForEach ($esxhost in (Get-Cluster "Acceptance" | Get-VMHost)) {Get-VmHostStorage $esxhost -RescanAllHba}
Set MPIO Settings for All Hosts in Cluster
ForEach ($esxhost in (Get-Cluster "Acceptance" | Get-VMHost)) {D:\tools\plink -ssh $esxhost -l root -pw <fillinpw> /opt/ontap/santools/config_mpath --primary --loadbalance --policy fixed}
Count the Number of VMs in a Cluster That Match a Name Pattern
get-cluster "acceptance" | get-vm | where {$_.name -match "prd"} | measure-object
Get all Dead Paths In a Datacenter
ForEach ($vmhost in (Get-Datacenter "The Netherlands" | Get-Vmhost | Sort)){ $deadpaths = Get-ScsiLun -vmhost $vmhost | Get-ScsiLunPath | where {$_.State -eq "Dead"} | Select ScsiLun,State; Write-Host $vmhost $deadpaths}
Get All LUN IDs in use on an ESX Server
Get-ScsiLun -vmhost esx01 -luntype disk | select runtimename | sort runtimename
Get All LUN IDs in use on a NetApp Filer
Get-NaLun | get-nalunmap | select Path,LunId | Sort LunId
Get All Volumes From NetApp Filer
This will get you all Volumes from a NetApp Filer that start with a capital R and an underscore, separated by a comma, and copied to the clipboard. I needed this to get all volumes that are part of replication:
import-module D:\sjoerd\dataontap connect-nacontroller filer01 -credential (Get-credential) (Get-NaVol | where {$_.name -like "R_*"} | select name -expandproperty Name) -join ',' | clip
Working with Credentials
If you need to submit credentials for connecting to something you can do this to get a prompt for entering the credentials in stead of having to put them on the commandline:
Connect-NaController filer01 -Credential (Get-Credential)
Get the Number of VMs on all Datastores in a Datacenter
Get-Datastore | where {$_.datacenter -match "The Netherlands"} | Select Name, @{N="Number of VMs";E={@($_ | Get-VM).Count}} | Sort "Number of VMs"
Get All VMs with Old Hardware Level Version
Get-Cluster "Acceptance" | Get-VM | Get-View | Where {$_.Config.Version -ne "vmx-09"} | Select Name | Sort Name
Set VM Description with CSV File
Note: This command will overwrite the existing descriptions, so make sure you do not overwrite anything important.
You need to create a simple csv file which looks like this:
VMName,Description server01,Domain Controller server02,Database Server
The second step is to run this command:
Import-Csv "D:\sjoerd\description.csv" | % { Set-VM $_.VMName -Description $_.Description -Confirm:$false}
Scripts
Save the code on your management workstation in a simple textfile, and change the extention to “.ps1”. Now you can run them from powershell like any executable.
Resource Pools with Ballooning and Swapping
$myCol = @() foreach($clus in (Get-Cluster)){ foreach($rp in (Get-ResourcePool -Location $clus | Get-View | Where-Object ` {$_.Name -ne "Resources" -and ` $_.Summary.QuickStats.BalloonedMemory -ne "0"})){ $Details = "" | Select-Object Cluster, ResourcePool, ` SwappedMemory ,BalloonedMemory $Details.Cluster = $clus.Name $Details.ResourcePool = $rp.Name $Details.SwappedMemory = $rp.Summary.QuickStats.SwappedMemory $Details.BalloonedMemory = $rp.Summary.QuickStats.BalloonedMemory $myCol += $Details } } $myCol
VMs with Ballooning and Swapping
$myCol = @() foreach($vm in (Get-View -ViewType VirtualMachine | Where-Object ` {$_.Summary.QuickStats.BalloonedMemory -ne "0"})){ $Details = "" | Select-Object VM, ` SwappedMemory ,BalloonedMemory $Details.VM = $vm.Name $Details.SwappedMemory = $vm.Summary.QuickStats.SwappedMemory $Details.BalloonedMemory = $vm.Summary.QuickStats.BalloonedMemory $myCol += $Details } $myCol
VMs Network Info
(get-vm) | %{ $vm = $_ echo $vm.name---- $vm.Guest.Nics | %{ $vminfo = $_ echo $vminfo.NetworkName $vminfo.IPAddress $vminfo.MacAddress echo ";`n"; } }
VMs Boot Time
$LastBootProp = @{ Name = 'LastBootTime' Expression = { ( Get-Date ) - ( New-TimeSpan -Seconds $_.Summary.QuickStats.UptimeSeconds ) } } Get-View -ViewType VirtualMachine -Property Name, Summary.QuickStats.UptimeSeconds | Select Name, $LastBootProp
Reading Values for Properties from CSV file
This little snippet will set the memory reservations for a VM from a csv file. This is useful if you want to rollback a change and you remembered to make a csv file with VM information. You can use the list to make a separate vms.txt file as input as well as a vmsinput.txt file with reservation settings:
vms.txt:
WINXP-TESTVM2 WINXP-TESTVM3 WINXP-TESTVM4
vmsinput.txt:
VMName,MEMReservation WINXP-TESTVM2,128 WINXP-TESTVM3,256 WINXP-TESTVM4,128
$sourcevms = "C:\Users\sjoerd\Desktop\powercli scripts\vms.txt" $sourcememory = "C:\Users\sjoerd\Desktop\powercli scripts\vmsinput.txt" $list = Get-Content $sourcevms | Foreach-Object {Get-VM $_ } foreach($item in $list){ $vm = $item.Name # The line below gives all information in @= format. This is not directly usable. $memres = import-csv $sourcememory | where-object {$_.vmname -eq "$vm"} # With this you get only the value of the property in the variable. $memresvm = $memres.MEMReservation Get-VM $vm | Get-VMResourceConfiguration | where {$_.MemReservationMB -eq '0'} | Set-VMResourceConfiguration -MemReservationMB $memresvm }