wiki.getshifting.com

--- Sjoerd Hooft's InFormation Technology ---

User Tools

Site Tools


start

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
2025/06/01 11:59

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
2025/06/01 11:59

Cheatsheet PowerShell

Summary: Powershell hints, tips, oneliners and best practices.
Date: 8 December 2024

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 vscode
code (Get-PSReadLineOption).HistorySavePath

PowerShell If

If statement
if (($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

  1. function Get-ScriptLineNumber {
  2. return $MyInvocation.ScriptLineNumber }
  3. try{
  4. Write-Host "Do something that you want to catch the error of"
  5. }catch{
  6. # Catch the error
  7. Write-Host "Full Error: $_"
  8. # Or error out after all
  9. Throw "Failed on: $actionname; Status: Failed; Line: $(Get-ScriptLineNumber); Error: $($_.Exception.Message)"
  10. }finally {
  11. <#Do this after the try block regardless of whether an exception occurred or not#>
  12. # For example, clean up remote ps sessions
  13. }


Exception.options
try{
    # 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
  1. ### Script Variables ###
  2. $scriptname = [System.IO.Path]::GetFilenameWithoutExtension($MyInvocation.MyCommand.Path.ToString())
  3. $scriptlocation = Split-Path $myinvocation.mycommand.path
  4. $date = (Get-Date).ToString('yyyyMMdd-HHmm')
  5.  
  6. ### Start transcript for full logging capabilities ###
  7. start-transcript -path "$scriptlocation\$scriptname-$date-logtranscript.txt"
  8.  
  9. ### Stop transcript
  10. Stop-transcript


Script output and Write-Host options
  1. # Inside a function use return or write-output
  2. return "value"
  3. Write-Output $value
  4. # Output an object without adding it to the function output
  5. Write-Host "color" -ForegroundColor Red -BackgroundColor green -noNewLine
  6. $object | Out-Host


Input password
$password = Read-Host "Enter password" -asSecureString


Use padright to fill a line with one symbol
Write-Host ''.PadRight(78, '=')
# Or with a variable
$wide = 32
Write-Host ''.PadRight($wide, '=')


Preference Variables

About 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 name
get-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/hyphen
New-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
  1. $AdminCredentials = Get-Credential
  2. $remotePort = 5986
  3. $pso = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
  4. $Culture = "en-US"
  5. $pso.Culture = $Culture
  6. $pso.UICulture = $Culture
  7. $sessionParams = @{}
  8. $sessionParams.Add('UseSSL', $true)
  9. $sessionParams.Add('Port', $remotePort)
  10. $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
  1. Write-Host "Check required PowerShell Modules `n"
  2. # The "new" PS module for Azure requires PowerShell 7
  3. if ($($PSVersionTable.PSVersion).Major -eq 7){
  4. if (Get-Module -ListAvailable -Name AZ) {
  5. Write-Host "PowerShell module Azure exists"
  6. } else {
  7. Write-Host "PowerShell module Azure does not exist. Start installation. "
  8. Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -Force
  9. }
  10. }else{
  11. Throw "Powershell needs to be version 7"
  12. }


PowerShell DNS Module
if (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)
  1. if (Get-Module -ListAvailable -Name Pester) {
  2. # Check for version 3.4 and if available remove it
  3. Get-Module -ListAvailable -Name Pester
  4. if (((((Get-Module -ListAvailable -Name Pester).Version).Major) -eq 3) -AND ((((Get-Module -ListAvailable -Name Pester).Version).Minor) -eq 4)) {
  5. Write-Host "PowerShell Module Pester is version 3.4 which is shipped along with Win10/Windows 2016. Start removal:"
  6. $module = "C:\Program Files\WindowsPowerShell\Modules\Pester"
  7. takeown /F $module /A /R
  8. icacls $module /reset
  9. icacls $module /grant "*S-1-5-32-544:F" /inheritance:d /T
  10. Remove-Item -Path $module -Recurse -Force -Confirm:$false
  11. }
  12. # Verifieer of Pester al aanwezig met minimaal versie 5
  13. if ((((Get-Module -ListAvailable -Name Pester).Version).Major) -ne 5) {
  14. Write-Host "PowerShell module Pester is not up to date"
  15. Install-Module -Name Pester -Force -Scope CurrentUser
  16. }else{
  17. Write-Host "PowerShell Module Pester is available with minimal version of 5:"
  18. Get-Module -ListAvailable -Name Pester
  19. }
  20. } else {
  21. Write-Host "PowerShell module Pester does not exist. Start installation. "
  22. Install-Module -Name Pester -Force -Scope CurrentUser
  23. }


IIS Administration Module, install extra version, see the version and the available commandlets. Note that this needs to be done in PowerShell 5 Administrative Shell
Install-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 Module
Import-Module Pester


Get commands within a module
Get-Command -module Pester


Get module for a command
Get-Command Get-Service


Remove / Unload a PowerShell module
Remove-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
  1. $myCol = @()
  2. foreach ($vm in (get-vmhost esxprd101.intranet | get-vm )){
  3. $VMInfo = "" | Select-Object VMName,VMHostName,NICCount
  4. $VMInfo.VMName = $vmview.Name
  5. $VMInfo.VMHostName = $vmview.Guest.HostName
  6. $VMInfo.NICCount = $vmview.Guest.Net.Count
  7. $myCol += $VMInfo
  8. }
  9. $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 back
PS 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 context
Connect-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
2025/06/01 11:59

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
}
2025/06/01 11:59
start.txt · Last modified: by 127.0.0.1