Meilleur auteur de réponses
Copy-Item et backup

Question
-
Bonjour,
Cela fait plusieurs jours que je tente d'écrire un script pour sauvegarder les logs de mes serveurs (je précise que je suis novice en programmation) je commence à toucher au but mais je butte sur un problème...
L'idée générale du script est d'utiliser un fichier .ini pour gérer les paramètres (comme la liste des serveurs à sauvegarder ou encore le chemin vers le dossier de backup) afin d'assurer une meilleur portabilité dudit script, ensuite j’exécute une série de teste et travaux préparatoire (test de connexion avec les serveurs, vérification de présence du dossier de backup etc.) puis enfin vient la sauvegarde à proprement parlé (dont vous trouverez le code ci-dessous) :
Function Backup-EventLogs { $Logs = $ListLogs.Split(",") Foreach($Server in $ServerList) { $Tmp = $TmpRaw.replace("<SERVEUR>", $Server) $BackupSubDir = $BackupDirPath+"\"+$Date+"_"+$Server Write-Host " $Server" Foreach($Log in $Logs) { Try { $Path = "$tmp\$Log.evtx" $BackupLog = Get-WmiObject -Class Win32_NTEventlogFile -ComputerName $Server | Where-Object LogfileName -eq $Log $BackupLog.BackupEventlog($Path) | Out-Null Copy-Item -Path $Path -Destination $BackupSubDir -Force Write-Host " $Log.evtx... OK" } Catch { $_.exception.message } } #End Foreach Logs } #End Foreach Serveurs } #End Backup-EventLogs
la variable $TmpRaw contient une string du genre \\<SERVEUR>\c$\tmp qui est extraite du fichier ini. Il s'agit en fait du chemin vers un dossier temporaire nécessaire pour sauvegarder les logs avec la méthode .backupEventlog, car j'ai cru comprendre que cette dernière ne permettait pas de sauvegarder les logs sur un support distant.
Une fois les logs sauvegardés, j’exécute une copie vers le dossier de sauvegarde définitif... oui, mais non ! la sauvegarde en local s'effectue bien mais pas la copie, plus bizarre encore la commande Copy-Item ne renvoi aucune erreur et lorsque je tape la commande manuellement en remplaçant les variable par leur valeur respective ça fonctionne !
Quelqu'un peut-il m'expliquer ? (tant que je suis là je suis également preneur de toute remarque qui me permettrait d'améliorer mon script ou ma façon de l'écrire :-) )
Merci d'avance, cordialement.
Réponses
-
Mon script s’exécute sur la machine A, se connecte sur B (THOT-AD1) avec Invoke d'où il lance la copie des log à destination de A ! Ça compte vraiment pour un double saut ? Même si la commande est à destination de la machine d'origine ?
c'est un double même si la machine C est la A !! dommage
a tu essayer la solution suivante :
$ids = New-PSSession $server $Path = "c:\tmp\$Log.evtx" Copy-Item -FromSession $ids -Path $Path -Destination $BackupSubDir Remove-PSSession $ids
- Marqué comme réponse Nóla lundi 15 juillet 2019 07:00
Toutes les réponses
-
salut Mira.pro
ton script semble correct :)
tu devrait commencer par vérifier le contenu de $BackupSubDir et de $BackupDirPath à l'execution dans la fonction
Dans un deuxième temps comme ta fonction fait partie d'un script plus grand que l'on n'a pas, exécute tu cette fonction dans une session à distance ?
si oui tu a sans doute un problème de double saut
si non je vois pas ou est l'erreur, le mieux alors est de faire du débogage pas à pas dans l’éditeur ISE pour voir l'état des variable et aussi de nous transmettre les messages d'erreurs si il y en a
- Modifié 6ratgus mardi 9 juillet 2019 16:33
-
Bonjour 6ratgus,
Tout d'abord merci pour ta réponse :-)
Ensuite, non la fonction ne s’exécute pas sur une session à distance, comme je le disais je suis relativement novice en Powershell et je ne suis pas très familier le système de fonctionnement des sessions distantes... par exemple je ne comprends pas la différence entre New-PsSession et Enter-PsSession (c'est embêtant ^^) en fait j'utilise simplement l'attribut -ComputerName quand j'ai besoin pour exécuter une commande sur une machine distante et le symbole "c$" pour désigner un chemin d’accès local (sur le lecteur C:\ du coup) du genre "\\<SERVEUR>\c$\tmp".
Quand aux variables $BackupSubDir et $BackupDirPath leur contenu semble correcte, de même pour la variable $Path. Malgré cela, quand je lance le script rien ne ce passe, mais si je lance moi même la commande (en remplaçant les variables par les valeurs correspondante) la copie s'effectue ! En fait c'est comme si le script passait la commande sans l’exécuter...
EDIT:
C'est vraiment très bizarre, si j’insère dans le script la commande
Copy-Item "\\THOT-AD\c$\tmp\*" -Destination "\\THOT-CLT\Backuplog\20191007_THOT-AD"
Rien ne se passe, mais si je l'entre manuellement dans l'invite là ça fonctionne...
- Modifié Nóla mercredi 10 juillet 2019 11:29
-
Bonjour,
Peut-être le c$ qui pose problème ?
Essayez de créer un partage caché nommé tmp$ et modifiez \\thot-ad\c$\tmp par \\thot-ad\tmp$
-
bingo !
Merci Spunamo, le problème semble effectivement venir du c$, j'ai partage le dossier tmp, remplacé le paramètre dans le script et c'est tout bon :-)
Mais à présent... quelqu'un connaîtrait-il un moyen "techniquement abordable" de partager un dossier avec Powershell en sachant que je tourne sous W7/W2K8 ? J'ai cru comprendre que le module SmbShare n'était pas dispo sur les versions antérieurs à W10...
EDIT:
Bon OK j'me suis un peu emballé... ca marche pas en fait -_-'
J'ai modifié le code
$Path = "$tmp\$Log.evtx" $BackupLog = Get-WmiObject -Class Win32_NTEventlogFile -ComputerName $Server | Where-Object LogfileName -eq $Log $BackupLog.BackupEventlog($Path) | Out-Null Copy-Item -Path $Path -Destination $BackupSubDir -Force Write-Host " $Log.evtx... OK"
pour que la variable $tmp soit égale à \\THOT-AD1\tmp au lieu de \\THOT-AD1\c$\tmp
Mais à présent ça me dit que le paramètre -Path de la commande Copy-Item n'est pas valide car le chemin renvoyé par la variable $Path (à savoir "\\THOT-AD1\tmp\System.evtx") n'existe pas ! pourtant ce chemin existe bien puisque la méthode .BackupEventlog($Path) l'a créée juste avant !
- Modifié Nóla mercredi 10 juillet 2019 14:33
-
tu dit :
quand je lance le script rien ne ce passe, mais si je lance moi même la commande (en remplaçant les variables par les valeurs correspondante) la copie s'effectue
a tu fais comme je te l'ai dis un debug pour connaitre les valeur de tes variables ?
si tu ne sais pas utilisé le debogage de ISE va voir chez Microsoft ou sur ce site
tu peut aussi faire un simple write-host comme tu le fais pour $server
deuxième question : quand tu dis "je lance le script", tu le lance comment ? sur la même machine ? le même utilisateur ? ok y a trois questions
derniere question : a tu des messages d'erreurs ? il semble que oui peut nous les copier/coller ici
- Modifié 6ratgus mercredi 10 juillet 2019 17:07
-
Oui le debug n'a révélé aucune anomalie de ce coté là, les variables renvoient bien les bonnes valeurs.
Je pense que le problème vient du fait que le chemin renvoyé par $Path est un chemin local ! ( du genre "C:\tmp") il semblerait qu'il soit correctement interprété par la méthode .BackupEventlog comme un chemin pointant sur chaque machine à sauvegarder (et non pas un chemin sur la machine qui exécute le script) mais pas la commande Copy-Item.
Partant de la je me suis orienté sur l'utilisation d'une commande intermédiaire "Invoke-Command" (avec ma commande de copie dans le BlockScript) ainsi que l'utilisation des sessions PS (il a bien fallu que je m'y mette du coup ^^).
De là, nouveau problème => la commande me renvoi un jolie "Accès refusé" après recherche/vérification il semblerait que cela soit dû au fameux problème de "double saut" (même si je ne vois pas où il y a double saut puisque la copie se fait sur le PC qui exécute le script... )
Nouveau problème = nouvelle solution : utilisation de l'authentification CredSSP, j’exécute donc les commandes
Sur la station qui exécute le script :
Enable-WSManCredSSP -Role Client -DelegateComputer "THOT-AD1, THOT-EXCH1"
Sur les serveur à sauvegarder :
Enable-WSManCredSSP -Role Server
(Ou THOT-AD1 et THOT-EXCH1 sont les noms netbios de mes serveurs.)
Mais voila ça ne fonctionne toujours qu'à moitié... sur le serveur THOT-EXCH1 c'est ok mais pas sur le THOT-AD1. Le serveur me renvoie l'erreur :
New-PSSession : [THOT-AD1] Connecting to remote server THOT-AD1 failed with the following error message : Le client WinRM ne peut pas traiter la demande. Une stratégie d’ordinateur ne permet pas la délégation des informations d’identification de l’utilisateur à l’ordinateur cible car ce dernier n’est pas approuvé. L’identité de l’ordinateur cible ne peut pas être vérifiée si vous configurez le service WSMAN pour utiliser un certificat valide à l’aide de la commande suivante: winrm set winrm/config/service '@{CertificateThumbprint="<thumbprint>"}' Sinon, vous pouvez rechercher dans l’Observateur d’événements un événement qui spécifie que le SPN suivant n’a pas pu être créé: WSMAN/<computerFQDN>. Si vous trouvez cet événement, vous pouvez manuellement créer le SPN à l’aide de setspn.exe. Si le SPN existe, mais que CredSSP ne peut pas utiliser Kerberos pour valider l’identité de l’ordinateur cible et si vous souhaitez toujours autoriser la délégation des informations d’identification de l’utilisateur à l’ordinateur cible, utilisez gpedit.msc et examinez la stratégie suivante: Configuration de l’ordinateur -> Modèles d’administration -> Système -> Délégation d’informations d’identification -> Autoriser les nouvelles informations d’identification avec l’authentification du serveur NTLM uniquement. Vérifiez qu’elle est activée et configurée avec un SPN approprié pour l’ordinateur cible. Par exemple, pour le nom d’ordinateur cible «monserveur.domaine.com», le SPN peut être: WSMAN/monserveur.domaine.com ou WSMAN/*.domaine.com. Renouvelez la demande après ces modifications. For more information, see the about_Remote_Troubleshooting Help topic. At Z:\LOG\Logs_Backup_v1.0a.ps1:331 char:18 + ... $s = New-PSSession -ComputerName $Server -Credential $Credenti ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemotingTransportException + FullyQualifiedErrorId : -2144108124,PSSessionOpenFailed
Et la je suis bloqué...
- Modifié Nóla vendredi 12 juillet 2019 12:04
-
inutile de faire du credSSP si tu arrive a faire fonctionne ton code en mettent les valeurs en dure !!
mais tu peut si tu veux regarde ce post sur le sujet
Oui le debug n'a révélé aucune anomalie de ce coté là, les variables renvoient bien les bonnes valeurs.
bonne nouvelle donc la variable $path contient "\\THOT-AD1\c$\tmp\quelque chose.evtx" ?
puisque ton code le construit ainsi :
$Tmp = $TmpRaw.replace("<SERVEUR>", $Server)
$Path = "$tmp\$Log.evtx"
hors du dis :
Je pense que le problème vient du fait que le chemin renvoyé par $Path est un chemin local ! ( du genre "C:\tmp") il semblerait qu'il soit correctement interprété par la méthode .BackupEventlog comme un chemin pointant sur chaque machine à sauvegarder (et non pas un chemin sur la machine qui exécute le script) mais pas la commande Copy-Item.
si $path contient un lecteur local (du type c:\), c'est que ton code ne marche pas !!
mais tu a vérifier en debug ou avec un write-host que la variable est bonne. Donc ça doit marcher comme quand tu le fais à la main
Copy-Item "\\THOT-AD\c$\tmp\*" -Destination "\\THOT-CLT\Backuplog\20191007_THOT-AD"
si $path contient un lecteur local, c'est que ton code ne marche pas !! ? mais tu a vérifier en debug ou avec un write-host, la variable est bonne. Donc ça doit marcher comme quand tu le fais à la main
j'insiste mais pour moi
- soit la construction de ta variable $path ne fonctionne pas comme tu le veux
- soit tu n'utilise pas le script avec les mêmes paramètres (utilisateur, ordinateur, élévation admin) que quand tu faire la manip avec les valeurs en dure dans copy-item dans le script
dernière info tu peut utilisé copy-item avec l'option fromsession ou tosession voir la doc
qui permet la copie depuis un lecteur local d'un serveur distant vers un autre dossier local ou réseau
- Modifié 6ratgus vendredi 12 juillet 2019 13:52
-
Autant pour moi je n'ai pas précisé que j'avais testé une autre option avec la variable $Path, (au lieu de passer par le partage part défaut c$ je suis passé par un chemin local en "dur" de type C:\tmp que je manipulais via la commande Invoke-Commande) mais vu que cela n'a pas porté de fruit j'abandonne cette option et reprends le postulat de départ:
La variable $Path fonctionne correctement et renvoie bien le résultat attendu à savoir par exemple "\\THOT-AD1\c$\tmp\System.evtx"
Cette variable fonctionne correctement quand je l'utilise avec la méthode .BackupLog($Path) (Le fichier de log est correctement sauvegardé dans le dossier temporaire du serveur concerné)
En revanche elle ne fonctionne pas que je tente de l’utiliser avec la commande Copy-Item ! J'obtiens à la place un jolie message d'erreur m'informant que "can not find path '\\THOT-AD1\c$\tmp\Application.evtx' because it does not exist"
Du coup je tente de l'utiliser en passant par la commande Invoke-Commande, et là... ça fonctionne pour l'AD mais pas pour THOT-EXCH1 ! pour ce dernier j'obtiens le message d'erreur "Accès refusé"
pour lancer le script je le fait depuis l'interface Powershell ISE (en mode admin), quand je tente d’exécuter la commande "manuellement" je le fait depuis l'invite Powershell ISE, juste sous mon script... tu penses que ça peut venir de là ?
-
ok je vois plus clair maintenant
pour lancer le script je le fait depuis l'interface Powershell ISE (en mode admin), quand je tente d’exécuter la commande "manuellement" je le fait depuis l'invite Powershell ISE, juste sous mon script... tu penses que ça peut venir de là ?
non aucun problème par rapport a ces manip :)
Cette variable fonctionne correctement quand je l'utilise avec la méthode .BackupLog($Path) (Le fichier de log est correctement sauvegardé dans le dossier temporaire du serveur concerné)
avec BackupLog tu accède à distance au serveur THOT-AD1 via l'option -ComputerName du WMI. tu a donc un premier saut, ce qui explique pourquoi tu n'arrive pas a écrire directement sur le deuxième serveur car ça fais un deuxième saut (problème double hop)
En revanche elle ne fonctionne pas que je tente de l’utiliser avec la commande Copy-Item ! J'obtiens à la place un jolie message d'erreur m'informant que "can not find path '\\THOT-AD1\c$\tmp\Application.evtx' because it does not exist"
peut tu avec l'explorateur Windows avoir accès à ce dossier depuis la machine ou tu execute le script ??
si non ton problème est la !!!
source possible :
- résolution DNS du nom du serveur THOT-AD sur ta machine,
- blocage firewall,
- limitation dans le partage de c$,
- le dossier destination n'existe pas : celui avec la date et le nom du serveur (20191007_THOT_AD)
au passage des fois tu met AD1 des fois AD tout court
si oui ,
- je reviens encore sur le contenu de la variable $path
- peut-etre faut t'il rajouter un "\" a la fin de $BackupSubDir
- il arrive parfois qu'un caractère invisible ce soit glissé dans la ligne du copy-item. solution il te retaper toute la ligne de code !!
Du coup je tente de l'utiliser en passant par la commande Invoke-Commande, et là... ça fonctionne pour l'AD mais pas pour THOT-EXCH1 ! pour ce dernier j'obtiens le message d'erreur "Accès refusé"
la c'est un problème d'autorisation d’accès ( le double saut ) !!! ton script tourne sur ta machine "A", tu te connecte au serveur "B" THOT-AD1 via invoke (premier saut) et depuis ce serveur AD tu essai d'accédé au serveur "C" THOT-EXCH1 pour le copy-item (deuxième saut)
derniere idée avant le weekend :
$ids = New-PSSession $server $Path = "c:\tmp\$Log.evtx" Copy-Item -FromSession $ids -Path $Path -Destination $BackupSubDir Remove-PSSession $ids
pour info j'ai fait un test rapide de ton script sans soucis
- Modifié 6ratgus vendredi 12 juillet 2019 18:39
-
Oui avec l'explorateur Windows j'y accède très bien, le contenu de cette variable ne peut tout simplement pas être faux puisque c'est exactement la même variable qui est utilisée juste au dessus pour le .BackupEventlog qui lui fonctionne très bien...
Pour ce qui est de rajouter un "\" a la fin de $BackupSubDir, je ne vois pas pourquoi puisque ce n'est pas cette variable qui est incriminée... (dans le doute j'ai testé mais sans résultat)
A force de tripaturer mon script j'ai modifié le nom de certaines variables, pour plus de clarté je poste donc une version "simplifiée" du script...
Param( $ErrorActionPreference = 'stop', $ConfFile = "$LocalPath\Configuration.ini", $TempRaw = "\\<SERVEUR>\c$\Temp" ) Function Import-Conf { $ItemFileConf = Get-Item -Path $ConfFile #Remplissage de la table de hash avec les éléments du fichier .ini $ConfTable = @{} Switch -Regex -File $ItemFileConf {...} #Déclaration des nouvelles variables $Script:ListLogs = $ConfTable.PARAMETRES["Logs"] $Script:BackupDirPath = $ConfTable.PARAMETRES["Dossier_Backup"] $Script:BackupDirName =$ConfTable.PARAMETRES["Dossier_Backup"].split("\")[-1] $Script:BackupPCName = $ConfTable.PARAMETRES["Dossier_Backup"].split("\")[2] $Script:ServerList = $ConfTable.SERVEURS.Keys Ctrl-Server } #End Import-Conf Function Ctrl-Server {...} #End Ctrl-Server Function Ctrl-BackupDir {...} #End Ctrl-BackupDir Function Ctrl-TmpDir {...} #End Ctrl-TmpDir Function Backup-EventLogs { Write-Host "`nDébut de la sauvegarde des logs.`n" -ForegroundColor Green $Date = Get-Date -Format "yyyyMMdd" $Logs = $ListLogs.Split(",") Foreach($Server in $ServerList) { $Temp = $TempRaw.replace("<SERVEUR>", $Server) $BackupSubDir = $BackupDirPath+"\"+$Date+"_"+$Server Write-Host "|| $Server ||`n" -ForegroundColor Gray #Controle du sous-dossier de sauvegarde des log (dossier du jour du type "20190703_THOT-AD1"] If(Test-Path $BackupSubDir) {...} Foreach($Log in $Logs) { Try { $LogBackupTempPath = "$Temp\$Log.evtx" $BackupLog = Get-WmiObject -Class Win32_NTEventlogFile -ComputerName $Server | Where-Object LogfileName -eq $Log $BackupLog.BackupEventlog($LogBackupTempPath) | Out-Null $LogBackupTempPath Copy-Item -Path "\\THOT-AD1\c$\Temp\Application.evtx" -Destination $BackupSubDir -Force #Invoke-Command -ComputerName $Server -ScriptBlock{param($LogBackupTempPath, $BackupSubDir)Copy-Item -Path $LogBackupTempPath -Destination $BackupSubDir -Force} -ArgumentList $LogBackupTempPath, $BackupSubDir Write-Host " $Log.evtx... OK" } Catch {...} } #End Foreach Logs } #End Foreach Serveurs } #End Backup-EventLogs $LocalPath = Split-Path -parent $MyInvocation.MyCommand.Definition Clear-Host Ctrl-ConfFile
Pour le double saut ce que je ne comprends pas c'est pourquoi je passerai du Serveur B au Serveur C ?
Mon script s’exécute sur la machine A, se connecte sur B (THOT-AD1) avec Invoke d'où il lance la copie des log à destination de A ! Ça compte vraiment pour un double saut ? Même si la commande est à destination de la machine d'origine ?
-
Mon script s’exécute sur la machine A, se connecte sur B (THOT-AD1) avec Invoke d'où il lance la copie des log à destination de A ! Ça compte vraiment pour un double saut ? Même si la commande est à destination de la machine d'origine ?
c'est un double même si la machine C est la A !! dommage
a tu essayer la solution suivante :
$ids = New-PSSession $server $Path = "c:\tmp\$Log.evtx" Copy-Item -FromSession $ids -Path $Path -Destination $BackupSubDir Remove-PSSession $ids
- Marqué comme réponse Nóla lundi 15 juillet 2019 07:00
-