Powershell : obtention de la taille d’un share

Voici un petit script Powershell permettant de récupérer la taille d’un ou plusieurs share.

Ce script peut être appelé de deux manières :

  • sans arguments : le script va chercher un fichier texte dans le répertoire d’exécution pour passer sur TOUS les répertoires indiqués dans le fichier (un partage par ligne) ; le but est donc de renseigner tous les partages pour lesquels on souhaite connaître la volumétrie dans le fichier. Le script retourne ensuite un fichier CSV :
 
 
 
 
  •  avec des arguments : en donnant en argument d’exécution du script le serveur et le partage, on récupère la taille dans la console directement :
param([string]$shareHost, [string]$shareName)

function folderSize()
{
param($path)
try {
$byteSize = (Get-ChildItem -path "$path" -Recurse -ErrorAction SilentlyContinue | Measure-Object Length -sum).Sum
if ($byteSize.ToString().Length -lt 4) { return "$byteSize B." }
if ($byteSize.ToString().Length -ge 4 -and $byteSize.ToString().Length -lt 7) { $kbSize = [math]::Round($byteSize/1024,1) ; return "$kbSize KB." }
if ($byteSize.ToString().Length -ge 7 -and $byteSize.ToString().Length -lt 10) { $mbSize = [math]::Round($byteSize/1048576,1) ; return "$mbSize MB." }
if ($byteSize.ToString().Length -ge 10 -and $byteSize.ToString().Length -lt 13) { $gbSize = [math]::Round($byteSize/1073741824,1) ; return "$gbSize GB." }
if ($byteSize.ToString().Length -ge 13) { $tbSize = [math]::Round($byteSize/1099511627776,2) ; return "$tbSize TB." }
}
catch { return "Share doesn't exist or is unreachable or you don't have the required privileges." }
}

Write-Host "Share size retriever Powershell script"
Write-Host "======================================"
Write-Host "Usage: .\win_foldersize.ps1 <SERVER> <SHARE>"
Write-Host "If any parameter is missing, the script will look for a sharelist.txt file in the execution folder and will detect the size of all the folders inside the file."

if ($shareHost -eq "" -or $shareName -eq "")
{
Write-Host "You didn't provide both parameters while running the script. I will now try to read directly the shares from sharelist.txt in the script folder."
$today = Get-Date -f "yyMMdd"
$CsvOutputFile = "share-size-$today.csv"
$InputFile = "sharelist.txt"
$CsvHeader = "Share,Size"
Add-Content $CsvOutputFile $CsvHeader
try { $ShareList = Get-Content $InputFile -ErrorAction Stop }
catch { Write-Host "Unable to read sharelist.txt. Aborting." ; break }
foreach ($Share in $ShareList)
{
$sizeDump = folderSize($Share)
$Dump = "$Share,$sizeDump"
Add-Content $CsvOutputFile $Dump
}
Write-Host "Done, output file : $CsvOutputFile"
}
else {
Write-Host "Both parameters detected."
Write-Host "Server specified: $shareHost"
Write-Host "Share: $shareName"
$shareString = "\\"+"$shareHost"+"\"+"$shareName"
$displaySize = folderSize($shareString)
Write-host $displaySize
}

Powershell : audit des serveurs SQL Server

J’ai développé en prenant comme base ce script sur le TechNet un script Powershell récupérant diverses informations propres aux serveurs SQL Server dont le nom est renseigné dans un fichier CSV.

Le script parcourt dans le fichier CSV spécifié la colonne ayant pour entête ServerName (si jamais votre extract d’origine comprend plusieurs colonnes, comme le nom de l’instance par exemple) et va tenter de récupérer plusieurs informations pour chacun des hostname lus. Une fois un serveur traité, les détails recueillis sont ajoutés à un fichier CSV exploitable par la suite dans Excel par exemple.

Un exemple de fichier d’entrée avec les hostname des serveurs SQL à auditer.

Je n’ai pas réalisé de contrôles particuliers sur l’écriture ou l’accès aux serveurs SQL dans le script, il faudra donc en cas de dysfonctionnement quelconque s’assurer que les fichiers CSV d’entrée et sortie puissent être lus et écrits sur le disque et que l’utilisateur exécutant le script ait un minimum de privilèges sur SQL Server.

[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO')

function Get_ProperOS{
param($OS)
if ($OS -like '5.0*') { return "Windows Server 2000" }
elseif ($OS -like '5.2*') { return "Windows Server 2003" }
elseif ($OS -like '6.0*') { return "Windows Server 2008" }
elseif ($OS -like '6.1*') { return "Windows Server 2008 R2" }
elseif ($OS -like '6.2*') { return "Windows Server 2012" }
elseif ($OS -like '6.3*') { return "Windows Server 2012 R2" }
elseif ($OS -like '10.0*') { return "Windows Server 2016" }
else { return "Unknown NT version" }
}

function Get_ProperSQL{
param($SQL)
if ($SQL -like '8.0*') { return "SQL Server 2000" }
elseif ($SQL -like '9.0*') { return "SQL Server 2005" }
elseif ($SQL -like '10.0*') { return "SQL Server 2008" }
elseif ($SQL -like '10.5*') { return "SQL Server 2008 R2" }
elseif ($SQL -like '11.0*') { return "SQL Server 2012" }
elseif ($SQL -like '12.0*') { return "SQL Server 2014" }
elseif ($SQL -like '13.0*') { return "SQL Server 2016" }
elseif ($SQL -like '14.0*') { return "SQL Server 2017" }
else { return "Unknown SQL version" }
}

function Get_ServerName{
param($SqlHostProperties)
$SrvHostname = $SqlHostProperties | where {$_.name -eq "ComputerNamePhysicalNetBios"} | select value
return $SrvHostname.Value
}

function Get_ServerMemory{
param($SqlHostProperties)
$SrvMemory = $SqlHostProperties | where {$_.name -eq "PhysicalMemory"} | select value
return $SrvMemory.Value
}

function Get_ServerProcessors{
param($SqlHostProperties)
$SrvCPUs = $SqlHostProperties | where {$_.name -eq "Processors"} | select value
return $SrvCPUs.Value
}

Write-Host "SQL Server Inventory Powershell Script"
Write-Host "======================================"
$today = Get-Date -f "yyMMdd"
$CsvFile = "C:\temp\SqlServer_Inventory_$today.csv"
Clear-Content -path $CsvFile -Force
$CsvHeader = "ServerName,OS,SqlServerVersion,SqlServerEdition,SqlServicePack,Cores,RAM"
Add-Content $CsvFile $CsvHeader
$SqlSrvListFile = "sqlsrv_list.csv"
$SqlSrvList = [object]$SqlSrvList = Import-CSV $SqlSrvListFile
foreach ($SqlServer in $SqlSrvList.ServerName) {
Write-Host "Working on $SqlServer"
$SqlHost = New-Object -type Microsoft.SqlServer.Management.Smo.Server -ArgumentList $SqlServer
if ($SqlHost.ComputerNamePhysicalNetBIOS -ne $null) {
$SqlHostProperties = $SqlHost.Information.Properties | select Name,Value
$ServerName = Get_ServerName($SqlHostProperties)
$OSVersString = Get_ProperOS($SqlHost.OSVersion)
$SqlVersString = Get_ProperSQL($SqlHost.VersionString)
$SqlEdit = $SqlHost.Edition
$SqlSpack = $SqlHost.ProductLevel
$Cpu = Get_ServerProcessors($SqlHostProperties)
$Mem = Get_ServerMemory($SqlHostProperties)
$Dump =  "$ServerName"+","+"$OSVersString"+","+"$SqlVersString"+","+"$SqlEdit"+","+"$SqlSpack"+","+"$Cpu"+","+"$Mem"
Add-Content $CsvFile $Dump
}
else { Write-Host "Couldn't query $SqlServer." }
}
Write-Host "Done."

Voici une copie d’écran d’exemple du fichier CSV généré par le script :

Désactivation de OneDrive via GPO

Petite problématique du jour, désactiver proprement OneDrive sur les stations du domaine via GPO. Rien de bien difficile, tout est déjà prévu dans les politiques pour désactiver le composant OneDrive sur des OS Windows 7 ou plus récents.

Tout d’abord, création d’un groupe d’ordinateurs dans l’ActiveDirectory ; à terme il faudra cibler tous les postes et donc un filtre par défaut suffira une fois la GPO liée à l’OU comprenant les stations, mais étant donné qu’au départ il s’agit d’un pilote, le plus simple était de créer un groupe et d’ajouter dedans petit à petit les stations concernées par la GPO et utiliser le groupe comme filtre.

Les paramètres concernant OneDrive se trouvent dans Computer > Policies > Administrative Templates > Windows Components > OneDrive :

Il suffit d’activer l’option visant à empêcher l’utilisation de OneDrive pour le stockage de fichiers.

Ensuite, lier la GPO sur l’OU concernée ; attention, en utilisant en filtre un groupe d’ordinateurs, il faut lier la GPO sur l’OU englobant toutes les stations concernées, sans quoi la politique ne redescendra pas sur lesdites stations.

Un gpupdate /force plus tard sur les stations visées par la GPO, on a bien disparition du lien OneDrive sur le bandeau de navigation sur la gauche et il est impossible pour certaines applications installées sur la machine de sauvegarder les données sur OneDrive ou même de les charger ; par ailleurs un appel de l’application OneDrive ne donne rien.

Avant.
Après.

Powershell : compression et archivage automatique de logs

En vue d’une éventuelle mise en place d’un event collector permettant de centrer en un seul et même endroit tous les logs générés par les machines et lisibles en local dans l’event viewer, j’ai développé un petit script Powershell permettant une compression automatique des logs présents dans un répertoire dans un but d’archive. Le script ne retourne aucune information et ne procède à aucune vérification puisqu’il est idéalement appelé depuis une tâche planifiée et les droits de lecture/écriture par rapport au compte d’exécution auront été contrôlés auparavant. La journalisation étant activée, il sera possible de tracer les actions de 7z.exe et constater le succès ou l’échec de l’archivage.

Le script exécute 7-Zip, compresse les fichiers *.evtx dans une archive puis les supprime. Il conviendra naturellement d’adapter les chemins en fonction de l’environnement.

$7zpath = "C:\Program Files\7-Zip"
$logpath = "C:\events\logs-files\*.evtx"
$archivepath = "C:\events\archives"
$date = Get-Date -Format "yyyy-MM-dd"
$archivename = "logs-archive-$date.zip"
$7zreport = "C:\events\7z-compresslog-$date.log"
cd $7zpath
.7z.exe a "$archivepath$archivename" -r $logpath -mx=9 -bb -sdel > $7zreport 2>&1