PowerShell Write-Log: دليل على وظيفة تسجيل بسيطة

إذا كنت تكتب نصوصًا بواسطة PowerShell التي تقوم بأي شيء معنوي، فإنك بحاجة إلى تسجيل. سواء كنت تقوم بنشر برنامج، أو إدارة خدمات، أو أتمتة المهام، فإن وجود سجل لما فعله النص الخاص بك (أو لم يفعل) أمر حاسم. في هذا البرنامج التعليمي، ستتعلم كيفية إنشاء وظيفة تسجيل PowerShell بسيطة وفعالة.

المتطلبات المسبقة

إذا كنت ترغب في متابعة هذا البرنامج التعليمي، تأكد من أن لديك:

  • نظام Windows 10 أو Windows Server مع PowerShell 5.1 أو PowerShell 7+
  • محرر نصوص (يُوصى باستخدام VSCode)
  • فهم أساسي لوظائف PowerShell

المشكلة مع تسجيل البيانات الأساسي

فلنقل أنك تكتب نصًا لتثبيت بعض البرامج بصمت. قد تبدو الطريقة الأساسية كما يلي:

Add-Content -Path "C:\\Scripts\\install.log" -Value "Starting install..."
Start-Process -FilePath 'installer.exe' -ArgumentList '/i /s' -Wait -NoNewWindow
Add-Content -Path "C:\\Scripts\\install.log" -Value "Finished install."

هذا يعمل، ولكن به بعض المشاكل:

  • لا يوجد الطوابع الزمنية
  • رمز متكرر
  • تنسيق تسجيل غير متسق
  • مسار تسجيل مُشفر

دعونا نُصلح هذه المشكلات من خلال بناء وظيفة تسجيل مناسبة.

بناء وظيفة كتابة السجلات الأساسية

أولاً، دعنا ننشئ وظيفة بسيطة تضيف الطوابع الزمنية إلى إدخالات السجل الخاصة بنا:

function Write-Log {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Message
    )

    $timeGenerated = Get-Date -Format HH:mm:ss
    Add-Content -Path "C:\\Scripts\\script.log" -Value "$timeGenerated - $Message"
}

الآن يمكنك استخدامها بهذه الطريقة:

Write-Log -Message "Starting install..."
Start-Process -FilePath 'installer.exe' -ArgumentList '/i /s' -Wait -NoNewWindow
Write-Log -Message "Finished install."

سيحتوي ملف السجل (C:\Scripts\script.log) على إدخالات تبدو مثل:

09:42:15 - Starting install...
09:43:22 - Finished install.

أنظف بكثير! ولكن يمكننا أن نفعل أفضل.

إضافة المزيد من الوظائف

لنعزز وظيفة تسجيلنا ببعض الميزات المفيدة:

  • مسارات تسجيل مخصصة
  • مستويات السجل المختلفة (معلومات، تحذير، خطأ)
  • تاريخ في اسم الملف
  • التعامل مع الأخطاء

إليك النسخة المحسنة:

function Write-Log {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Message,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$LogFilePath = "C:\\Scripts\\Logs",

        [Parameter()]
        [ValidateSet('Information','Warning','Error')]
        [string]$Level = "Information"
    )

    # Create the log directory if it doesn't exist
    if (!(Test-Path $LogFilePath)) {
        New-Item -Path $LogFilePath -ItemType Directory -Force | Out-Null
    }

    # Build the log file path with date
    $date = Get-Date -Format "MM-dd-yyyy"
    $logFile = Join-Path $LogFilePath "log-$date.txt"

    # Get the current timestamp
    $timeStamp = Get-Date -Format "HH:mm:ss"

    # Create the log entry
    $logEntry = "$timeStamp [$Level] - $Message"

    try {
        Add-Content -Path $logFile -Value $logEntry -ErrorAction Stop
    }
    catch {
        Write-Error "Failed to write to log file: $_"
    }
}

تمنحك هذه النسخة المعززة مزيدًا من المرونة. إليك كيفية استخدامها:

