Powershell : obtention des jobs d’impressions KO

J’ai été confronté ces derniers jours à des dysfonctionnements sur un serveur d’impression, avec un process PrintIsolationHost utilisant toutes les ressources CPU, pénalisant toutes les impressions. Généralement, ce processus utilise 100% du CPU si un des drivers d’impression fonctionne mal. Je vous renvoie à la documentation Microsoft sur le rôle de ce process.

Dans mon cas, je n’avais pas installé de drivers depuis quelques temps et le problème se reproduisait sur toutes les imprimantes ; il s’agissait au final de fichiers générés par un outil tiers gérant l’impression ayant une taille énorme (pas loin du Go pour certains), faisant planter le driver sollicité.

En attendant de trouver la cause, j’ai dû plusieurs fois arrêter à la main les impressions. Chercher imprimante par imprimante sur un serveur en hébergeant une trentaine n’est ni amusant ni productif. J’ai donc développé un script Powershell permettant de remonter les jobs d’impression qui sont en erreur sur un serveur donné, ce qui me permettait de retrouver immédiatement le fichier bloquant.

Write-Host "KO Printing Jobs listing script"
Write-Host "===================================`r`n"
$hostname = Read-Host "Print Server to query"
$printjobs = Get-Printer -computer $hostname | Foreach-Object { Get-PrintJob -Computer $hostname -PrinterName $_.Name }
if($?){
foreach($printjob in $printjobs){
if($printjob.JobStatus -ne "Normal") {
$size = [math]::Round($printjob.Size/1024,0)
Write-Host "Job"$printjob.Id"-"$printjob.DocumentName"(size:"$size "KB) has the following status:"$printjob.JobStatus"on"$printjob.PrinterName
}
}
}

Voici un exemple d’output du script :

Powershell : automatisation de la création et peuplement de groupes AD

Dans le billet précédent, j’expliquais la création de groupes ActiveDirectory pour cadrer les flux générés par le Windows Update Delivery Optimization. Afin de faciliter le process de création de groupes et de peuplement de ces groupes, j’ai développé un script Powershell qui, avec un peu d’adaptation, permet d’automatiser tout ce travail.

Ce script va importer un fichier CSV dans un tableau dont toutes les lignes seront traitées pour créer un groupe correspondant, renvoyer le GUID du groupe créé, puis ajouter à ce groupe les stations de travail correspondantes.

Dans cet exemple, le fichier CSV peut se présenter ainsi :

Le fichier CSV en question avec les « colonnes » ID et location qui seront ensuite importées dans un tableau.

Ensuite, en prenant comme nomenclature <SiteID><Type><No>, qui va donner des noms comme FR01F01 pour le premier desktop parisien ou UK02M03 pour le troisième laptop du site de Glasgow, on peut articuler la requête ActiveDirectory qui va lister les stations correspondantes au site pour ensuite peupler le groupe lié. Le passage d’un paramètre permet de sélectionner – si cela est possible – le type de station que l’on souhaite inclure. Il sera peut-être nécessaire de travailler le contenu de la requête ActiveDirectory afin qu’elle corresponde à la nomenclature de nommage des stations.

function adquery{
param($T)
$adQuery = "Get-ADComputer -filter 'Name -like ""$id$T*""'"
$compList = Invoke-Expression $adQuery
if($?) {
foreach($comp in $compList){
Add-ADGroupMember -Identity $GrpName -Members $comp
}
}
}

$siteList = Import-CSV site.csv
$dn = (Get-ADDomain).DistinguishedName
foreach ($site in $siteList){
$id = $site.ID
$loc = $site.Location
$GrpName = $id+"-WUDO"
New-ADGroup -Name $GrpName -Description "Groupe d'ordinateurs du site $id ($loc)" -GroupScope DomainLocal -GroupCategory Security -Path "OU=Groupes-WUDO,OU=Workstations,$dn"
Write-Host "Groupe $GrpName"
Write-Host (Get-ADGroup $GrpName).ObjectGuid.Guid
adquery("F")
adquery("L")
}

Powershell : copie de fichiers considérés comme anciens

Suite à une demande d’un collègue, j’ai réalisé un script Powershell réalisant une copie récursive de fichiers et dossiers si ceux-ci ont été créés, modifiés ou utilisés (au choix de l’utilisateur) depuis un nombre de jours spécifiés.

