Study guide

4.3 Practical Shell Scripting & Automation

Google IT Support Professional Certificate Exam

Track your progress as you read

Finished sections get a check mark.

1 Chapter 1: Program Overview & Technical Support Fundamentals

1.1 Certificate Overview & Core Hardware 1.2 PC Assembly, BIOS/UEFI & Boot Sequence 1.3 Troubleshooting Methodology & Customer Service

2 Chapter 2: The Bits and Bytes of Computer Networking

2.1 Network Models & Physical Layer 2.2 Network Layer & IP Addressing 2.3 Transport & Application Layer Protocols 2.4 Wireless, Remote Access & Network Diagnostics

3 Chapter 3: Operating Systems — Windows & Linux Power User Basics

3.1 OS Architecture & Shell Navigation 3.2 User Accounts, Groups & Access Control 3.3 Package Management & Software Deployment

4 Chapter 4: Operating Systems — Process Management, Filesystems & Scripting

4.1 Process Management & System Logging 4.2 Filesystem Types & Storage Management 4.3 Practical Shell Scripting & Automation

5 Chapter 5: System Administration & IT Infrastructure Services

5.1 Sysadmin Role & IT Policies 5.2 Core Infrastructure Services: DNS, DHCP & NTP 5.3 Directory Services: Active Directory & LDAP

6 Chapter 6: Cloud Services, Systems Management & Disaster Recovery

6.1 Cloud Models & Enterprise Storage 6.2 OS Imaging & Configuration Management 6.3 Backup Strategies & Disaster Recovery

7 Chapter 7: IT Security — Defense Against the Digital Dark Arts

7.1 Security Principles & Threat Landscape 7.2 Cryptography & Public Key Infrastructure 7.3 AAA, Network Defense & Incident Response

4.3 Practical Shell Scripting & Automation

Key Takeaways Explain This Topic AI

Shell scripting empowers IT support teams to automate repetitive administrative workflows, enforce deterministic system configurations, eliminate manual operator errors, and execute unattended maintenance.