# Basic information logging
Write-Log -Message "Starting software installation"

# Warning about a non-critical issue
Write-Log -Message "Config file not found, using defaults" -Level Warning

# Log an error
Write-Log -Message "Installation failed!" -Level Error

# Use a custom log path
Write-Log -Message "Custom path log" -LogFilePath "D:\\CustomLogs"

سيبدو ملف السجل الناتج (log-03-12-2024.txt) كالتالي:

10:15:22 [Information] - Starting software installation
10:15:23 [Warning] - Config file not found, using defaults
10:15:25 [Error] - Installation failed!

وفي D:\CustomLogs\log-03-12-2024.txt:

10:15:26 [Information] - Custom path log

لاحظ كيف يتضمن كل إدخال الطابع الزمني، مستوى السجل بين الأقواس، والرسالة. هذه الصيغة المنظمة تجعل من السهل تحليل السجلات وتحديد المشكلات بسرعة.

مثال من العالم الحقيقي: برنامج تثبيت البرمجيات

دعنا نستخدم وظيفة التسجيل لدينا في برنامج حقيقي يقوم بتثبيت البرمجيات بصمت:

# First, dot-source the logging function
. .\\Write-Log.ps1

# Script variables
$installer = "C:\\Installers\\software.exe"
$logPath = "C:\\Scripts\\InstallLogs"

# Start logging
Write-Log -Message "Beginning installation process" -LogFilePath $logPath

# Check if installer exists
if (Test-Path $installer) {
    Write-Log -Message "Found installer at: $installer"

    try {
        # Attempt installation
        Write-Log -Message "Starting installation..."
        $process = Start-Process -FilePath $installer -ArgumentList '/i /s' -Wait -NoNewWindow -PassThru

        # Check the exit code
        if ($process.ExitCode -eq 0) {
            Write-Log -Message "Installation completed successfully"
        }
        else {
            Write-Log -Message "Installation failed with exit code: $($process.ExitCode)" -Level Error
        }
    }
    catch {
        Write-Log -Message "Installation failed with error: $_" -Level Error
    }
}
else {
    Write-Log -Message "Installer not found at: $installer" -Level Error
}

Write-Log -Message "Installation script completed"

سيبدو ملف السجل الناتج شيئًا مثل هذا:

09:15:22 [Information] - Beginning installation process
09:15:22 [Information] - Found installer at: C:\\Installers\\software.exe
09:15:22 [Information] - Starting installation...
09:16:45 [Information] - Installation completed successfully
09:16:45 [Information] - Installation script completed

نصائح مفيدة

إليك بعض الممارسات الجيدة عند استخدام هذه الوظيفة للتسجيل:

  1. قم دائمًا بتسجيل بداية ونهاية البرنامج النصي الخاص بك – يساعد ذلك في تتبع وقت تنفيذ البرنامج النصي وحالة الانتهاء.

  2. استخدم مستويات السجل المناسبة – لا تصنف كل شيء كخطأ؛ استخدم المستوى المناسب للموقف:

    • معلومات: العمليات العادية
    • تحذير: مشكلات غير حرجة
    • خطأ: مشكلات حرجة تحتاج إلى اهتمام
  3. تضمين التفاصيل ذات الصلة – سجل معلومات كافية لفهم ما حدث:

    # سيء
    Write-Log "فشل الاتصال"
    
    # جيد
    Write-Log "فشل الاتصال بالخادم 'SQL01' - انتهاء الوقت بعد 30 ثانية" -Level Error
    
  4. تنظيف السجلات القديمة – اعتبر إضافة تدوير للسجلات لمنع امتلاء مساحة القرص:

    # حذف السجلات الأقدم من 30 يومًا
    Get-ChildItem -Path $LogFilePath -Filter "*.txt" |
        Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) } |
        Remove-Item
    

استنتاج

