Sync all scripts from website downloads — 352 scripts total
Includes updated JS challenge scripts with Claude-User whitelist, same-site referer bypass, Blackbox-Exporter allowed bot, and all new exporters, cheat sheets, and automation scripts.
This commit is contained in:
@@ -0,0 +1,293 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Windows Print Server Prometheus Metrics Exporter
|
||||
.DESCRIPTION
|
||||
Prometheus exporter for Windows Print Server. Monitors print queues, job
|
||||
counts, job status, printer errors, spooler health, and driver information.
|
||||
Exports metrics as Prometheus-compatible text format for windows_exporter
|
||||
textfile collector or standalone HTTP listener.
|
||||
.PARAMETER Mode
|
||||
Output mode: 'stdout' (default), 'textfile', or 'http'
|
||||
.PARAMETER Port
|
||||
HTTP port for http mode (default: 9197)
|
||||
.PARAMETER TextfileDir
|
||||
Directory for textfile collector output (default: C:\ProgramData\node_exporter)
|
||||
.PARAMETER OutputFile
|
||||
Custom output file path
|
||||
.PARAMETER InstallScheduledTask
|
||||
Switch to create a scheduled task for automatic collection
|
||||
.PARAMETER TaskIntervalMinutes
|
||||
Interval in minutes for the scheduled task (default: 2)
|
||||
.NOTES
|
||||
Author: Phil Connor
|
||||
Contact: contact@mylinux.work
|
||||
Website: https://mylinux.work
|
||||
License: MIT
|
||||
Version: 1.0
|
||||
#>
|
||||
|
||||
param(
|
||||
[switch]$TextFile,
|
||||
[string]$OutFile = "",
|
||||
[switch]$Install,
|
||||
[string]$Listen = "",
|
||||
[int]$Interval = 120
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "SilentlyContinue"
|
||||
$Version = "1.0"
|
||||
$TextfileDir = "C:\ProgramData\node_exporter"
|
||||
$MetricPrefix = "windows_print"
|
||||
|
||||
# ============================================================================
|
||||
# HELPER FUNCTIONS
|
||||
# ============================================================================
|
||||
|
||||
function Get-PrometheusEscape {
|
||||
param([string]$Value)
|
||||
$Value -replace '\\', '\\' -replace '"', '\"' -replace "`n", ''
|
||||
}
|
||||
|
||||
function Write-MetricHeader {
|
||||
param([string]$Name, [string]$Help, [string]$Type)
|
||||
"# HELP $Name $Help"
|
||||
"# TYPE $Name $Type"
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# METRIC GENERATION
|
||||
# ============================================================================
|
||||
|
||||
function Get-PrintMetrics {
|
||||
$startTime = Get-Date
|
||||
$metrics = [System.Collections.ArrayList]::new()
|
||||
|
||||
# Check if Print Spooler is running
|
||||
$spooler = Get-Service -Name "Spooler" -ErrorAction SilentlyContinue
|
||||
$spoolerUp = if ($spooler -and $spooler.Status -eq "Running") { 1 } else { 0 }
|
||||
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_up" "Print server exporter status (1=up, 0=down)" "gauge"))
|
||||
[void]$metrics.Add("${MetricPrefix}_up $spoolerUp")
|
||||
[void]$metrics.Add("")
|
||||
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_exporter_info" "Exporter version information" "gauge"))
|
||||
[void]$metrics.Add("${MetricPrefix}_exporter_info{version=`"$Version`"} 1")
|
||||
[void]$metrics.Add("")
|
||||
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_spooler_up" "Print Spooler service status" "gauge"))
|
||||
[void]$metrics.Add("${MetricPrefix}_spooler_up $spoolerUp")
|
||||
[void]$metrics.Add("")
|
||||
|
||||
if ($spoolerUp -eq 0) {
|
||||
return ($metrics -join "`n")
|
||||
}
|
||||
|
||||
# ========================================================================
|
||||
# PRINTER METRICS
|
||||
# ========================================================================
|
||||
|
||||
$printers = Get-Printer -ErrorAction SilentlyContinue
|
||||
|
||||
$totalPrinters = 0
|
||||
$onlinePrinters = 0
|
||||
$offlinePrinters = 0
|
||||
$errorPrinters = 0
|
||||
|
||||
if ($printers) {
|
||||
$totalPrinters = @($printers).Count
|
||||
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_printers_total" "Total configured printers" "gauge"))
|
||||
[void]$metrics.Add("${MetricPrefix}_printers_total $totalPrinters")
|
||||
[void]$metrics.Add("")
|
||||
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_printer_status" "Printer status (1=current state)" "gauge"))
|
||||
|
||||
foreach ($printer in $printers) {
|
||||
$name = Get-PrometheusEscape $printer.Name
|
||||
$status = $printer.PrinterStatus.ToString()
|
||||
$shared = if ($printer.Shared) { "true" } else { "false" }
|
||||
|
||||
[void]$metrics.Add("${MetricPrefix}_printer_status{printer=`"$name`",status=`"$status`",shared=`"$shared`"} 1")
|
||||
|
||||
switch ($status) {
|
||||
"Normal" { $onlinePrinters++ }
|
||||
"Offline" { $offlinePrinters++ }
|
||||
default { $errorPrinters++ }
|
||||
}
|
||||
}
|
||||
[void]$metrics.Add("")
|
||||
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_printers_online" "Online printers" "gauge"))
|
||||
[void]$metrics.Add("${MetricPrefix}_printers_online $onlinePrinters")
|
||||
[void]$metrics.Add("")
|
||||
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_printers_offline" "Offline printers" "gauge"))
|
||||
[void]$metrics.Add("${MetricPrefix}_printers_offline $offlinePrinters")
|
||||
[void]$metrics.Add("")
|
||||
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_printers_error" "Printers in error state" "gauge"))
|
||||
[void]$metrics.Add("${MetricPrefix}_printers_error $errorPrinters")
|
||||
[void]$metrics.Add("")
|
||||
}
|
||||
|
||||
# ========================================================================
|
||||
# PRINT JOB METRICS
|
||||
# ========================================================================
|
||||
|
||||
$jobs = Get-PrintJob -PrinterName * -ErrorAction SilentlyContinue
|
||||
|
||||
$totalJobs = 0
|
||||
$printingJobs = 0
|
||||
$queuedJobs = 0
|
||||
$errorJobs = 0
|
||||
$totalPages = 0
|
||||
$totalBytes = 0
|
||||
|
||||
if ($jobs) {
|
||||
$totalJobs = @($jobs).Count
|
||||
|
||||
foreach ($job in $jobs) {
|
||||
$totalPages += $job.TotalPages
|
||||
$totalBytes += $job.Size
|
||||
|
||||
switch ($job.JobStatus) {
|
||||
{ $_ -match "Printing" } { $printingJobs++ }
|
||||
{ $_ -match "Error" } { $errorJobs++ }
|
||||
default { $queuedJobs++ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_jobs_total" "Total print jobs in queue" "gauge"))
|
||||
[void]$metrics.Add("${MetricPrefix}_jobs_total $totalJobs")
|
||||
[void]$metrics.Add("")
|
||||
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_jobs_printing" "Jobs currently printing" "gauge"))
|
||||
[void]$metrics.Add("${MetricPrefix}_jobs_printing $printingJobs")
|
||||
[void]$metrics.Add("")
|
||||
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_jobs_queued" "Jobs waiting in queue" "gauge"))
|
||||
[void]$metrics.Add("${MetricPrefix}_jobs_queued $queuedJobs")
|
||||
[void]$metrics.Add("")
|
||||
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_jobs_error" "Jobs in error state" "gauge"))
|
||||
[void]$metrics.Add("${MetricPrefix}_jobs_error $errorJobs")
|
||||
[void]$metrics.Add("")
|
||||
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_jobs_pages_total" "Total pages across all queued jobs" "gauge"))
|
||||
[void]$metrics.Add("${MetricPrefix}_jobs_pages_total $totalPages")
|
||||
[void]$metrics.Add("")
|
||||
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_jobs_bytes_total" "Total bytes across all queued jobs" "gauge"))
|
||||
[void]$metrics.Add("${MetricPrefix}_jobs_bytes_total $totalBytes")
|
||||
[void]$metrics.Add("")
|
||||
|
||||
# Per-printer job counts
|
||||
if ($printers -and $jobs) {
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_queue_jobs" "Jobs per printer queue" "gauge"))
|
||||
foreach ($printer in $printers) {
|
||||
$name = Get-PrometheusEscape $printer.Name
|
||||
$pJobs = @($jobs | Where-Object { $_.PrinterName -eq $printer.Name }).Count
|
||||
[void]$metrics.Add("${MetricPrefix}_queue_jobs{printer=`"$name`"} $pJobs")
|
||||
}
|
||||
[void]$metrics.Add("")
|
||||
}
|
||||
|
||||
# ========================================================================
|
||||
# PRINT PORT METRICS
|
||||
# ========================================================================
|
||||
|
||||
$ports = Get-PrinterPort -ErrorAction SilentlyContinue
|
||||
if ($ports) {
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_ports_total" "Total configured printer ports" "gauge"))
|
||||
[void]$metrics.Add("${MetricPrefix}_ports_total $(@($ports).Count)")
|
||||
[void]$metrics.Add("")
|
||||
}
|
||||
|
||||
# ========================================================================
|
||||
# DRIVER METRICS
|
||||
# ========================================================================
|
||||
|
||||
$drivers = Get-PrinterDriver -ErrorAction SilentlyContinue
|
||||
if ($drivers) {
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_drivers_total" "Total installed printer drivers" "gauge"))
|
||||
[void]$metrics.Add("${MetricPrefix}_drivers_total $(@($drivers).Count)")
|
||||
[void]$metrics.Add("")
|
||||
}
|
||||
|
||||
# ========================================================================
|
||||
# PERFORMANCE COUNTERS
|
||||
# ========================================================================
|
||||
|
||||
$perfCounter = Get-Counter -Counter "\Print Queue(_Total)\Total Jobs Printed" -ErrorAction SilentlyContinue
|
||||
if ($perfCounter) {
|
||||
$totalPrinted = [math]::Round($perfCounter.CounterSamples[0].CookedValue)
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_jobs_printed_total" "Total jobs printed (lifetime)" "counter"))
|
||||
[void]$metrics.Add("${MetricPrefix}_jobs_printed_total $totalPrinted")
|
||||
[void]$metrics.Add("")
|
||||
}
|
||||
|
||||
# ========================================================================
|
||||
# EXPORTER RUNTIME
|
||||
# ========================================================================
|
||||
|
||||
$endTime = Get-Date
|
||||
$duration = [math]::Round(($endTime - $startTime).TotalSeconds, 2)
|
||||
$timestamp = [math]::Round((Get-Date -UFormat %s), 0)
|
||||
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_exporter_duration_seconds" "Script execution time" "gauge"))
|
||||
[void]$metrics.Add("${MetricPrefix}_exporter_duration_seconds $duration")
|
||||
[void]$metrics.Add("")
|
||||
|
||||
[void]$metrics.Add((Write-MetricHeader "${MetricPrefix}_exporter_last_run_timestamp" "Unix timestamp of last run" "gauge"))
|
||||
[void]$metrics.Add("${MetricPrefix}_exporter_last_run_timestamp $timestamp")
|
||||
|
||||
return ($metrics -join "`n")
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# OUTPUT MODES
|
||||
# ============================================================================
|
||||
|
||||
if ($Install) {
|
||||
$scriptPath = $MyInvocation.MyCommand.Path
|
||||
$action = New-ScheduledTaskAction -Execute "powershell.exe" `
|
||||
-Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -TextFile"
|
||||
$trigger = New-ScheduledTaskTrigger -RepetitionInterval (New-TimeSpan -Seconds $Interval) -Once -At (Get-Date)
|
||||
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
|
||||
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable
|
||||
Register-ScheduledTask -TaskName "Print Server Metrics Exporter" -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force
|
||||
Write-Host "Scheduled task 'Print Server Metrics Exporter' created (interval: ${Interval}s)"
|
||||
exit 0
|
||||
}
|
||||
|
||||
if ($Listen -ne "") {
|
||||
$port = $Listen -replace '.*:', ''
|
||||
if (-not $port) { $port = "9197" }
|
||||
$listener = [System.Net.HttpListener]::new()
|
||||
$listener.Prefixes.Add("http://+:$port/")
|
||||
$listener.Start()
|
||||
Write-Host "Print Server exporter listening on port $port..."
|
||||
|
||||
while ($listener.IsListening) {
|
||||
$context = $listener.GetContext()
|
||||
$response = $context.Response
|
||||
$output = Get-PrintMetrics
|
||||
$buffer = [System.Text.Encoding]::UTF8.GetBytes($output)
|
||||
$response.ContentType = "text/plain; version=0.0.4"
|
||||
$response.ContentLength64 = $buffer.Length
|
||||
$response.OutputStream.Write($buffer, 0, $buffer.Length)
|
||||
$response.Close()
|
||||
}
|
||||
} elseif ($TextFile -or $OutFile -ne "") {
|
||||
$outputPath = if ($OutFile -ne "") { $OutFile } else { Join-Path $TextfileDir "print-server.prom" }
|
||||
$outputDir = Split-Path $outputPath -Parent
|
||||
if (-not (Test-Path $outputDir)) { New-Item -ItemType Directory -Path $outputDir -Force | Out-Null }
|
||||
$tempFile = Join-Path $outputDir ".print-server-metrics.tmp"
|
||||
$metricsOutput = Get-PrintMetrics
|
||||
$metricsOutput | Out-File -FilePath $tempFile -Encoding utf8 -NoNewline
|
||||
Move-Item -Path $tempFile -Destination $outputPath -Force
|
||||
Write-Host "Metrics written to $outputPath"
|
||||
} else {
|
||||
Get-PrintMetrics
|
||||
}
|
||||
Reference in New Issue
Block a user