Comment utiliser un script PowerShell pour générer des fichiers journaux d’assistance NinjaOne ?

Lors de la résolution de problèmes techniques dans un environnement d’entreprise, la génération et la collecte de journaux de diagnostic constituent une première étape cruciale. Pour les fournisseurs de services gérés (MSP) et les professionnels de l’informatique, disposer d’un moyen optimisé et automatisé de produire des journaux pertinents pour les équipes d’assistance permet d’accélérer considérablement les délais de résolution. L’une de ces solutions est le script PowerShell présenté dans cet article, conçu pour créer, gérer et déplacer les fichiers journaux de l’agent NinjaOne avec une intervention manuelle minimale.

Contexte

La génération manuelle de journaux de diagnostic peut s’avérer fastidieuse et source d’erreurs, en particulier lorsque l’on travaille sur des dizaines ou des centaines de terminaux. Les scripts qui automatisent la collecte des journaux améliorent non seulement la cohérence, mais appliquent également des formats normalisés et réduisent le temps de résolution. Ce script PowerShell particulier répond au besoin de créer des fichiers journaux d’agent NinjaOne horodatés, de les relocaliser éventuellement dans un répertoire personnalisé et de garantir la conformité administrative par le biais d’autorisations élevées et de la validation des entrées.

Les MSP qui s’appuient sur NinjaOne bénéficient de ce niveau d’automatisation, en particulier lorsqu’ils tentent d’assister des clients distants ou de recueillir des informations avant de faire appel au support de NinjaOne.

Le script

#Requires -Version 5.1

<#
.SYNOPSIS
    Generate a log file for Ninja Support. The script will store the file in the System Drive's Windows\Temp directory by default, or you can specify a destination directory.  
.DESCRIPTION
    Generate a log file for Ninja Support. The script will store the file in the System Drive's Windows\Temp directory by default, or you can specify a destination directory. 
By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
    Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).

.EXAMPLE
    (No Parameters)
    
    [Info] Looking for old log files in 'C:\Windows\Temp' to rename before generating the new log file.

    [Info] No old log files were found.

    [Info] Starting Ninja log collection.
    [Info] Finished Ninja log collection.

    [Info] The Ninja log file has been successfully created in 'C:\Windows\Temp'!

    [Info] Renaming 'ninjalogs.cab' to 'ninjalogs_2025-02-04_11-20-56AM.cab'.
    [Info] Successfully renamed 'ninjalogs.cab' to 'ninjalogs_2025-02-04_11-20-56AM.cab'.

    [Info] Ninja log file saved to 'C:\Windows\Temp\ninjalogs_2025-02-04_11-20-56AM.cab'

.PARAMETER -DestinationDirectory "C:\example"
    Enter the destination directory where the Ninja log file will be saved. The directory will be created if it does not exist. If not used, the log file will be placed in the System Drive's Windows\Temp directory by default.

.EXAMPLE
    -DestinationDirectory "C:\example"
    
    [Info] 'C:\example' does not exist. Creating the directory.
    [Info] Successfully created the directory at: 'C:\example'.

    [Info] Looking for old log files in 'C:\Windows\Temp' to rename before generating the new log file.

    [Info] No old log files were found.

    [Info] Starting Ninja log collection.
    [Info] Finished Ninja log collection.

    [Info] The Ninja log file has been successfully created in 'C:\Windows\Temp'!

    [Info] Renaming 'ninjalogs.cab' to 'ninjalogs_2025-02-04_11-19-28AM.cab'.
    [Info] Successfully renamed 'ninjalogs.cab' to 'ninjalogs_2025-02-04_11-19-28AM.cab'.

    [Info] Moving 'ninjalogs_2025-02-04_11-19-28AM.cab' to 'C:\example'.
    [Info] Successfully moved 'ninjalogs_2025-02-04_11-19-28AM.cab' to 'C:\example'.

    [Info] Ninja log file saved to 'C:\example\ninjalogs_2025-02-04_11-19-28AM.cab'

.NOTES
    Minimum OS Architecture Supported: Windows 10, Windows Server 2016
    Release Notes: Initial Release
#>

[CmdletBinding()]
param (
    [Parameter()]
    [string]$DestinationDirectory
)

begin {
    function Test-IsElevated {
        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
        $p = New-Object System.Security.Principal.WindowsPrincipal($id)
        $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
    }

    if ($env:DestinationDirectory){
        $DestinationDirectory = $env:DestinationDirectory
    }

    # validate input destination directory
    if ($DestinationDirectory){
        # if DestinationDirectory does not start with a letter, colon and backslash (i.e. C:\), output an error and exit
        if ($DestinationDirectory -notmatch "^[A-Za-z]:\\") {
            Write-Host "[Error] Invalid destination directory: '$DestinationDirectory'"
            Write-Host "Please enter a full path to a directory, for example: C:\Ninja\Logs_Folder"
            exit 1
        }

        # If DestinationDirectory contains invalid characters, output an error and exit the script
        if ($DestinationDirectory -match '[/*?"<>|]' -or $DestinationDirectory.SubString(2) -match "[:]") {
            Write-Host "[Error] Invalid destination directory: '$DestinationDirectory'"
            Write-Host "The directory you specified contains one of the following invalid characters: '/*?`"<>|:'"
            exit 1
        }

        $DestinationDirectory -split '\\' | ForEach-Object {
            # Check each folder to see if it ends with a period or a space and output an error if so
            if ($_ -match "\.\\?$|\s\\?$"){
                Write-Host "[Error] Invalid destination directory: '$DestinationDirectory'"
                Write-Host "Directories cannot end in spaces or periods."
                exit 1
            }
            # Check each folder in the directory path for reserved names and output an error if any are found
            $Folder = ($_).Trim()
            if ($Folder -match '^CON$' -or $Folder -match '^PRN$' -or $Folder -match '^AUX$' -or $Folder -match '^NUL$' -or $Folder -match '^LPT\d$' -or $Folder -match '^COM\d+$') {
                Write-Host "[Error] Invalid destination directory: '$DestinationDirectory'"
                Write-Host "The following folder names are reserved: CON, PRN, AUX, NUL, COM1-9, LPT1-9"
                exit 1
            }
        }        
    }
}
process {
    if (-not (Test-IsElevated)) {
        Write-Host -Object "[Error] Access Denied. Please run with Administrator privileges."
        exit 1
    }

    if ($DestinationDirectory){
        # create destination directory if it does not exist
        if (-not (Test-Path $DestinationDirectory -PathType Container)){
            Write-Host "[Info] '$DestinationDirectory' does not exist. Creating the directory."
            try{
                # if an invalid character or path is entered, this will fail and the catch will take over
                $newDir = New-Item $DestinationDirectory -ItemType Directory -ErrorAction Stop 

                # otherwise, set the destination directory to the new directory's FullName which will take out any unnecessary characters
                $DestinationDirectory = $newDir.FullName
                
                Write-Host "[Info] Successfully created the directory at: '$DestinationDirectory'.`n"
            }
            catch{
                Write-Host "[Error] Error creating the directory '$DestinationDirectory'."
                Write-Host "$($_.Exception.Message)"
                exit 1
            }
        }
    }
    else{
        $DestinationDirectory = "$env:windir\Temp"
    }

    # check for old Ninja log files in $env:windir\Temp
    Write-Host "[Info] Looking for old log files in '$env:windir\Temp' to rename before generating the new log file.`n"
    $logFilesInTemp = Get-ChildItem $env:windir\Temp | Where-Object {$_.Name -match "ninjalogs\.cab$"}

    # rename old log files in $env:windir\Temp
    if ($logFilesInTemp){
        Write-Host "[Info] Renaming old log files in '$env:windir\Temp'.`n"

        foreach ($log in $logFilesInTemp){
            $currentFileName = $log.Name
            $newFileName = "ninjalogs_" + $log.CreationTime.ToString("yyyy-MM-dd_hh-mm-sstt") + ".cab"

            try{
                Write-Host "[Info] Renaming '$currentFileName' to '$newFileName'."
                Rename-Item $log.FullName -NewName $newFileName
                Write-Host "[Info] Successfully renamed '$currentFileName' to '$newFileName'.`n"
            }
            catch{
                Write-Host "[Error] Error renaming previous log file '$currentFileName'."
                Write-Host "$($_.Exception.Message)"
                exit 1
            }
        }
        Write-Host "[Info] Finished renaming old log files.`n"
    }
    else{
        Write-Host "[Info] No old log files were found.`n"
    }

    # find ninjarmmagent.exe path, which will be used to generate the log file
    if ($env:NINJA_EXECUTING_PATH -and (Test-Path $env:NINJA_EXECUTING_PATH)){
        $agentPath = "$env:NINJA_EXECUTING_PATH\ninjarmmagent.exe"
    }
    else {
        $agentPath = (Get-ChildItem -Path $env:ProgramFiles,${env:ProgramFiles(x86)} -Filter "ninjarmmagent.exe" -File -Recurse -Depth 1 -Force -ErrorVariable agentSearchErrors -ErrorAction SilentlyContinue).FullName
        
        if ($agentSearchErrors){
            Write-Host "[Warning] Errors encountered while looking for ninjarmmagent.exe:"
            foreach ($err in $agentSearchErrors){
                Write-Host $err.Exception.Message
            }
            Write-Host ""
        }
    }

    if ([string]::IsNullOrWhiteSpace($agentPath)){
        Write-Host "[Error] Ninja agent (ninjarmmagent.exe) could not be found."
        exit 1
    }
    
    $newLogFile = "$env:windir\Temp\ninjalogs.cab"

    # collect logs
    try{
        Write-Host "[Info] Starting Ninja log collection."
        $timer = New-Object System.Diagnostics.Stopwatch
        $timer.Start()
        Start-Process $agentPath -ArgumentList "/collectlogs" -ErrorAction Stop
    }
    catch{
        Write-Host "[Error] Error starting Ninja log collection process."
        Write-Host "$($_.Exception.Message)"
        exit 1
    }
    
    # wait until the new log file has been generated or 30 mins have passed
    # check every 10 seconds
    while ((Test-Path $newLogFile) -eq $false){
        if ($timer.Elapsed.Minutes -ge 30){
            $timer.Stop()
            Write-Host "[Error] Log collection failed. Timeout reached while waiting for the log file to be created."
            exit 1
        }
        Start-Sleep -Seconds 10
    }
        
    Write-Host "[Info] Finished Ninja log collection.`n"
    
    Write-Host "[Info] The Ninja log file has been successfully created in '$env:windir\Temp'!`n"

    # rename file to have timestamp
    $currentFile = Get-Item $newLogFile
    $currentFileName = $currentFile.Name
    $newFileName = "ninjalogs_" + $currentFile.CreationTime.ToString("yyyy-MM-dd_hh-mm-sstt") + ".cab"
    
    try{
        Write-Host "[Info] Renaming '$currentFileName' to '$newFileName'."
        Rename-Item -Path $currentFile.FullName -NewName $newFileName -ErrorAction Stop -Force
        Write-Host "[Info] Successfully renamed '$currentFileName' to '$newFileName'.`n"
    }
    catch{
        Write-Host "[Error] Error renaming '$currentFileName' to '$newFileName'."
        Write-Host "$($_.Exception.Message)"
        exit 1
    }

    # move file to destination directory if it isn't $env:windir\Temp
    if ($DestinationDirectory -ne "$env:windir\Temp"){
        try{
            Write-Host "[Info] Moving '$newFileName' to '$DestinationDirectory'."
            Move-Item -Path "$env:windir\Temp\$newFileName" -Destination $DestinationDirectory -ErrorAction Stop
            Write-Host "[Info] Successfully moved '$newFileName' to '$DestinationDirectory'.`n"
        }
        catch{
            Write-Host "[Error] Error moving '$newFileName' to '$DestinationDirectory'."
            Write-Host "$($_.Exception.Message)"
            Write-Host "Log file still remains at $env:windir\Temp\$newFileName."
            exit 1
        }
    }

    $path = (Get-ChildItem $DestinationDirectory | Where-Object {$_.Name -match "$newFileName"}).FullName

    Write-Host "[Info] Ninja log file saved to '$path'"
    
    exit 0
}
end {
    
    
    
}

 