وظيفة تسجيل جيدة ضرورية لأي نص PowerShell جاد. مع وظيفة Write-Log التي أنشأناها، لديك الآن طريقة مرنة وقابلة لإعادة الاستخدام لإضافة تسجيل صحيح إلى جميع نصوصك. تذكر أن تعدل الوظيفة وفقًا لاحتياجاتك المحددة – قد ترغب في إضافة ميزات مثل:

تدوير السجلات

function Write-Log {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Message,

        [Parameter()]
        [int]$MaxLogFiles = 30  # Keep last 30 days of logs
    )

    # Remove old log files
    Get-ChildItem -Path $LogFilePath -Filter "*.txt" |
        Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$MaxLogFiles) } |
        Remove-Item -Force

    # Continue with normal logging...
}

أشكال إخراج مختلفة (CSV، JSON)

function Write-Log {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Message,

        [Parameter()]
        [ValidateSet('TXT','CSV','JSON')]
        [string]$Format = 'TXT'
    )

    $logEntry = [PSCustomObject]@{
        Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        Level = $Level
        Message = $Message
    }

    switch ($Format) {
        'CSV'  { $logEntry | Export-Csv -Path "$LogFilePath\\log.csv" -Append -NoTypeInformation }
        'JSON' { $logEntry | ConvertTo-Json | Add-Content -Path "$LogFilePath\\log.json" }
        'TXT'  { "$($logEntry.Timestamp) [$($logEntry.Level)] - $($logEntry.Message)" |
                 Add-Content -Path "$LogFilePath\\log.txt" }
    }
}

دعم المسار الشبكي

function Write-Log {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Message,

        [Parameter()]
        [string]$NetworkPath = "\\\\server\\logs"
    )

    # Test network path connectivity
    if (!(Test-Path $NetworkPath)) {
        # Fallback to local logging if network is unavailable
        $NetworkPath = "C:\\Scripts\\Logs"
        Write-Warning "Network path unavailable. Using local path: $NetworkPath"
    }

    # Continue with normal logging...
}

إشعارات بريد إلكتروني للأخطاء

function Write-Log {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Message,

        [Parameter()]
        [string]$SmtpServer = "smtp.company.com",

        [Parameter()]
        [string[]]$NotifyOnError = "[email protected]"
    )

    # Normal logging first...

    # Send email if this is an error
    if ($Level -eq 'Error' -and $NotifyOnError) {
        $emailParams = @{
            From = "[email protected]"
            To = $NotifyOnError
            Subject = "PowerShell Script Error"
            Body = "Error occurred at $timeStamp`n`nMessage: $Message"
            SmtpServer = $SmtpServer
        }

        try {
            Send-MailMessage @emailParams
        }
        catch {
            Write-Warning "Failed to send error notification: $_"
        }
    }
}

المفتاح هو البدء بأساس قوي والبناء من هناك بناءً على احتياجاتك المحددة. يجب أن تعطيك هذه الأمثلة نقطة انطلاق جيدة لتوسيع وظيفة التسجيل الأساسية مع ميزات أكثر تقدمًا.

على سبيل المثال، يمكنك دمج العديد من هذه الميزات في حل تسجيل شامل واحد:

Write-Log -Message "Critical error in payment processing" `
          -Level Error `
          -Format CSV `
          -NetworkPath "\\\\server\\logs" `
          -NotifyOnError "[email protected]","[email protected]" `
          -MaxLogFiles 90

سيقوم هذا ب:

  • تسجيل الخطأ بتنسيق CSV
  • تخزينه على مشاركة شبكية
  • إرساله إلى عدة مستلمين عبر البريد الإلكتروني
  • الاحتفاظ بتاريخ تسجيل لمدة 90 يومًا

تذكر أن تقوم بإجراء اختبار شامل، خاصة عند تنفيذ مسارات الشبكة أو إشعارات البريد الإلكتروني، حيث يمكن أن تؤثر هذه التبعيات الخارجية على موثوقية سيناريو البرنامج الخاص بك. نتمنى لك تجربة سعيدة!

Source:
https://adamtheautomator.com/powershell-write-log-tutorial/