IT Tutorials

PowerShell Scripting for System Admins: Practical Guide with Real Examples

Introduction: Why System Admins Need PowerShell

Managing infrastructure manually is inefficient.

Updating 100 servers manually takes 2+ hours. The same task with PowerShell takes 2 minutes.

PowerShell isn’t complicated. It’s practical automation.

This guide covers:

  • What PowerShell actually is
  • Real scripts you can use today
  • Common mistakes to avoid
  • Best practices for production

What PowerShell Actually Is

PowerShell is an automation language built into Windows.

The core concept: Ask the computer questions and tell it what to do with the answers.

powershell
Get-Service          // "What services are running?"
Get-Process          // "What processes are running?"
Get-ChildItem        // "What files exist?"

Every command follows the pattern: Verb-Noun

  • Get-Service (get information about services)
  • Set-ItemProperty (set a property)
  • Remove-Item (delete something)
  • Start-Service (start something)

Once you understand this pattern, you can guess most commands.


Part 1: Essential PowerShell Concepts

Cmdlets (Commands)

A cmdlet is a PowerShell command.

powershell
Get-Service

Returns a list of services.

Piping (The Powerful Part)

The pipe (|) takes output from one command and sends it to another.

powershell
Get-Service | Where-Object {$_.Status -eq "Running"}

Translation: “Get services, then filter to show only running ones.”

Variables

Store values for reuse:

powershell
$serverName = "Server1"
$date = Get-Date
$services = Get-Service

Loops

Repeat actions for multiple items:

powershell
$servers = "Server1", "Server2", "Server3"

foreach ($server in $servers) {
    Get-Service -ComputerName $server
}

Part 2: Practical Scripts for System Admins

Script 1: Check Disk Space on Multiple Servers

This script checks free disk space and alerts if below threshold:

powershell
$servers = "Server1", "Server2", "Server3", "Server4"
$threshold = 10GB

foreach ($server in $servers) {
    $volumes = Get-Volume -ComputerName $server
    
    foreach ($volume in $volumes) {
        if ($volume.SizeRemaining -lt $threshold) {
            Write-Host "$server - Drive $($volume.DriveLetter): Only $([math]::Round($volume.SizeRemaining/1GB))GB free"
        }
    }
}

What it does:

  • Checks each server’s disk space
  • Shows drives with less than 10GB free
  • Helps identify capacity issues early

Use case: Run daily via scheduled task. Get alerts before disks fill up.


Script 2: Find and Delete Old Files

Clean up old log files automatically:

powershell
$path = "C:\Logs"
$daysOld = 30
$deleteConfirm = $false  // Set to $true to actually delete

$oldFiles = Get-ChildItem $path -Recurse | 
    Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-$daysOld)}

if ($deleteConfirm) {
    $oldFiles | Remove-Item -Force
    Write-Host "Deleted $($oldFiles.Count) files older than $daysOld days"
} else {
    Write-Host "Found $($oldFiles.Count) files to delete (not actually deleting)"
    $oldFiles | Select-Object FullName, LastWriteTime
}

What it does:

  • Finds files older than 30 days
  • Shows what would be deleted (safe mode)
  • Actually deletes when confirmed

Use case: Automated log cleanup on servers.


Script 3: Monitor Critical Services

Ensure critical services stay running:

powershell
$criticalServices = @("W3SVC", "MSSQLSERVER", "BITS")
$servers = @("AppServer1", "AppServer2", "DBServer1")

foreach ($server in $servers) {
    foreach ($service in $criticalServices) {
        $status = Get-Service -ComputerName $server -Name $service -ErrorAction SilentlyContinue
        
        if ($status.Status -ne "Running") {
            Start-Service -InputObject $status -ErrorAction SilentlyContinue
            Write-Host "Service $service on $server was stopped. Restarting..."
        }
    }
}

What it does:

  • Checks if critical services are running
  • Restarts them if stopped
  • Logs actions

Use case: Run every 5 minutes via scheduled task. Auto-recovery for critical services.


Script 4: Bulk Password Reset

Reset passwords for multiple users:

powershell
$users = Import-Csv -Path "C:\users.csv"
$tempPassword = ConvertTo-SecureString "TempPass@123" -AsPlainText -Force

foreach ($user in $users) {
    try {
        Set-ADUserPassword -Identity $user.SamAccountName -NewPassword $tempPassword -Reset
        Write-Host "Password reset for $($user.Name)"
    } catch {
        Write-Host "Error resetting password for $($user.Name): $_"
    }
}

