IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Scripts/Batch Discussion :

Saturation mémoire cause récursivité [PowerShell]


Sujet :

Scripts/Batch

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 72
    Points : 61
    Points
    61
    Par défaut Saturation mémoire cause récursivité
    Bonjour

    J'ai créé ce petit script qui permet d'analyser tous les droits d'un ou des utilisateurs.
    Le problème est ma fonction de récursivité.
    Les données ce chargement en mémoire tant que la boucle n'est pas terminé.

    Je débute en powershell (merci à Laurent Dardenne pour le cour sur les porté)
    Et je ne sais pas comment libéré mes données au fur et a mesure.

    avez vous des piste à me donner ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    Param([String]$Path=(Get-Location).Path, [bool]$Recurse=$false)
    
    #Import ActiveDirectory Module if not loaded
    $Module = Get-Module ActiveDIrectory
    If ($Module -eq $Null) {Import-Module ActiveDirectory}
    
    $strPATH = $Path
    
    #Initialisation du tableau
    $tabACL=@()
    
    Function fAD_Name{
        Param ([string]$strAccountName)
    	
        if ($strAccountName.Contains("\")){
    	#Retourne uniquement le sAMAccountName
    	return [String]$strAccountName = ($strAccountName.Split("\")[-1]).Trim()
        } Else {
            return $strAccountName.Trim()
    	}
    }
    
    Function fAddTab(){
        Param([String]$strDirectory,[String]$strMemberName,[String]$strMemberOf='',[PSObject]$Access)
        
        $Dico=New-Object PSObject
        $Dico | Add-Member -Name Directory -MemberType NoteProperty -Value $strDirectory
        $Dico | Add-Member -Name User -MemberType NoteProperty -Value $strMemberName
        $Dico | Add-Member -Name MemberOf -MemberType NoteProperty -Value $strMemberOf
        $Dico | Add-Member -Name FileSystemRights -MemberType NoteProperty -Value $($Access.FileSystemRights).ToString() -PassThru
        $Dico | Add-Member -Name AccessControlType -MemberType NoteProperty -Value $($Access.AccessControlType).ToString() -PassThru
        $Dico | Add-Member -Name IsInherited -MemberType NoteProperty -Value $($Access.IsInherited).ToString() -PassThru
        Return $Dico
    }
    
    Function fAD_AddMembers(){
        Param (
            [String]$strCNObjectAD,
            [String]$strFolder,
            [PSObject]$Ace,
            [String]$strSubCNObjectAD=''
        )
        
        $strCNObjectAD = $strCNObjectAD.Trim()
    
        #Récupureation de l'objet Active Directory (User ou Group)
        $objADObject = Get-ADObject -LDAPFilter "(sAMAccountName=$strCNObjectAD)" -properties Name, ObjectClass, Member
    
        Switch ([String]$objADObject.ObjectClass){
            "group" {
                #Pour Chaque membre du  groupe
                ForEach ($Member in $objADObject.member){
                
                    $objADO = Get-ADObject -LDAPFilter "(distinguishedName=$Member)" -properties cn, ObjectClass
    
                    #Si dans les membres ont trouve un autre groupe, alors ont rappel la fonction
    			    if ($objADO.ObjectClass -like 'group') {
    				    fAD_AddMembers -strCNObjectAD $objADO.cn -strFolder $strFolder -Ace $Ace -strSubCNObjectAD $strCNObjectAD
                    }Else{
                        $script:tabACL+=fAddTab -strDirectory $strFolder -strMemberName $objADO.cn -strMemberOf $strCNObjectAD -Access $Ace
                    }
                }
                break
            }
            "user"{
    		    #Entrée utilisateur
    		    $script:tabACL+=fAddTab -strDirectory $strFolder -strMemberName $objADObject.Name -Access $Ace
                break
            }
            Default{
                $script:tabACL+=fAddTab -strDirectory $strFolder -strMemberName $strCNObjectAD -Access $Ace
            }
        }
    }
    
    if($Recurse -eq $true){
        $liste_repertoire = Get-childitem $strPATH -recurse
    }Else{
        $liste_repertoire = Get-childitem $strPATH
    }
    
    foreach ($repertoire in $liste_repertoire){
        if($repertoire.Attributes -eq "Directory"){
            
            $global_acl = Get-Acl $repertoire.FullName
    
            foreach ($droit in $global_acl.Access){
                $strIdentification = fAD_Name $droit.IdentityReference
                fAD_AddMembers -strCNObjectAD $strIdentification.trim() -strFolder $repertoire.FullName -Ace $droit
    	}
        }
    }
    return $tabACL

  2. #2
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Salut,
    utilise un tableau de type Arraylist, l'ajout dans un tableau de base ( $Tab=@() ) peut provoquer une surcharge mémoire en cas de volumétrie importante.
    Le type System.Array n'est pas redimensionnable, .Net recrée un nouveau tableau à chaque ajout et 'abandonne' l'ancien, la mémoire ainsi occupée par les multiples copies sera libérée à un moment donné...

    Essaie déjà cela.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 72
    Points : 61
    Points
    61
    Par défaut
    Merci encore une fois.

    J'ai bien optimiser l'utilisation de la mémoire par contre j'affiche quatre fois une entré de la arraylist ???
    J'y es passé un moment pour essaye de comprendre ce je que j'ai mal fait mais la il doit y avoir un mécanisme que je ne comprend pas.

    Ci dessous l'illustration de ma première entrée dans la arraylist.

    Nom : debug.png
Affichages : 308
Taille : 86,5 Ko

    Voici mon code modifier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    Param([String]$Path=(Get-Location).Path, [bool]$Recurse=$false)
    
    #Import ActiveDirectory Module if not loaded
    $Module = Get-Module ActiveDIrectory
    If ($Module -eq $Null) {Import-Module ActiveDirectory}
    
    #Initialisation du tableau
    $tabACL = New-Object System.Collections.ArrayList(0)
    $AclIndice
    
    Function fAD_Name{
    	Param ([string]$strAccountName)
    	
    	if ($strAccountName.Contains("\")){
    		#Retourne uniquement le sAMAccountName
    		return [String]$strAccountName = ($strAccountName.Split("\")[-1]).Trim()
        } Else {
            return $strAccountName.Trim()
    	}
    }
    
    Function fAddTab(){
    	Param([String]$strDirectory,[String]$strMemberName,[String]$strMemberOf='',[PSObject]$Access)
        
    	$Dico=New-Object PSObject
    	$Dico | Add-Member -Name Directory -MemberType NoteProperty -Value $strDirectory
    	$Dico | Add-Member -Name User -MemberType NoteProperty -Value $strMemberName
    	$Dico | Add-Member -Name MemberOf -MemberType NoteProperty -Value $strMemberOf
    	$Dico | Add-Member -Name FileSystemRights -MemberType NoteProperty -Value $($Access.FileSystemRights).ToString() -PassThru
    	$Dico | Add-Member -Name AccessControlType -MemberType NoteProperty -Value $($Access.AccessControlType).ToString() -PassThru
    	$Dico | Add-Member -Name IsInherited -MemberType NoteProperty -Value $($Access.IsInherited).ToString() -PassThru
    	
        Write-Host $Dico
    	Return $Dico
    }
    
    Function fAD_AddMembers(){
        Param (
            [String]$strCNObjectAD,
            [String]$strFolder,
            [PSObject]$Ace,
            [String]$strSubCNObjectAD=''
        )
        
        $strCNObjectAD = $strCNObjectAD.Trim()
    
    	#Récupureation de l'objet Active Directory (User ou Group)
        $objADObject = Get-ADObject -LDAPFilter "(sAMAccountName=$strCNObjectAD)" -properties Name, ObjectClass, Member
    
        Switch ([String]$objADObject.ObjectClass){
            "group" {
                #Pour Chaque membre du  groupe
    		    ForEach ($Member in $objADObject.member){
                
                    $objADO = Get-ADObject -LDAPFilter "(distinguishedName=$Member)" -properties cn, ObjectClass
                    
                    #Si dans les membres ont trouve un autre groupe, alors ont rappel la fonction
    			    if ($objADO.ObjectClass -like 'group') {
    				    fAD_AddMembers -strCNObjectAD $objADO.cn -strFolder $strFolder -Ace $Ace -strSubCNObjectAD $strCNObjectAD
                    }Else{
                        $script:AclIndice=$script:tabACL.add(1)
    					$script:tabACL[$script:AclIndice]=fAddTab -strDirectory $strFolder -strMemberName $objADO.cn -strMemberOf $strCNObjectAD -Access $Ace
                    }
                }
                break
            }
            "user"{
    		    #Entrée utilisateur
    		    $script:AclIndice=$script:tabACL.add(1)
    			$script:tabACL[$script:AclIndice]=fAddTab -strDirectory $strFolder -strMemberName $objADObject.Name -Access $Ace
                break
            }
            Default{
    			$script:AclIndice=$script:tabACL.add(1)
                $script:tabACL[$script:AclIndice]=fAddTab -strDirectory $strFolder -strMemberName $strCNObjectAD -Access $Ace
                break
            }
        }
    }
    
    if($Recurse -eq $true){
        $liste_repertoire = Get-childitem $Path -recurse | Where-Object{$_.PSIsContainer}
    }Else{
        $liste_repertoire = Get-childitem $Path | Where-Object{$_.PSIsContainer}
    }
    
    foreach ($repertoire in $liste_repertoire){
        if($repertoire.Attributes -eq "Directory"){
            
            $global_acl = Get-Acl $repertoire.FullName
    
            foreach ($droit in $global_acl.Access){
                
                $strIdentification = fAD_Name $droit.IdentityReference
                fAD_AddMembers -strCNObjectAD $strIdentification.trim() -strFolder $repertoire.FullName -Ace $droit
    		}
        }
    }
    
    return $tabACL

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 72
    Points : 61
    Points
    61
    Par défaut
    J'ai résolu mon problème d'affiche.

    J'avais bêtement appliqué l'argument -PassThru sans comprendre à quoi il servait.

    Par contre, je n'arrive plus a exporter mon résultat dans un CSV.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    '.\AccessRights.ps1' | Export-Csv D:\ACL.csv
    Voici le contenu de mon CSV :


    #TYPE System.String
    "Length"
    "29"

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 72
    Points : 61
    Points
    61
    Par défaut
    bon je suis un boulet j'ai oublié le caractère & devant l'appel de mon script.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $'.\AccessRights.ps1' | Export-Csv D:\ACL.csv
    Merci de ton aide qui m'oriente et m’instruis.

    J'ai encore des améliorations a faire notamment une gestion des erreurs pour évite par exemple les noms de dossier trop long.

    A bientôt pour de l'aide ou pour partager le résultat de mon travail.

  6. #6
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Pour la gestion des noms longs tu as ce module autour d'une librairie dédiée. Il y a un post sur le sujet dans ce forum qui utilise la dll directement et sur une volumétrie très importante.

    Au cas où, pour la gestion des erreurs tu as un tuto ici.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 6
    Dernier message: 31/01/2011, 16h45
  2. [Toutes versions] Problème de saturation mémoire lors d'une copie de contact
    Par langkif dans le forum VBA Outlook
    Réponses: 3
    Dernier message: 25/08/2010, 10h08
  3. problème de saturation mémoire
    Par Mengué georges dans le forum Tomcat et TomEE
    Réponses: 2
    Dernier message: 17/03/2008, 21h58
  4. Eclipse 3.2 WTP problème saturation mémoire
    Par javanat dans le forum Eclipse Java
    Réponses: 0
    Dernier message: 03/09/2007, 20h11
  5. Réponses: 7
    Dernier message: 04/06/2007, 12h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo