Διόρθωση: Αργή εκκίνηση της κονσόλας και των σεναρίων PowerShell

Έχω παρατηρήσει ότι η κονσόλα PowerShell μερικές φορές χρειάζεται πολύ χρόνο για να ανοίξει. Αυτό το ζήτημα παρουσιάζεται σε διαφορετικούς υπολογιστές. Σε ορισμένες περιπτώσεις, μπορεί να χρειαστούν αρκετά λεπτά για να φορτώσει το PowerShell. Αυτό επηρεάζει το άνοιγμα του ίδιου του κελύφους εντολών (powershell.exe ή pwsh.exe) και τον χρόνο εκτέλεσης των σεναρίων σύνδεσης του PowerShell που εκκινούνται μέσω GPO ή σεναρίων στις προγραμματισμένες εργασίες. Αυτή η ανάρτηση εξηγεί πώς να εντοπίσετε πιθανούς λόγους για την αργή εκκίνηση του PowerShell και να μειώσετε τον χρόνο φόρτωσης.

Ακολουθούν ορισμένοι συνήθεις λόγοι για τους οποίους το PowerShell μπορεί να χρειαστεί πολύ χρόνο για να φορτώσει:

  • Οι συναρτήσεις που καθορίζονται από το χρήστη στα αρχεία προφίλ του PowerShell φορτώνονται κάθε φορά που ξεκινά η διαδικασία PowerShell.exe
  • Ένας σημαντικός αριθμός μονάδων PS εγκαθίστανται και φορτώνονται αυτόματα
  • Η λειτουργική μονάδα PSReadLine φορτώνει ένα τεράστιο αρχείο που περιέχει το ιστορικό των εντολών του PowerShell
  • Σημαντικές επιβραδύνσεις στο PowerShell και στη φόρτωση λειτουργιών προκαλούνται από διενέξεις ή καταστροφή στα στοιχεία του .NET Framework.

ΟΜέτρο-ΕντολήΤο cmdlet μπορεί να χρησιμοποιηθεί για τη μέτρηση του χρόνου φόρτωσης μιας διαδικασίας PowerShell. Χρησιμοποιήστε αυτήν την εντολή για να ελέγξετε το χρόνο φόρτωσης του PowerShell σε κανονική λειτουργία.:

powershell -noprofile -ExecutionPolicy Bypass ( Measure-Command { powershell "Write-Host 1" } ).TotalSeconds

Η εντολή θα εμφανίσει πόσο χρόνο χρειάστηκε για να φορτώσει και να εκτελέσει μια απλή εντολή η διαδικασία PowerShell.

Όταν ξεκινά το PowerShell, μπορεί να αναφέρει το χρόνο που χρειάστηκε για τη φόρτωση.

Loading personal and system profiles took XXX ms

Όπως μπορείτε να δείτε σε αυτό το παράδειγμα, η διαδικασία PowerShell χρειάστηκε 12 δευτερόλεπτα για να φορτώσει. Αυτό είναι αρκετά. Αυτό το μήνυμα εμφανίζεται αυτόματα εάν ο χρόνος φόρτωσης των προφίλ PowerShellυπερβαίνει τα 500 ms.

Αυτό υποδηλώνει ότι τα αρχεία προφίλ PowerShell εκτελούν αργό κώδικα κάθε φορά που ξεκινά η διαδικασία.

Συγκρίνετε την ταχύτητα εκκίνησης της διαδικασίας PowerShell όταν τα προφίλ δεν φορτώνονται. Για να το κάνετε αυτό, εκτελέστε τη διαδικασία του κελύφους με το-χωρίς προφίλεπιλογή:

powershell.exe -noprofile

ή για να εκτελέσετε τον πυρήνα του PowerShell:

pwsh.exe -noProfile

Όπως μπορείτε να δείτε, το PowerShell ξεκίνησε πολύ πιο γρήγορα όταν τα προφίλ δεν φορτώνονταν. Τα προφίλ PowerShell είναι αρχεία PS1 που χρησιμοποιούνται για τη διαμόρφωση του περιβάλλοντος χρήστη. Επιτρέπουν επίσης στον χρήστη να εκτελεί συγκεκριμένες εντολές και να φορτώνει προσαρμοσμένες λειτουργίες ή μονάδες.

Από προεπιλογή, τα αρχεία προφίλ PowerShell δεν χρησιμοποιούνται (δεν δημιουργούνται αρχεία προφίλ). Η ακόλουθη εντολή εμφανίζει μια λίστα με όλα τα αρχεία προφίλ που θα φορτωθούν όταν ξεκινήσει η διαδικασία PowerShell.