Description détaillée

Voici un aperçu, étape par étape, du fonctionnement du script :

  1. Traitement des paramètres et validation des entrées

    • Accepte un paramètre facultatif : -DestinationDirectory.
    • Valide le format du chemin d’accès au répertoire d’entrée, en vérifiant la présence de caractères non valides, de noms de dossiers réservés et de terminaisons incorrectes.
  2. Vérification de l’élévation des privilèges

    • Vérifie que le script est exécuté avec des privilèges administratifs, ce qui est essentiel pour accéder à des répertoires protégés ou à des fichiers système.
  3. Créer un répertoire de destination (si nécessaire)

    • Si un chemin de destination est fourni et qu’il n’existe pas, il tente de créer le répertoire.
    • Il détecte et signale les erreurs lors de la création.
  4. Renommage des anciens fichiers journaux

    • Vérifie le répertoire temporaire du système (par défaut : C:\Windows\Temp) pour les fichiers ninjalogs.cab existants.
    • Les renommer en utilisant un format d’horodatage pour éviter l’écrasement, par exemple, ninjalogs_2025-02-04_11-20-56AM.cab.
  5. Génération de fichiers journaux

    • Identifie l’exécutable ninjarmmagent.exe à l’aide de la variable d’environnement ou de la recherche dans le système de fichiers.
    • Lance l’agent avec l’option /collectlogs via Start-Process.
    • Attend jusqu’à 30 minutes (interrogation toutes les 10 secondes) que le fichier journal soit créé.
  6. Renommer et déplacer des fichiers

    • Une fois généré, il renomme le fichier journal avec un horodatage.
    • Si une destination personnalisée a été définie, le journal y est déplacé et le chemin d’accès final enregistré est indiqué.