En reprenant la logique du script d’archivage automatique de fichiers d’événements Windows, il peut être possible de réaliser une mécanique d’archivage automatique de certains fichiers comme des logs par exemple. Les deux scripts (combinés en un seul) pourraient alors réaliser la copie dans un répertoire temporaire où ils seraient compressés avant d’être acheminés sur un répertoire réseau dédié.

function process{
Write-Host "Folders will be displayed in Cyan." -ForegroundColor "Cyan"
Write-Host "Files will be displayed in Green.`r`n" -ForegroundColor "Green"
foreach($item in $items){
if ($item.Attributes -eq "Directory") { Write-Host $item.FullName -ForegroundColor "Cyan" }
else { Write-Host $item.FullName -ForegroundColor "Green" }
$destination = $item.FullName.Substring($origpath.Length,$item.FullName.Length-$origpath.Length)
Copy-Item $item.FullName -Destination "$destpath\$destination" -Force
}
}
Write-Host "Old files archiving script"
Write-Host "=========================="
$origpath = "C:\source\"
$destpath = "C:\dest\"
$today = Get-Date
if (Test-Path -Path $destpath) { Write-Host "Destination directory already exists. Be careful as the script will overwrite any existing files." -ForegroundColor "Red" } else { New-Item -Path $destpath -ItemType "directory" | out-null }
$olderthan = Read-Host "Archive files older than X days"
Write-Host "1: Creation Date"
Write-Host "2: Modification Date"
Write-Host "3: Last Access Date"
$datetype = Read-Host "Kind of timestamp the script should use ? (1, 2 or 3)"
switch($datetype){
"1" { $items = Get-ChildItem $origpath -Recurse | Where-Object { $_.CreationTime -lt $today.AddDays(-$olderthan) } ; process }
"2" { $items = Get-ChildItem $origpath -Recurse | Where-Object { $_.LastWriteTime -lt $today.AddDays(-$olderthan) } ; process }
"3" { $items = Get-ChildItem $origpath -Recurse | Where-Object { $_.LastAccessTime -lt $today.AddDays(-$olderthan) } ; process }
}
Write-Host "Bye."

VMware et Powershell : rapport des versions d’hôtes vSphere

Voici un script permettant de lister les versions des hôtes vSphere présents dans un vCenter. Le premier mode liste tous les hôtes tandis que le deuxième permet de lister une version spécifique, majeure ou mineure. Par exemple, en saisissant « 6 », alors le script cherchera les serveurs en 6.x.x tandis qu’en envoyant « 5.5 », il cherchera les serveurs en 5.5.x. Dans tous les cas, un export CSV exploitable est réalisé. Naturellement, il est nécessaire que les modules Powershell de VMware soient déployés sur la machine exécutant le script (si ils ne le sont pas, il suffit simplement de télécharger PowerCli).

Import-Module VMware.VimAutomation.Core

function allhosts{
Write-Host "Retrieving all hosts on vCenter $vcenter"
$spheres = Get-VMHost
process
}

function spechosts{
Write-Host "Retrieving specific hosts on vCenter $vcenter."
$reqver = Read-Host "Please input the desired version in one of those formats : 6, 6.0 or 6.0.0"
if($reqver.Length -lt 5) { $reqver = "$reqver*" }
$spheres = Get-VMHost | Where-Object {$_.Version -like $reqver}
process
}

function process{
$path = "$env:temp\vmware-hostver-$vcenter.csv"
$header = "Hostname,PowerState,Version"
Add-Content -Value $header -Path $path
foreach($vsphere in $spheres) {
$row = $vsphere.Name+","+$vsphere.PowerState+","+$vsphere.Version
Add-Content -Value $row -Path $path
}
Write-Host "Processing is done. Results are located in $path."
explorer $env:temp
}

Write-Host "vSphere host version listing script"
Write-Host "===================================`r`n"
$vcenter = Read-Host "vCenter to connect to ?"
Connect-VIServer $vcenter | Out-Null
Write-Host "1: List all hosts and versions on this vCenter`r`n2: List only hosts running under a specific version"
$mode = Read-Host "Choice"
switch ($mode){
1 { allhosts }
2 { spechosts }
}
Disconnect-VIServer $vcenter -confirm:$false | Out-Null
Write-Host "Bye."