Linux Bash scripts utilize a shebang line (#!/bin/bash), require execute permissions (chmod +x), leverage positional parameters ($0 to $9, $#, $?), and execute conditional logic using standard bracket evaluation ([ condition ] or [[ condition ]]).

Windows PowerShell scripts (.ps1) operate within an Execution Policy security framework (Get-ExecutionPolicy, Set-ExecutionPolicy RemoteSigned), passing strongly typed .NET objects across pipelines via ForEach-Object (%) and Where-Object (?).

Task automation is orchestrated via background schedulers: Linux utilizes the cron daemon with 5-field crontab syntax alongside precision systemd timers, while Windows leverages Task Scheduler (taskschd.msc), schtasks.exe, and Register-ScheduledTask.

Defensive scripting practices—such as evaluating exit codes ($?), enforcing strict error modes (set -eu in Bash, $ErrorActionPreference = 'Stop' in PowerShell), and writing structured audit logs—are essential for robust enterprise automation.

Last updated: August 2026

Practical Shell Scripting & Automation

In modern enterprise IT environments managing thousands of client workstations, virtual machines, and cloud server instances, manual point-and-click administration does not scale. Repetitive tasks—such as provisioning new employee user accounts, auditing dormant logins, monitoring free disk thresholds, rotating log archives, and enforcing security configurations—must be automated. Shell scripting provides the bridge between manual interactive commands and fully autonomous system administration.

1. Scripting Foundations for Enterprise IT Support +-----------------------------------------------------------------------------+

  • | WHY SCRIPT? THE POWER OF IT AUTOMATION |
  • | |
  • | - REPEATABILITY: Executes identical steps deterministically every time.|
  • | - ERROR REDUCTION: Eliminates typos and missed steps in manual workflows.|
  • | - SCALABILITY: Manages 10,000 servers as easily as managing 1. |
  • | - AUDITABILITY: Scripts can be version-controlled in Git repositories.|
  • | - UNATTENDED: Executes off-hours maintenance via background timers. |
  • +-----------------------------------------------------------------------------+
  • Scripting vs. Compiled Programming

Shell Scripts (Interpreted): Plaintext files containing sequences of commands executed line-by-line by a shell interpreter (e.g., /bin/bash or pwsh ). Shell scripts require no compilation step, have instant development turnaround, and directly invoke underlying operating system binaries and APIs.

Compiled Programs (C, C++, Rust, Go): Source code compiled by a compiler into standalone binary machine code. Compiled languages offer raw execution speed for intensive algorithms, but are heavier and less agile for routine OS administration and pipeline glue tasks.

2. Linux Bash Scripting Fundamentals

Bash (Bourne Again Shell) is the industry-standard scripting language for Linux systems administration. +-----------------------------------------------------------------------------+

  • | ANATOMY OF A BASH SCRIPT |
  • | |
  • | #!/bin/bash <-- 1. Shebang Line |
  • | # Automated Maintenance Script <-- 2. Comment / Metadata |
  • | set -euo pipefail <-- 3. Defensive Shell Flags |
  • | |
  • | LOG_DIR="/var/log/custom_app" <-- 4. Variable Declaration |
  • | THRESHOLD=85 |
  • | |
  • | if [ ! -d "$LOG_DIR" ]; then <-- 5. Conditional Logic |
  • | echo "Error: Log dir missing!" >&2 |
  • | exit 1 <-- 6. Exit Status Code |
  • | fi |
  • +-----------------------------------------------------------------------------+
  • The Shebang Line & File Permissions

The Shebang ( #! ): The very first line of an executable script. It informs the operating system kernel's execve() system call which interpreter binary to load:

#!/bin/bash : Standard Bash path on Linux.

#!/usr/bin/env bash : Portable shebang that searches the user's $PATH for the Bash binary.

Execution Permissions: Before a script can be executed directly as ./script.sh , it must be granted execution permissions via chmod +x script.sh .

Execution Invocation Methods:

./script.sh : Runs the script in a dedicated child subshell. Requires chmod +x .

bash script.sh : Explicitly launches Bash to run the script in a subshell (does not require execute bit).

. script.sh or source script.sh : Executes the script directly inside the current active shell environment . Any variable changes or directory changes ( cd ) persist in the user's active session.

Variables, Quotes & Positional Parameters

Variable Assignment Rules: No spaces are permitted around the = assignment operator ( BACKUP_DIR="/opt/backup" is valid; BACKUP_DIR = "/opt/backup" throws a command-not-found error).

Variable Expansion: Reference variables using $VAR_NAME or ${VAR_NAME} ( echo "Target: ${BACKUP_DIR}_old" ).

Quoting Mechanics:

"Double Quotes" : Perform variable expansion and command substitution ( echo "User is $USER on $(hostname)" ).

'Single Quotes' : Treat all characters strictly as raw literals with zero expansion ( echo '$USER' outputs $USER ).

$(command) : Command Substitution —executes a command and captures its stdout into a variable ( TODAY=$(date +%Y-%m-%d) ).

Positional Parameters & Automatic Variables

Variable Definition & Contents

$0 The name/path of the executing script itself (e.g., ./backup.sh ).

$1 to $9 The first through ninth command-line positional arguments passed to the script.

${10} + Positional arguments beyond 9 (must be enclosed in curly braces).

$# The total integer count of positional arguments passed to the script.

$@ All positional arguments as separate individual quoted strings ( "$1" "$2" "$3" ). Recommended for loops.

$* All positional arguments joined together into a single string ( "$1 $2 $3" ).

$$ The Process ID (PID) of the currently running script process.

$? The Exit Status of the most recently executed command ( 0 = Success; 1–255 = Error).

Conditionals & Test Operators

Conditionals evaluate expressions using [ condition ] (standard POSIX test ) or [[ condition ]] (extended Bash test supporting regular expressions and boolean && / || ). # Bash If-Else Syntax:

  • if [ condition ]; then
  • # commands
  • elif [ condition ]; then
  • # commands
  • else
  • # commands
  • fi
  • Bash vs. PowerShell Comparison Operators

Operation / Test Bash Numeric / String Operator Bash File Test Operator PowerShell Operator Example (Bash vs. PowerShell)

  • Equal To -eq (numeric) / == (string) N/A -eq [ $COUNT -eq 10 ] vs $Count -eq 10
  • Not Equal To -ne (numeric) / != (string) N/A -ne [ $STATUS != "OK" ] vs $Status -ne "OK"
  • Greater Than -gt (numeric) N/A -gt [ $USAGE -gt 90 ] vs $Usage -gt 90
  • Less Than -lt (numeric) N/A -lt [ $AGE -lt 30 ] vs $Age -lt 30
  • String Empty / Zero-Length -z "$STR" N/A [string]::IsNullOrEmpty($str) if [ -z "$VAR" ] vs if (-not $Var)
  • String Non-Empty -n "$STR" N/A [bool]$str if [ -n "$VAR" ] vs if ($Var)

File Exists & Is Regular File N/A -f <file> Test-Path -PathType Leaf if [ -f "$FILE" ] vs Test-Path $File -PathType Leaf

Directory Exists N/A -d <dir> Test-Path -PathType Container if [ -d "$DIR" ] vs Test-Path $Dir -PathType Container

File Size Greater Than Zero N/A -s <file> (Get-Item $File).Length -gt 0 if [ -s "$LOG" ] vs (Get-Item $Log).Length -gt 0

  • Wildcard Match [[ $str == *.log ]] N/A -like [[ $file == *.txt ]] vs $File -like "*.txt"
  • Regex Match [[ $str =~ ^[0-9]+$ ]] N/A -match [[ $ip =~ ^192. ]] vs $IP -match "^192."
  • Practical Linux IT Administration Scripts
  • 1. Automated Disk Space Alert Script #!/bin/bash
  • # Disk Space Monitoring & Alerting Script
  • set -euo pipefail
  • THRESHOLD=85
  • CURRENT_USAGE=$(df / | grep / | awk '{ print $5 }' | sed 's/%//g')
  • if [ "$CURRENT_USAGE" -ge "$THRESHOLD" ]; then
  • MESSAGE="WARNING: Root filesystem disk usage is at ${CURRENT_USAGE}% on $(hostname)!"
  • logger -t DISK_MONITOR "$MESSAGE"
  • echo "$MESSAGE" | mail -s "Disk Space Alert: $(hostname)" sysadmin@example.com
  • else
  • logger -t DISK_MONITOR "Disk space normal at ${CURRENT_USAGE}%."
  • fi
  • 2. Bulk User Provisioning Script #!/bin/bash
  • # Provisions users from a CSV file (Format: username,group,fullname)
  • set -euo pipefail

CSV_FILE="/root/new_users.csv"

  • if [ ! -f "$CSV_FILE" ]; then
  • echo "Error: User list $CSV_FILE not found." >&2
  • exit 1
  • fi
  • while IFS=',' read -r USERNAME GROUP FULLNAME; do
  • # Skip empty lines or header
  • [ -z "$USERNAME" ] || [ "$USERNAME" == "username" ] && continue
  • # Create group if missing
  • if ! getent group "$GROUP" > /dev/null 2>&1; then
  • groupadd "$GROUP"
  • fi
  • # Create user with home directory and primary group
  • if ! id "$USERNAME" > /dev/null 2>&1; then
  • useradd -m -s /bin/bash -c "$FULLNAME" -g "$GROUP" "$USERNAME"
  • echo "User $USERNAME created successfully."
  • else
  • echo "Notice: User $USERNAME already exists. Skipping."
  • fi
  • done < "$CSV_FILE"
  • 3. Log Rotation & Compression Script #!/bin/bash
  • # Compresses and archives logs older than 30 days
  • set -euo pipefail
  • LOG_SRC="/var/log/custom_app"
  • ARCHIVE_DST="/backup/log_archives"
  • TIMESTAMP=$(date +%Y%m%d_%H%M%S)

mkdir -p "$ARCHIVE_DST"

  • # Find and package log files older than 30 days
  • OLD_LOGS=$(find "$LOG_SRC" -name "*.log" -type f -mtime +30)
  • if [ -n "$OLD_LOGS" ]; then
  • tar -czf "${ARCHIVE_DST}/logs_archived_${TIMESTAMP}.tar.gz" $OLD_LOGS
  • find "$LOG_SRC" -name "*.log" -type f -mtime +30 -delete
  • logger -t LOG_ARCHIVER "Archived and purged old logs successfully."
  • fi
  • 3. Windows PowerShell Scripting

PowerShell is an object-oriented shell and scripting framework built on Microsoft .NET. +-----------------------------------------------------------------------------+

  • | POWERSHELL EXECUTION & OBJECT MODEL |
  • | |
  • | [Execution Policy Security Filter] |
  • | Get-ExecutionPolicy / Set-ExecutionPolicy RemoteSigned -Scope CurrentUser |
  • | |
  • | [Structured Object Pipeline] |
  • | Get-Service | Where-Object Status -eq 'Stopped' | Start-Service |
  • | (Passes System.ServiceProcess.ServiceController .NET Objects) |
  • +-----------------------------------------------------------------------------+
  • PowerShell Execution Policy

To prevent users from inadvertently executing malicious scripts downloaded from the web, PowerShell enforces an Execution Policy . Note: The Execution Policy is a safety barrier against accidental execution, not a cryptographic security boundary.

Restricted : Default on client Windows. Blocks all script ( .ps1 ) execution; permits interactive commands only.

AllSigned : Only scripts digitally signed by a trusted certificate publisher can execute.

RemoteSigned : Default on Windows Server. Scripts written locally run without signatures; scripts downloaded from the Internet (bearing an alternate data stream mark of the web) must be digitally signed.

Unrestricted : Runs all scripts; prompts a warning before executing downloaded internet scripts.

Bypass : Nothing is blocked and no warning prompts are shown (commonly used in automated deployment pipelines).

Configuring Policy: # Check current execution policy across scopes:

Get-ExecutionPolicy -List

# Set policy to RemoteSigned for the current user:

  • Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser -Force
  • PowerShell Script Syntax, Variables & Collections

Variables: Prefixed with $ ( $ComputerName = $env:COMPUTERNAME ).

Arrays: Defined using @(item1, item2, item3) or comma-separated lists ( $Servers = @("DC01", "WEB01", "DB01") ). Access via index: $Servers[0] .

Hashtables (Dictionaries): Defined using @{ Key = 'Value' } ( $User = @{ Name = 'Alice'; Role = 'Sysadmin'; Department = 'IT' } ). Access via $User.Role .

Environment Variables: Accessed via $env:VARIABLE_NAME (e.g., $env:USERPROFILE , $env:TEMP , $env:PATH ).

Pipeline Filtering: Where-Object & ForEach-Object

Where-Object (Alias: ? ): Filters objects in the pipeline based on conditional evaluations.

ForEach-Object (Alias: % ): Iterates over every individual object in the pipeline, referencing the current item using $_ or $PSItem .

  • Practical Windows Administration Scripts
  • 1. Bulk CSV User Creation Script # Bulk Local User Provisioning from CSV
  • # CSV Columns: Username, FullName, Department, Description

$CsvPath = "C:/Scripts/NewUsers.csv"

  • if (-not (Test-Path -Path $CsvPath)) {
  • Write-Error "CSV input file not found at $CsvPath"
  • exit 1
  • }

$Users = Import-Csv -Path $CsvPath

  • foreach ($User in $Users) {
  • if (-not (Get-LocalUser -Name $User.Username -ErrorAction SilentlyContinue)) {
  • $TempPassword = ConvertTo-SecureString "P@ssw0rd1234!" -AsPlainText -Force
  • New-LocalUser -Name $User.Username `
  • FullName $User.FullName `
  • Description $User.Description `
  • Password $TempPassword `
  • PasswordNeverExpires:$false
  • Write-Host "Created user: $($User.Username)" -ForegroundColor Green
  • } else {
  • Write-Warning "User $($User.Username) already exists. Skipping."
  • }
  • }

2. Inactive User Account Audit & Remediation # Audits local accounts inactive for over 90 days and disables them

$ThresholdDate = (Get-Date).AddDays(-90)

  • $InactiveUsers = Get-LocalUser | Where-Object {
  • $_.Enabled -eq $true -and
  • $_.LastLogon -ne $null -and
  • $_.LastLogon -lt $ThresholdDate
  • }
  • foreach ($Account in $InactiveUsers) {
  • Disable-LocalUser -Name $Account.Name
  • Write-EventLog -LogName Application -Source "IT_Audit" -EventId 2001 `
  • EntryType Warning `
  • Message "Disabled inactive local account: $($Account.Name)"
  • Write-Host "Disabled dormant account: $($Account.Name)" -ForegroundColor Yellow
  • }
  • 3. Service Auto-Recovery Watchdog # Watchdog script to monitor and auto-restart critical Windows services
  • $CriticalServices = @("Spooler", "wuauserv", "W32Time")
  • foreach ($ServiceName in $CriticalServices) {
  • $Service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
  • if ($Service -and $Service.Status -ne 'Running') {
  • Write-Warning "Service $ServiceName is stopped. Attempting restart..."
  • try {
  • Start-Service -Name $ServiceName -ErrorAction Stop
  • Write-Host "Successfully restarted $ServiceName." -ForegroundColor Green
  • } catch {
  • Write-Error "Failed to start $ServiceName. Reason: $($_.Exception.Message)"
  • }
  • }
  • }
  • 4. Task Scheduling & Automation (Cron, Systemd Timers & Task Scheduler)

Automating scripts requires scheduling daemons that execute jobs at precise calendar times, recurring intervals, or upon specific system events. +-----------------------------------------------------------------------------+

  • | CRONTAB 5-FIELD SYNTAX FORMAT |
  • | |
  • | * * * * * /path/to/script.sh |
  • | | | | | | |
  • | | | | | +---- Day of Week (0 - 7) (0/7 = Sunday) |
  • | | | | +------------ Month (1 - 12) |
  • | | | +-------------------- Day of Month (1 - 31) |
  • | | +---------------------------- Hour (0 - 23) |
  • | +------------------------------------ Minute (0 - 59) |
  • +-----------------------------------------------------------------------------+
  • Linux cron Daemon & Crontab Syntax

The crond daemon wakes up every 60 seconds, evaluates user and system crontabs, and executes any scheduled commands matching the current minute.

Crontab Commands:

crontab -e : Edits the current user's crontab file using the default editor.

crontab -l : Displays the current user's crontab entries.

crontab -r : Purges and removes the current user's crontab file.

sudo crontab -u alice -e : Allows administrators to edit another user's crontab.

Crontab Schedule Expression Examples

Expression Schedule Execution Time

30 2 * * * Every day at exactly 02:30 AM .

0 0 * * 0 (or @weekly ) Every Sunday at midnight (00:00).

*/15 * * * * Every 15 minutes past the hour.

0 9-17 * * 1-5 Every hour on the hour from 9:00 AM to 5:00 PM , Monday through Friday .

0 0 1,15 * * At midnight on the 1st and 15th day of every month.

@reboot Executes once immediately after the operating system boots up.

Linux systemd Timers

Modern enterprise Linux systems increasingly utilize systemd Timers as a robust alternative to cron:

Monotonic Timers: Can trigger tasks relative to boot time ( OnBootSec=15min ) or relative to previous task completion ( OnUnitActiveSec=1h ).

Real-Time Calendar Timers: Trigger at exact calendar dates ( OnCalendar=*-*-* 04:00:00 ).

Benefits over Cron: Tight integration with systemd cgroups, CPU/memory resource throttling, automatic logging to journalctl , and failure dependency tracking.

Management: systemctl list-timers .

Windows Task Scheduler ( taskschd.msc )

Windows Task Scheduler automates tasks across four core components:

Triggers: When the task executes (Schedule: Daily/Weekly; System Event: At Startup, On User Logon, On specific Event ID).

Actions: What the task does (e.g., Program: powershell.exe , Arguments: -ExecutionPolicy Bypass -File C:/Scripts/audit.ps1 ).

Conditions: Safeguards (Run only if computer is connected to AC power, Start only if network is available).

Settings: Operational behaviors (Restart if task fails, Stop task if it runs longer than 2 hours).

Command-Line Scheduling with schtasks.exe and PowerShell :: Create a daily task running at 3:00 AM under the SYSTEM account:

schtasks /create /tn "DailyLogCleanup" /tr "powershell.exe -ExecutionPolicy Bypass -File C:/Scripts/cleanup.ps1" /sc daily /st 03:00 /ru "SYSTEM"

:: Query task status:

schtasks /query /tn "DailyLogCleanup" /fo list /v # PowerShell Scheduled Task Creation:

  • $Action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-File C:/Scripts/backup.ps1"
  • $Trigger = New-ScheduledTaskTrigger -Daily -At 2:00AM
  • $Principal = New-ScheduledTaskPrincipal -UserId "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount
  • Register-ScheduledTask -TaskName "EnterpriseBackup" -Action $Action -Trigger $Trigger -Principal $Principal
  • 5. Defensive Scripting, Structured Logging & Exit Codes

Unattended enterprise scripts must handle unexpected errors gracefully, validate inputs, and report standard exit codes.

Standard POSIX Exit Codes

Exit Code Standard Meaning Operational Trigger / Cause

0 Success Command completed normally with zero errors.

1 General Catchall Error Miscellaneous operational failure (e.g., file not found, permission denied).

2 Misuse of Shell Builtins Syntax error in script command or missing required argument.

126 Command Cannot Execute Target file found but lacks executable permissions ( chmod +x ).

127 Command Not Found Binary or script does not exist in $PATH .

130 Script Terminated by Ctrl+C Process received SIGINT (128 + 2).

137 Script Killed by SIGKILL Process terminated forcefully by kernel Out-Of-Memory (OOM) killer or kill -9 (128 + 9).

  • Defensive Bash Header
  • Enterprise Bash scripts should always begin with strict safety flags: #!/bin/bash
  • # -e: Exit immediately if any command returns a non-zero exit status
  • # -u: Treat unset/uninitialized variables as an error and exit immediately
  • # -o pipefail: Pipeline returns exit status of the rightmost command to fail
  • set -euo pipefail

Loading diagram... Linux Crontab Evaluation & Background Execution Architecture

Loading diagram... Windows PowerShell Automation Pipeline & Error Handling Workflow