Cas d’utilisation potentiels

Étude de cas : Diagnostic à distance pour le terminal VIP

Un fournisseur de services gérés (MSP) gérant un environnement client distribué reçoit une plainte d’un utilisateur VIP concernant des pannes logicielles récurrentes. Au lieu d’accéder manuellement au système, le technicien déploie ce script à distance en utilisant les outils d’automatisation de NinjaOne. Le script génère le journal, l’enregistre sur un partage sécurisé prédéfini et l’horodate. En quelques minutes, le technicien a accès aux journaux nécessaires et commence le processus de triage sans interrompre l’utilisateur final.

Comparaisons

Collection manuelle

La génération manuelle de journaux à l’aide de NinjaOne implique souvent d’interagir avec l’interface graphique, de localiser ninjarmmagent.exe et de copier les fichiers manuellement; une tâche qui prend du temps et qui est sujette à des erreurs.

Outils tiers de journalisation

Bien que les solutions de journalisation centralisées (par exemple, Splunk, ELK) puissent collecter des journaux à l’échelle du système, elles n’ont souvent pas d’interface directe avec les outils spécifiques des fournisseurs tels que NinjaOne. Ce texte remplit efficacement ce créneau spécifique aux vendeurs.

Capacités natives de NinjaOne

Bien que NinjaOne fournisse des outils intégrés pour collecter les journaux, l’écriture de scripts offre flexibilité, portabilité et contrôle total de l’exécution, ce qui est idéal pour les flux de travail personnalisés et l’automatisation.

Questions fréquentes

Ai-je besoin de privilèges d’administrateur pour exécuter ce script ?

Oui, le script vérifie les droits d’administration et se termine s’ils ne sont pas élevés.

Que se passe-t-il si le chemin de destination n’est pas valide ?

Le script comprend une validation performante des entrées et se termine par des messages d’erreur utiles si le chemin d’accès est mal formé ou contient des noms réservés.

Puis-je l’utiliser sur Windows 7 ?

Non. Les systèmes d’exploitation minimum pris en charge sont Windows 10 et Windows Server 2016.

Que faire si ninjarmmagent.exe n’a pas été trouvé ?

Le script recherche à la fois %ProgramFiles% et %ProgramFiles(x86)%. S’il n’est pas trouvé, il s’arrête avec une erreur appropriée.

Implications

Ce script standardise la collecte des journaux sur les terminaux, réduisant ainsi le délai entre la détection d’un problème et l’escalade. Il élimine les erreurs humaines, garantit le respect des conventions de dénomination et renforce la sécurité en appliquant des contrôles d’autorisation. De plus, un enregistrement cohérent améliore l’analyse post-script et aide les équipes à mettre en place de meilleurs processus d’analyse des causes profondes (RCA).

Recommandations

  • Testez toujours le script dans un environnement contrôlé avant de le déployer à grande échelle.
  • Utilisez les capacités d’automatisation de NinjaOne pour lancer le script en tant que tâche planifiée ou à la demande.
  • Stockez les journaux générés dans un référentiel centralisé et à accès contrôlé pour en faciliter la récupération.
  • Envisagez d’étendre le script pour zipper ou chiffrer les fichiers journaux si vous traitez des environnements sensibles.
  • Intégrez les systèmes de gestion des tickets (par exemple, ConnectWise, ServiceNow) en joignant le chemin d’accès au journal dans le cadre du flux de travail de l’escalade.

Conclusion

L’automatisation de la collecte des journaux avec PowerShell permet aux équipes informatiques de travailler plus intelligemment, et non plus difficilement. Ce script illustre la manière dont l’automatisation ciblée peut simplifier les flux de travail d’assistance tout en améliorant la précision et la responsabilité. Pour les utilisateurs de NinjaOne, l’intégration de ces scripts avec les fonctions d’automatisation et de scripting de la plateforme permet une synergie puissante, accélérant la réponse du support et renforçant l’efficacité opérationnelle.

En utilisant un script PowerShell pour générer des fichiers journaux pour l’assistance, les professionnels de l’informatique peuvent se concentrer sur la résolution des problèmes, et non sur la recherche d’artefacts. Associé à des pratiques de script intelligentes comme celle-ci, NinjaOne devient plus qu’un RMM, il devient le pilier d’une gestion informatique proactive et évolutive.

Next Steps

Building an efficient and effective IT team requires a centralized solution that acts as your core service delivery tool. NinjaOne enables IT teams to monitor, manage, secure, and support all their devices, wherever they are, without the need for complex on-premises infrastructure.

Learn more about NinjaOne Remote Script Deployment, check out a live tour, or start your free trial of the NinjaOne platform.

Catégories :

Vous pourriez aussi aimer