$profile | select *

Ελέγξτε τα περιεχόμενα όλων των αρχείων προφίλ για τον χρήστη μη αυτόματα ή χρησιμοποιήστε τις ακόλουθες εντολές για να τα εμφανίσετε:
Get-Content $PROFILE.AllUsersAllHosts
Get-Content $PROFILE.AllUsersCurrentHost
Get-Content $PROFILE.CurrentUserAllHosts
Get-Content $PROFILE.CurrentUserCurrentHost

Στην περίπτωσή μου, μερικές εντολές προστίθενται στοMicrosoft.PowerShell_profile.ps1αρχείο χρήστη. Ελέγξτε το αρχείο προφίλ για να βεβαιωθείτε ότι όλες οι εντολές και οι λειτουργίες είναι απαραίτητες. Εάν είναι δυνατόν, αφαιρέστε τις περιττές εντολές και βελτιστοποιήστε τον κώδικα.

Ένας μεγάλος αριθμός εγκατεστημένων μονάδων θα μπορούσε να είναι ένας άλλος πιθανός λόγος για την αργή εκκίνηση του PowerShell. Το PowerShell φορτώνει αυτόματα μονάδες από τους ακόλουθους φακέλους:

C:Users%username%DocumentsWindowsPowerShellModules
C:Program FilesWindowsPowerShellModules
C:Windowssystem32WindowsPowerShellv1.0Modules

Η λίστα τους μπορεί να εμφανιστεί ως εξής:

$Env:PSModulePath -split ';'

Καταχωρίστε τις μονάδες PS που έχουν φορτωθεί στη συνεδρία.

Get-Module -ListAvailable

Καταχωρίστε τις εγκατεστημένες μονάδες τρίτων κατασκευαστών.

Get-InstalledModule

Ελέγξτε τη λίστα για να δείτε αν χρειάζεστε όλες τις ενότητες. Απεγκαταστήστε τυχόν αχρησιμοποίητες μονάδες PowerShell.:
Remove-Module -Name BurntToast
Uninstall-Module -Name BurntToast -AllVersions -Force

Οι μονάδες PowerShell που έχουν εγκατασταθεί με μη αυτόματο τρόπο πρέπει να απεγκατασταθούν με μη αυτόματο τρόπο.

Για να αναλύσετε το χρόνο φόρτωσης κάθε ενότητας, χρησιμοποιήστε την ακόλουθη εντολή:

Measure-Command { Import-Module ModuleName -Force }

Ή ελέγξτε το χρόνο φόρτωσης όλων των μονάδων PS μαζικά:
$modules = Get-InstalledModule| Select-Object -ExpandProperty Name -Unique
foreach ($mod in $modules) {
$time = Measure-Command { Import-Module $mod -Force }
[PSCustomObject]@{
Module = $mod
LoadTimeSec = $time.Totalseconds
}
}

Δείτε ποιες μονάδες χρειάζονται περισσότερο χρόνο φόρτωσης.

Για να αποτρέψετε την αυτόματη φόρτωση όλων των μονάδων PS, προσθέστε την ακόλουθη γραμμή στο αρχείο προφίλ:

$PSModuleAutoLoadingPreference="None"

Σε αυτήν την περίπτωση, μπορείτε να φορτώσετε με μη αυτόματο τρόπο την απαιτούμενη ενότητα χρησιμοποιώντας την ακόλουθη εντολή:

Import-Module [ModuleName]

Φροντίστε να προσθέσετε τις ακόλουθες κοινές ενότητες στο αρχείο προφίλ σας:

Import-Module Microsoft.PowerShell.Utility
Import-Module Microsoft.PowerShell.Management

Υπάρχει επίσης ένα γνωστό ζήτημα κατά τη φόρτωση της λειτουργικής μονάδας διαχείρισης υποδομής VMware PowerShell, επίσης γνωστή ωςVMware PowerCLI. Η φόρτωση της μονάδας ενδέχεται να χρειαστούν αρκετά λεπτά σε υπολογιστή που δεν είναι συνδεδεμένος στο Διαδίκτυο. Το πρόβλημα είναι ότι, κατά τη φόρτωση, η λειτουργική μονάδα προσπαθεί να ελέγξει μια εξωτερική λίστα ανακληθέντων πιστοποιητικών (CRL,Λίστα ανάκλησης πιστοποιητικού). Λόγω έλλειψης σύνδεσης στο διαδίκτυο, αυτή η διαδικασία έληξε. Η λύση είναι νααπενεργοποιήστε τον έλεγχο CRL στα Windows. Μπορείτε να απενεργοποιήσετε τον έλεγχο CRL μέσω του μητρώου:

reg add HKLMSYSTEMCurrentControlSetServicesSstpSvcParameters /v NoCertRevocationCheck /t REG_DWORD /d 0x00000001 /f

Ή στη μικροεφαρμογή Ιδιότητες Διαδικτύου:inetcpl.cpl->Προχωρημένος–> καταργήστε την επιλογή της επιλογήςΕλέγξτε για ανάκληση πιστοποιητικού εκδότη (διακομιστή)..

Ο λόγος που το PowerShell μπορεί να πάρει πολύ χρόνο για να ξεκινήσει είναι συχνά το λογισμικό προστασίας από ιούς που είναι εγκατεστημένο στον υπολογιστή. Μπορείτε να ελέγξετε ποια εξωτερικά DLL και λειτουργικές μονάδες έχουν φορτωθεί όταν ξεκινά η διαδικασία PowerShell.

  1. Ανοιχτόcmd.exeκαι εκτελέστε την εντολή:powershell.exe -c "Write-Host $PID;Start-Sleep -s 60"
  2. Αυτή η εντολή επιστρέφει το αναγνωριστικό διεργασίας (PID) της διαδικασίας PowerShell.exe που εκτελείται. Αντιγράψτε τοPIDκαι επικολλήστε την στην ακόλουθη εντολή σε μια νέα περίοδο λειτουργίας PowerShell:
    Get-Process | where {$_.Id -eq <YOUR_PID>} | select -ExpandProperty modules
  3. Θα λάβετε μια λίστα με τα DLL που έχουν φορτωθεί όταν ξεκινά η διαδικασία PowerShell. Ελέγξτε εάν η βιβλιοθήκη προστασίας από ιούς περιλαμβάνεται στη λίστα. Εάν ναι, δοκιμάστε να προσθέσετε τις διεργασίες pwsh.exe και powershell.exe στις εξαιρέσεις προστασίας από ιούς.

Για παράδειγμα, μπορείτε να χρησιμοποιήσετε την παρακάτω εντολή για να προσθέσετε εξαιρέσεις στο ενσωματωμένο πρόγραμμα προστασίας από ιούς του Windows Defender:

Add-MpPreference -ExclusionProcess "C:WindowsSystem32WindowsPowerShellv1.0powershell.exe","C:Program FilesPowerShell7pwsh.exe"

Διαβάστε επίσης:Γραμμή εντολών των Windows 10: Νέα κονσόλα έναντι κονσόλας παλαιού τύπου

Εάν υποψιάζεστε ότι η αργή εκκίνηση του PowerShell προκαλείται από την αργή λειτουργία της βιβλιοθήκης .NET Framework, μπορείτε να μεταγλωττίσετε όλες τις χρησιμοποιημένες συναρμολογήσεις σε εγγενή κώδικα μηχανής χρησιμοποιώντας τοngen.exeεργαλείο (Native Image Generator). Αυτό θα βελτιώσει σημαντικά την απόδοση των εφαρμογών .NET, συμπεριλαμβανομένου του PowerShell:

$env:PATH = [Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory()
[AppDomain]::CurrentDomain.GetAssemblies() | ForEach-Object {
$path = $_.Location
if ($path) {
$name = Split-Path $path -Leaf
Write-Host -ForegroundColor Yellow "`r`nRunning ngen.exe on '$name'"
ngen.exe install $path /nologo
}
}

Το κλασικόΠαρακολούθηση διαδικασίαςΤο εργαλείο μπορεί επίσης να χρησιμοποιηθεί για την ανάλυση του χρόνου εκκίνησης του PowerShell. (https://technet.microsoft.com/en-us/sysinternals/processmonitor.aspx). ΤρέξιμοProcMon64.exe, ενεργοποιήστε το φίλτρο στη διαδικασία PowerShell.exe, ανοίξτε το κέλυφος PS και εντοπίστε τις λειτουργίες που προκάλεσαν τη μεγαλύτερη καθυστέρηση.

Στο παράδειγμά μου, η ανάγνωση του αρχείου ιστορικού εντολών PowerShell που διατηρείται από τη μονάδα PSReadline χρειάστηκε περίπου 30 δευτερόλεπτα. (C:UsersusernameAppDataRoamingMicrosoftWindowsPowerShellPSReadLineConsoleHost_history.txt). Το πρόβλημα προκλήθηκε από τηνConsoleHost_history.txtαρχείο με μέγεθος μεγαλύτερο από 2 GB. Ο καθαρισμός του αρχείου ιστορικού μείωσε σημαντικά τον χρόνο εκκίνησης του PowerShell.

Related Posts