What it does:

  • Reads CSV file with usernames
  • Resets password for each user
  • Handles errors gracefully

Use case: Bulk password resets, onboarding multiple users.


Script 5: Export Active Directory Users

Get all users and export to CSV:

powershell
Get-ADUser -Filter * -Properties Name, EmailAddress, Enabled, LastLogonDate |
    Select-Object Name, SamAccountName, EmailAddress, Enabled, LastLogonDate |
    Export-Csv -Path "C:\AllUsers.csv" -NoTypeInformation

Write-Host "User list exported to C:\AllUsers.csv"

What it does:

  • Gets all AD users
  • Exports to Excel-compatible CSV
  • Can be filtered/analyzed in spreadsheet

Use case: User audits, management reports.


Part 3: Common Mistakes to Avoid

Mistake 1: Not Testing Before Running

Bad approach:

powershell
// Write script
// Run on production immediately
// Oops, deleted wrong files

Good approach:

powershell
// Write script
// Test on test servers first
// Verify output is correct
// Then run on production

Best practice: Always test scripts in non-production environment first.


Mistake 2: Ignoring Error Handling

Bad:

powershell
Get-Service -ComputerName $server -Name "ServiceName"
// If server is offline, script crashes

Good:

powershell
try {
    Get-Service -ComputerName $server -Name "ServiceName"
} catch {
    Write-Host "Error connecting to $server: $_"
    // Script continues
}

Best practice: Always include error handling for network operations.


Mistake 3: Hardcoded Values

Bad:

powershell
$path = "C:\Logs"
// Want to use different path? Edit script

Good:

powershell
param(
    [string]$Path = "C:\Logs",
    [int]$DaysOld = 30
)

Get-ChildItem $Path -Recurse | 
    Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-$DaysOld)}

Use it:

powershell
.\CleanLogs.ps1 -Path "D:\OldLogs" -DaysOld 60

Best practice: Use parameters for flexibility.


Mistake 4: Not Scheduling Properly

Bad:

  • Write script
  • Run manually every week
  • Forget sometimes
  • Problems occur

Good:

  • Write script
  • Schedule in Windows Task Scheduler
  • Runs automatically
  • Consistent execution

Best practice: Automate recurring tasks with scheduled tasks.

useful Links:
Microsoft PowerShell docs


Part 4: PowerShell Best Practices

Write Clean Code

powershell
// Good variable names
$serverName = "Server1"
$diskSpace = Get-Volume

// Bad variable names
$s = "Server1"
$x = Get-Volume

Add Comments

powershell
// What this does
$servers = "Server1", "Server2"

// Loop through each server
foreach ($server in $servers) {
    // Check if server is reachable
    if (Test-Connection -ComputerName $server -Quiet) {
        // Get services
        Get-Service -ComputerName $server
    }
}

Use Functions for Reusable Code

powershell
function Get-DiskSpace {
    param([string]$ComputerName)
    
    Get-Volume -ComputerName $ComputerName |
        Select-Object ComputerName, DriveLetter, SizeRemaining
}

// Now reuse in multiple scripts
Get-DiskSpace -ComputerName "Server1"
Get-DiskSpace -ComputerName "Server2"

Part 5: Learning Resources

Official Resources

  • Microsoft PowerShell Documentation
  • PowerShell Gallery (scripts library)
  • Stack Overflow (PowerShell tag)

Best Practices

  • Test before running on production
  • Use error handling
  • Document what your scripts do
  • Use version control (Git)
  • Schedule important tasks

Common Tasks

  • Active Directory automation
  • File management
  • Service monitoring
  • User management
  • Report generation

Conclusion: Start Small, Build Skills

PowerShell is powerful because it automates repetitive work.

Start with simple scripts:

  1. Get information
  2. Filter results
  3. Take action

Master those basics.

Everything else is building on that foundation.

The best time to learn PowerShell was yesterday. The second best time is today.

Mo Assem

My name is Mohamed Assem, and I am a Cloud & Infrastructure Engineer with over 14 years of experience in IT, working across both Microsoft Azure and AWS. My expertise lies in cloud operations, automation, and building modern, scalable infrastructure. I design and implement CI/CD pipelines and infrastructure as code solutions using tools like Terraform and Docker to streamline operations and improve efficiency. Open to relocation to Europe for senior infrastructure and cloud engineering roles. Through my blog, TechWithAssem, I share practical tutorials, real-world implementations, and step-by-step guides to help engineers grow in Cloud and DevOps.

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button