Created
May 21, 2025 10:22
-
-
Save christiangda/ed6b94734292425eb549c7946889c015 to your computer and use it in GitHub Desktop.
Powershell script to check my external IP periodically
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Checks and logs the external IP address at a specified interval. | |
.DESCRIPTION | |
This script periodically fetches the public IP address from a specified web service | |
and logs it to a file and the console. The check period, IP endpoint, and log file | |
can be customized via parameters. | |
.PARAMETER PeriodSeconds | |
The interval in seconds at which to check the IP address. Must be a positive integer. | |
Default is 60 seconds. | |
.PARAMETER Endpoint | |
The URL of the service to use for checking the IP address (e.g., "ifconfig.me", "ipinfo.io/ip"). | |
Default is "ifconfig.me". | |
.PARAMETER LogFile | |
The path to the log file where IP address checks will be recorded. | |
Default is "external_ip.log" in the script's directory. | |
.PARAMETER Help | |
Displays this help message. | |
.EXAMPLE | |
.\Get-ExternalIpPeriodically.ps1 | |
Runs with default settings: checks every 60 seconds using ifconfig.me, logs to external_ip.log. | |
.EXAMPLE | |
.\Get-ExternalIpPeriodically.ps1 -PeriodSeconds 30 | |
Checks the IP every 30 seconds. | |
.EXAMPLE | |
.\Get-ExternalIpPeriodically.ps1 -PeriodSeconds 120 -Endpoint "ipinfo.io/ip" | |
Checks every 2 minutes using the ipinfo.io/ip service. | |
.EXAMPLE | |
.\Get-ExternalIpPeriodically.ps1 -LogFile "C:\Logs\MyPublicIP.txt" -PeriodSeconds 300 | |
Checks every 5 minutes and logs to C:\Logs\MyPublicIP.txt. | |
.EXAMPLE | |
.\Get-ExternalIpPeriodically.ps1 -Help | |
Displays the help information. | |
.NOTES | |
Author: Gemini | |
Version: 1.0 | |
To stop the script, press Ctrl+C. | |
Ensure your PowerShell execution policy allows running scripts. | |
You might need to run: Set-ExecutionPolicy RemoteSigned -Scope CurrentUser | |
#> | |
[CmdletBinding()] | |
param( | |
[Parameter(Mandatory=$false, HelpMessage="Check period in seconds (e.g., 30 for 30 seconds). Default: 60")] | |
[ValidateRange(1, [int]::MaxValue)] # Ensures it's a positive integer | |
[int]$PeriodSeconds = 60, | |
[Parameter(Mandatory=$false, HelpMessage="IP check endpoint (e.g., 'ipinfo.io/ip', 'api.ipify.org'). Default: 'ifconfig.me'")] | |
[string]$Endpoint = "ifconfig.me", | |
[Parameter(Mandatory=$false, HelpMessage="Path to the log file. Default: 'external_ip.log' in script directory")] | |
[string]$LogFile = (Join-Path $PSScriptRoot "external_ip.log"), | |
[Parameter(Mandatory=$false, HelpMessage="Display this help message.")] | |
[switch]$Help | |
) | |
# --- Function to display usage (using Get-Help) --- | |
if ($Help) { | |
Get-Help $MyInvocation.MyCommand.Definition -Full | |
exit 0 | |
} | |
# --- Function to get the external IP address --- | |
function Get-ExternalIp { | |
param( | |
[string]$CurrentEndpoint, | |
[string]$CurrentLogFile, | |
[int]$CurrentPeriodSeconds | |
) | |
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" | |
$ExternalIp = $null | |
$LogMessage = "" | |
try { | |
# Add "http://" or "https://" if not present, common for simple endpoints like "ifconfig.me" | |
$Uri = $CurrentEndpoint | |
if (-not ($Uri.StartsWith("http://") -or $Uri.StartsWith("https://"))) { | |
$Uri = "http://" + $Uri # Default to http, some services might require https | |
} | |
# Invoke-RestMethod is often better for APIs as it tries to parse the result | |
# Using -UseBasicParsing to avoid issues with IE first launch configuration | |
# Setting a timeout for the web request | |
Write-Verbose "Attempting to fetch IP from $Uri" | |
$ExternalIp = Invoke-RestMethod -Uri $Uri -TimeoutSec 10 -UseBasicParsing | |
} | |
catch { | |
$ErrorMessage = $_.Exception.Message | |
$LogMessage = "$Timestamp - Error: Could not retrieve IP from $CurrentEndpoint. Details: $ErrorMessage (Period: ${CurrentPeriodSeconds}s)" | |
Write-Warning $LogMessage | |
$LogMessage | Add-Content -Path $CurrentLogFile | |
return # Exit function on error | |
} | |
if (-not [string]::IsNullOrWhiteSpace($ExternalIp)) { | |
# Basic validation for an IP address format (can be improved for stricter IPv4/IPv6 checks) | |
# This regex matches common IPv4 and IPv6 patterns. | |
$IpPattern = '^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$|^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4})$' | |
if ($ExternalIp -match $IpPattern) { | |
$LogMessage = "$Timestamp - External IP: $ExternalIp (Endpoint: $CurrentEndpoint, Period: ${CurrentPeriodSeconds}s)" | |
Write-Host $LogMessage -ForegroundColor Green | |
} else { | |
$LogMessage = "$Timestamp - Warning: Received non-IP response from $CurrentEndpoint: '$ExternalIp' (Period: ${CurrentPeriodSeconds}s)" | |
Write-Warning $LogMessage | |
} | |
} else { | |
$LogMessage = "$Timestamp - Warning: Received empty response from $CurrentEndpoint. (Period: ${CurrentPeriodSeconds}s)" | |
Write-Warning $LogMessage | |
} | |
# Log to file | |
if (-not [string]::IsNullOrWhiteSpace($LogMessage)) { | |
try { | |
$LogMessage | Add-Content -Path $CurrentLogFile -ErrorAction Stop | |
} | |
catch { | |
Write-Error "Failed to write to log file $CurrentLogFile. Error: $($_.Exception.Message)" | |
} | |
} | |
} | |
# --- Main loop --- | |
Write-Host "Starting IP check..." -ForegroundColor Cyan | |
Write-Host "Check Period: $($PeriodSeconds) seconds" -ForegroundColor Cyan | |
Write-Host "IP Endpoint: $Endpoint" -ForegroundColor Cyan | |
Write-Host "Log File: $LogFile" -ForegroundColor Cyan | |
Write-Host "Press Ctrl+C to stop." -ForegroundColor Yellow | |
# Create log file directory if it doesn't exist | |
$LogDirectory = Split-Path -Path $LogFile -Parent | |
if (-not (Test-Path $LogDirectory)) { | |
try { | |
New-Item -ItemType Directory -Path $LogDirectory -Force -ErrorAction Stop | Out-Null | |
Write-Verbose "Created log directory: $LogDirectory" | |
} | |
catch { | |
Write-Error "Could not create log directory: $LogDirectory. Error: $($_.Exception.Message)" | |
Write-Error "Please create the directory manually or choose a different log file path." | |
exit 1 | |
} | |
} | |
# Trap Ctrl+C for graceful exit | |
trap { | |
Write-Host "Script interrupted. Exiting." -ForegroundColor Yellow | |
break # Breaks out of the loop | |
} | |
while ($true) { | |
Get-ExternalIp -CurrentEndpoint $Endpoint -CurrentLogFile $LogFile -CurrentPeriodSeconds $PeriodSeconds | |
Start-Sleep -Seconds $PeriodSeconds | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment