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

Shell et commandes GNU Discussion :

Lister et utiliser les utilisateurs d'un groupe


Sujet :

Shell et commandes GNU

  1. #1
    Membre averti
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2011
    Messages : 17
    Par défaut Lister et utiliser les utilisateurs d'un groupe
    Bonjour à tous,

    J'explique mon problème :

    j'ai actuellement 1 groupe que l'on va nommer "groupe1" qui possède plusieurs utilisateurs (user1, user2 et user3)

    Je dois créer un script sous linux qui me permet de récupérer la liste des utilisateurs du groupe groupe1 et pour chaque utilisateur, exécuter une suite d'action.

    j'ai déjà vérifier qu'une commande :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cat /etc/group |grep groupe1
    me renvoie bien la ligne associée au groupe1 du fichier /etc/group. Mais j'aimerai tirer de cette commande uniquement la liste des utilisateurs et pouvoir réaliser pour chaque utilisateur plusieurs action

    Merci d'avance pour vos conseils et réponses!!

  2. #2
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Par défaut
    Tu aurais pu faire plus simple que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cat /etc/group |grep groupe1
    en laissant tomber le cat inutile:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    grep groupe1 /etc/group
    Mais problème si tu as aussi un groupe nommé groupe10, ca ne marche plus. Le code suivant est meilleur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    grep -w groupe1 /etc/group
    mais les groupes peuvent être définis ailleurs que dans /etc/group.

    Cette commande gère toutes les sources pour la base group:
    mais il subsiste un autre problème, seuls les utilisateurs dont le groupe group1 est un groupe secondaire seront listés. Si tu veux aussi ceux dont c'est le groupe primaire, il faudra regarder chaque entrée utilisateur dans la base passwd.

    Voilà quelque chose qui devrait régler les problèmes évoqués ci-dessus:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    for user in $(g=$1
    gid=$(getent group $1 | awk -F : '{print $3}')
    (
      getent group $1 | awk -F : '{gsub(","," ",$4);print $4}'
      getent passwd | awk -F : -v gid=$gid '$3==gid {print $1}'
    ) | sort -u )
    do
      echo user=$user
    done

  3. #3
    Membre averti
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2011
    Messages : 17
    Par défaut
    Merci pour ta réponse,

    Effectivement on s'approche de la réponse, cependant, j'ai créé 2 utilisateurs au groupe groupe1 et lorsque j'exécute ton code, il me les trouve pas.

    J'ai alors exécuté la commande :

    et effectivement je n'ai pas les nouveaux utilisateurs d'affiché....

    Pourtant quand je vais dans la gestion des utilisateurs, j'ai bien mes nouveaux utilisateurs qui appartiennent tout deux au groupe groupe1.

    Est ce que j'ai loupé un truc?

    Je n'arrive d'ailleurs pas trop à comprendre ce qui se passe dans la partie de code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    gid=$(getent group $1 | awk -F : '{print $3}')
    (
      getent group $1 | awk -F : '{gsub(","," ",$4);print $4}'
      getent passwd | awk -F : -v gid=$gid '$3==gid {print $1}'
    ) | sort -u )
    je me doute que cela doit renvoyer l'id du groupe passé en paramètre du script, et encore j'en suis pas certain....

    J'ai vérifié et dans le fichier /etc/passwd il y a bien mes nouveaux utilisateurs. Mais pas moyen que le code que tu as fourni me les trouve....

  4. #4
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par mistertiger29 Voir le message
    Effectivement on s'approche de la réponse, cependant, j'ai créé 2 utilisateurs au groupe groupe1 et lorsque j'exécute ton code, il me les trouve pas.

    J'ai alors exécuté la commande :

    et effectivement je n'ai pas les nouveaux utilisateurs d'affiché....

    Pourtant quand je vais dans la gestion des utilisateurs, j'ai bien mes nouveaux utilisateurs qui appartiennent tout deux au groupe groupe1.

    Est ce que j'ai loupé un truc?
    Bonjour

    Les groupes reliés à un utilisateur se trouvent à 2 endroits
    1) dans le fichier /etc/passwd, sur la ligne correspondant à l'user, il y a son id de groupe en position 4.
    2) dans le fichier /etc/group, chaque groupe mentionne les users qui sont invités chez-lui. Mais il ne mentionne pas les users qui sont de son groupe (parce que l'info se trouve déjà dans /etc/passwd)

    Exemple: tu as le groupe user:x:200: et le groupe admin:x:100:.
    Tu crées un utilisateur "toto" de groupe "user". Tu auras alors, dans /etc/passwd, la ligne suivante: toto:x:123:200:...:/home/toto:/bin/bash.
    Toutefois, à ce niveau là, rien ne change dans /etc/group. La référence "200" permet de savoir que toto est de groupe "user".

    Maintenant tu décides que "toto", tout en restant user, sera aussi invité de "admin". A ce moment là, tu modifies dans /etc/group la ligne admin qui devient la suivante: admin:x:100:toto.

    Ainsi c'est en associant les deux fichiers qu'on peut savoir que toto est groupe "user" mais qu'il est aussi membre du groupe "admin".

    Au niveau des droits, c'est automatique. Si un fichier est du groupe "admin" alors toto y aura automatiquement accès selon les droits "g" (et non "o"). De même pour un fichier du groupe "user". A ce niveau là, on peut dire que toto est autant "user" que "admin".
    Là où il y a une différence, c'est quand toto crée un fichier. Le fichier créé (ne pouvant avoir qu'un seul groupe) prendra le groupe principal de toto, à savoir "user".

    Citation Envoyé par mistertiger29 Voir le message
    je me doute que cela doit renvoyer l'id du groupe passé en paramètre du script, et encore j'en suis pas certain....
    Ben en général on écrit un script pour qu'il réponde à ce qu'on veut ; on ne fait pas l'inverse (regarder si ce que l'on veut correspond au script)...

    Citation Envoyé par mistertiger29 Voir le message
    Je dois créer un script sous linux qui me permet de récupérer la liste des utilisateurs du groupe groupe1 et pour chaque utilisateur, exécuter une suite d'action.
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/bin/bash
     
    for group
    do
    	info=$(getent group $group)
    	gid=$(echo $info |cut -f3 -d:)
    	guest=$(echo $info |cut -f4 -d:)
     
    	for user in $(cut -f1,4 -d: /etc/passwd |grep ":$gid$" |cut -f1 -d:; echo $guest |sed -e "s/,/ /g")
    	do
    		echo "$user"
    	done
    done
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Par défaut
    Citation Envoyé par mistertiger29 Voir le message
    Effectivement on s'approche de la réponse, cependant, j'ai créé 2 utilisateurs au groupe groupe1 et lorsque j'exécute ton code, il me les trouve pas.
    As-tu créé un script contenant mon code ?
    Lui as-tu bien passé "groupe1" en paramètre ?
    N'a-t-il vraiment rien affiché ?
    Tu peux ajouter set -x au début du script pour voir ce qui se passe.

  6. #6
    Membre averti
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2011
    Messages : 17
    Par défaut
    Citation Envoyé par jlliagre Voir le message
    As-tu créé un script contenant mon code ?
    Lui as-tu bien passé "groupe1" en paramètre ?
    Oui j'ai créé un script contenant ton code et je l'ai exécuté en passant en paramètre le nom du groupe dont je veux récupérer ses utilisateurs.

    Citation Envoyé par jlliagre Voir le message
    N'a-t-il vraiment rien affiché ?
    Si il affiche bien 1 utilisateur qui appartient bien au groupe mais pas tous

    Citation Envoyé par jlliagre Voir le message
    Tu peux ajouter set -x au début du script pour voir ce qui se passe.
    Je vais essayer et je vous tiens au courant.

    Citation Envoyé par Sve@r Voir le message
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/bin/bash
     
    for group
    do
    	info=$(getent group $group)
    	gid=$(echo $info |cut -f3 -d:)
    	guest=$(echo $info |cut -f4 -d:)
     
    	for user in $(cut -f1,4 -d: /etc/passwd |grep ":$gid$" |cut -f1 -d:; echo $guest |sed -e "s/,/ /g")
    	do
    		echo "$user"
    	done
    done
    J'ai créé un script en modifiant un poil ton code et en effet cela à l'ai de faire ce que je souhaite. J'ai juste enlevé la première boucle for et remplacé le $group par $1 car le groupe dont je souhaite récupérer les utilisateurs sera passé en paramètre.
    De plus j'ai un utilisateur qui est invité du groupe groupe1 et aussi y fait partie :

    dans /etc/passwd j'ai : operatorEwss:503:506::/home/operatorEwss:/bin/bash
    et dans /etc/group j'ai : operatorEwss:506:operatorEwss

    Du coup le scipt me renvoie 2 fois l'utilisateur operatorEwss.
    Or les utilisateurs que je vais rajouter, appartiendront au groupe operatorEwss (groupe et utilisateur), c'est à dire que cela sera leur groupe primaire dans tous les cas.
    Je me disais donc que le code ci dessous devrait suffir.... Dites moi je me trompe.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    info=$(getent group $1)
    gid=$(echo $info |cut -f3 -d:)
     
    for user in $(cut -f1,4 -d: /etc/passwd |grep ":$gid$" |cut -f1 -d:)
    do
    	echo "$user"
    done
    Merci de votre aide à tous les deux

  7. #7
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Par défaut
    Citation Envoyé par mistertiger29 Voir le message
    Je n'arrive d'ailleurs pas trop à comprendre ce qui se passe dans la partie de code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    gid=$(getent group $1 | awk -F : '{print $3}')
    (
      getent group $1 | awk -F : '{gsub(","," ",$4);print $4}'
      getent passwd | awk -F : -v gid=$gid '$3==gid {print $1}'
    ) | sort -u )
    je me doute que cela doit renvoyer l'id du groupe passé en paramètre du script, et encore j'en suis pas certain....
    Non, ça renvoie les noms des utilisateurs membres du groupe dont le nom est passé en paramètre.

    Revoici mon code légèrement amélioré et surtout avec des commentaires:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    for user in $(
    # récupération dans gid de l'identifiant de groupe (3eme champs dans la base group) correspondant au nom de groupe passé en paramètre
    gid=$(getent group $1 | awk -F : '{print $3}'| head -1)
    (
      # affichage de la liste des membres du groupe (4eme champs), suppression du séparateur virgule 
      getent group $1 | awk -F : '{gsub(","," ",$4);print $4}'
      # affichage des noms des utilisateurs dont le groupe primaire est celui recherché
      getent passwd | awk -F : -v gid=$gid '$3==gid {print $1}'
    ) | sort -u ) # classement par ordre alphabétique des noms précédement trouvés et suppression des éventuels doublons
    do # boucle sur chaque nom d'utilisateur membre du groupe
      echo user=$user
    done
    Et sa sortie avec le même contenu que toi dans les fichiers group et passwd pour le nom recherché:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $ grep operatorEwss /etc/passwd /etc/group
    /etc/passwd:operatorEwss:x:503:506::/home/operatorEwss:/bin/bash
    /etc/group:operatorEwss:x:506:operatorEwss,jlliagre
    $ ./go operatorEwss
    user=operatorEwss
    user=jlliagre
    $

  8. #8
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Par défaut
    Citation Envoyé par mistertiger29 Voir le message
    J'ai juste enlevé la première boucle for et remplacé le $group par $1 car le groupe dont je souhaite récupérer les utilisateurs sera passé en paramètre.
    C'est un changement inutile car c'est ce que faisait déjà le for du script de Sve@r.

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par mistertiger29 Voir le message
    J'ai créé un script en modifiant un poil ton code et en effet cela à l'ai de faire ce que je souhaite. J'ai juste enlevé la première boucle for et remplacé le $group par $1 car le groupe dont je souhaite récupérer les utilisateurs sera passé en paramètre.
    C'est ce que faisait ma boucle. Sauf que elle, elle traitait n groupes l'un après l'autre alors que toi tu n'en traites qu'un seul !!!
    Faudrait quand-même que tu apprennes les bases des structures shell...

    Citation Envoyé par mistertiger29 Voir le message
    dans /etc/passwd j'ai : operatorEwss:x:503:506::/home/operatorEwss:/bin/bash.
    et dans /etc/group j'ai : operatorEwss:x:506:operatorEwss.
    Du coup le scipt me renvoie 2 fois l'utilisateur operatorEwss.
    Oui c'est vrai que je n'avais pas envisagé cette config. Pas grave, suffit de filtrer le résultat
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/bin/bash
     
    for group
    do
    	info=$(getent group $group)
    	gid=$(echo $info |cut -f3 -d:)
    	guest=$(echo $info |cut -f4 -d:)
     
    	for user in $(cut -f1,4 -d: /etc/passwd |grep ":$gid$" |cut -f1 -d:; echo $guest |sed -e "s/,/ /g")
    	do
    		echo "$user"
    	done |uniq # (ou done |sort -u si on les veut en plus triés)
    done
    Hé oui, le shell n'est fait que de briques. Tu veux une action en plus ? Tu rajoutes au bon endroit la bonne brique...

    Citation Envoyé par mistertiger29 Voir le message
    Je me disais donc que le code ci dessous devrait suffir.... Dites moi je me trompe.
    J'en sais rien. Quand tu fais un script, ben j'espère que tu le testes aussi... et dans différentes configurations...
    Le tien utilise le awk à outrance. Or si le awk est un très bon outil, c'est aussi un outil très lourd. Certains aiment bien essayer d'arriver au résultat en n'utilisant que les outils pile-poils adaptés à l'action (éviter d'écraser une souris à la catapulte par exemple)...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Le tien utilise le awk à outrance.
    Ce n'est pas le sien mais le mien, normal donc que mistertiger29 se pose des questions dessus.
    Or si le awk est un très bon outil, c'est aussi un outil très lourd. Certains aiment bien essayer d'arriver au résultat en n'utilisant que les outils pile-poils adaptés à l'action (éviter d'écraser une souris à la catapulte par exemple)...
    Ca se discute. J'utilise awk là où un cut suffirait, pas de problème mais on ne peut pas affirmer que les lignes suivantes soient un modèle d'efficacité et d'utilisation d'outils "pile-poil adaptés":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    guest=$(echo $info |cut -f4 -d:)
    ...
    cut -f1,4 -d: /etc/passwd |grep ":$gid$" |cut -f1 -d:; echo $guest |sed -e "s/,/ /g"
    Je préfère un seule commande awk plutôt que des constructions du type cut | grep | cut et cut | sed. De plus, tu assumes que les entrées utilisateurs sont toutes dans /etc/passwd, ce qui n'est pas garanti.

  11. #11
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par jlliagre Voir le message
    Je préfère un seule commande awk plutôt que des constructions du type cut | grep | cut et cut | sed.
    Effectivement ça se discute. Je commence par éliminer de /etc/passwd les infos inutiles ce qui donne des lignes plus courtes à faire avaler au grep pour lequel je peux préciser "fin de ligne" ce qui accèlère encore son traitement. Perso je préfère accumuler de "petits outils" (parce que cut et grep c'est quand-même pas énorme) plutôt qu'un gros dans lequel je vais devoir me casser le n... à regarder si le mot $4 est identique au gid (refaire le grep quoi)...

    Alors c'est sûr, à un certain moment l'accumulation de petits outils fera basculer les performances comparées à celles obtenues avec un gros plus complet mais chacun ses préférences et ça c'est humain. Donc toi tu préfères le awk, et moi le pipe. L'important est de ne pas refuser systématiquement certaines méthodes (il m'arrive quand-même aussi de faire du awk...)

    Citation Envoyé par jlliagre Voir le message
    De plus, tu assumes que les entrées utilisateurs sont toutes dans /etc/passwd, ce qui n'est pas garanti.
    Là je ne pige pas. Je ne vois pas trop où une entrée pourrait être ailleurs.
    Pour moi elles sont forcément dans /etc/passwd et éventuellement en plus dans /etc/group. Si une entrée ne se trouve ni dans l'un, ni dans l'autre alors cette entrée n'est pas un utilisateur (sauf si tu veux partir dans les outils de centralisation et d'annuaires qui remplacent mais cela sort du cadre du TP).
    Or mon for récupère bien les entrées situées dans les 2 fichiers...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  12. #12
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Effectivement ça se discute. Je commence par éliminer de /etc/passwd les infos inutiles ce qui donne des lignes plus courtes à faire avaler au grep pour lequel je peux préciser "fin de ligne" ce qui accèlère encore son traitement. Perso je préfère accumuler de "petits outils" (parce que cut et grep c'est quand-même pas énorme) plutôt qu'un gros dans lequel je vais devoir me casser le n... à regarder si le mot $4 est identique au gid (refaire le grep quoi)...
    Pas "refaire" le grep, awk fait déjà très bien grep.
    Alors c'est sûr, à un certain moment l'accumulation de petits outils fera basculer les performances comparées à celles obtenues avec un gros plus complet mais chacun ses préférences et ça c'est humain. Donc toi tu préfères le awk, et moi le pipe. L'important est de ne pas refuser systématiquement certaines méthodes (il m'arrive quand-même aussi de faire du awk...)
    Je dirais que les performances sont importantes mais ne doivent pas être privilégiées par rapport à l'exactitude. La concision est aussi souvent un gage de qualité.
    Là je ne pige pas. Je ne vois pas trop où une entrée pourrait être ailleurs.
    Pour moi elles sont forcément dans /etc/passwd et éventuellement en plus dans /etc/group. Si une entrée ne se trouve ni dans l'un, ni dans l'autre alors cette entrée n'est pas un utilisateur (sauf si tu veux partir dans les outils de centralisation et d'annuaires qui remplacent mais cela sort du cadre du TP).
    Or mon for récupère bien les entrées situées dans les 2 fichiers...
    1: Rien n'indique qu'il s'agit d'un TP et pas d'un cas réel.
    2: Même s'il s'agit d'un TP, autant faire un script qui gère tous les cas de figure dès le début. Les entrées passwd et group peuvent être dans les NIS, un annuaire LDAP, Active Directory, etc ...
    3: Ton script n'utilise pas le fichier /etc/group mais la commande getent qui, quand elle est disponible, est la bonne méthode pour récupérer les entrées de la base groupe. Il n'est pas cohérent pour la base passwd que tu accède directement au lieu d'utiliser getent passwd.

  13. #13
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par jlliagre Voir le message
    Pas "refaire" le grep, awk fait déjà très bien grep.
    Si tu commences à jouer sur les mots, je vais te sortir les définitions
    refaire (verbe transitif): Recommencer une action, une tâche déjà faite par soi-même ou par un autre (http://www.linternaute.com/dictionna...ition/refaire/)
    Donc (again) je ne vois pas pourquoi je vais utiliser awk et programmer un algo (aussi minime soit-il) pour refaire une tâche qui est déjà faite (en natif) par la commande "grep"

    Citation Envoyé par jlliagre Voir le message
    Il n'est pas cohérent pour la base passwd que tu accède directement au lieu d'utiliser getent passwd.
    Oui, c'est vrai.
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/bin/bash
     
    for group
    do
    	info=$(getent group $group)
    	gid=$(echo $info |cut -f3 -d:)
    	guest=$(echo $info |cut -f4 -d:)
     
    	for user in $(getent passwd |cut -f1,4 -d: |grep ":$gid$" |cut -f1 -d:; echo $guest |sed -e "s/,/ /g")
    	do
    		echo "$user"
    	done | uniq
    done
    C'est vrai aussi que cela change radicalement le script...

    Citation Envoyé par jlliagre Voir le message
    Revoici mon code légèrement amélioré et surtout avec des commentaires:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    for user in $(
    # récupération dans gid de l'identifiant de groupe (3eme champs dans la base group) correspondant au nom de groupe passé en paramètre
    gid=$(getent group $1 | awk -F : '{print $3}'| head -1)
    (
      # affichage de la liste des membres du groupe (4eme champs), suppression du séparateur virgule 
      getent group $1 | awk -F : '{gsub(","," ",$4);print $4}'
      # affichage des noms des utilisateurs dont le groupe primaire est celui recherché
      getent passwd | awk -F : -v gid=$gid '$3==gid {print $1}'
    ) | sort -u ) # classement par ordre alphabétique des noms précédement trouvés et suppression des éventuels doublons
    do # boucle sur chaque nom d'utilisateur membre du groupe
      echo user=$user
    done
    Accessoirement, ce script ne fonctionne pas si l'utilisateur ne se trouve pas inscrit sur la ligne correspondant à son groupe principal; c'est à dire dans le cas suivant
    /etc/group
    /etc/passwd
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    moi:x:2001:2000:...:/home/moi:/bin/bash.
    configuration qui arrive généralement dans la plupart du temps (et qui est celle de ma machine). Or, ben le mien il fonctionne (peut-être à peine moins vite mais aussi à peine plus complet)
    moi@virtualux:~/Projets$ time ./a.sh utilisateur
    moi

    real 0m0.010s
    user 0m0.008s
    sys 0m0.000s
    moi@virtualux:~/Projets$ time ./b.sh utilisateur

    real 0m0.008s
    user 0m0.004s
    sys 0m0.000s
    Le script "a.sh" étant le mien et le "b.sh" étant le tien...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  14. #14
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Par défaut
    Merci d'avoir détecté ce bug ! Je me suis fait avoir par mon compte de test qui avait un uid égal à son gid.

    Voici une version corrigée, allégée et qui reprend ta boucle externe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    for group
    do
        g=$(getent group $group)
        gid=$(echo "$g" | awk -F : '{print $3;exit}')
        (
            echo "$g" | awk -F : '{gsub(",","\n",$4);print $4}'
            getent passwd | awk -F : '$4=='$gid' {print $1}'
        ) | sort -u
    done
    Puisqu'on en est au code review, la commande uniq que tu as utilisée n'est pas suffisante pour supprimer les doublons car les identifiants ne sont pas nécessairement ordonnés, sort -u est approprié ici.

    Un profilage des deux versions ne montre pas de différence significative en durée d'exécution (entre 0 et 8ms elapsed suivant les exécutions, user et sys non mesurable par la commande time), une réduction de 50 à 75 % du nombre de changements de contexte (~25 vs 56 à 109) avec la version "awk" , une réduction de 25% en nombre d'appels système avec la version "awk" (764 vs 1024), et en revanche 28% de mémoire utilisée (max rss) en plus (1.28 Mo vs 1 Mo). Rien qui ne permette de conclure qu'awk soit un outil "très lourd" comparé à des outils plus simples et spécialisés.

    J'ai utilisé dash pour tester les scripts. La surcharge en terme de nombre d'appels système est de l'ordre de 40% avec ksh93 et de 50% avec bash, ce qui montre que le shell utilisé peut avoir un impact important sur les performances.

    L'empreinte mémoire s'établit autour de 1.8 Mo avec ksh93 et 1.4 Mo avec bash, cette fois sans différence entre la version "awk" et la version "cut/grep/sed".

    Pas de quoi fouetter un chat donc ... et je suis sûr que mistertiger29 sera satisfait des performances de l'un ou l'autre de ces scripts

    PS: pour m'amuser un peu, je viens d'écrire cette version où toute la logique est implémentée en GNU awk :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #!/bin/bash
    for group
    do
      awk -F: '
      FNR==NR&&$1==g{gid=$3;c=split($4,u,",");for(i in u)v[u[i]]=1;nextfile;next}
      gid&&$4==gid{v[$1]=1}
      END{m=asorti(v,w);for(i=1;i<m;i++)print w[i]}
      ' g=$group <(getent group) <(getent passwd)
    done
    L'explication de son fonctionnement est, comme on dit en anglais, left as an exercise for the reader

  15. #15
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 658
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 658
    Par défaut
    dans la deuxième version (±full awk) getent me semble avoir perdu son utilité, et je me pose la question de celle de la boucle for.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  16. #16
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par jlliagre Voir le message
    Merci d'avoir détecté ce bug ! Je me suis fait avoir par mon compte de test qui avait un uid égal à son gid.
    C'était pour éviter ce genre de pb que je commence par un cut qui ne me conserve que le login et le gid.
    Mais j'ai triché car étant (à temps partiel) enseignant de shell, ce TP est chez-moi un classique (je le nomme "bdd shell" parce qu'il permet de faire un ersatz de "select where"). Parfois je les fais partir du login pour qu'ils me trouvent le groupe correspondant (je leur fais grace du champ 4 de /etc/group), parfois je pars du groupe et je les fais chercher les login correspodant (et là je leurs demande de prendre en compte aussi ce champ 4). Et ce bug bien évidemment ils tombent quasiment tous dedans...

    Citation Envoyé par jlliagre Voir le message
    Voici une version corrigée, allégée et qui reprend ta boucle externe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    for group
    do
        g=$(getent group $group)
        gid=$(echo "$g" | awk -F : '{print $3;exit}')
        (
            echo "$g" | awk -F : '{gsub(",","\n",$4);print $4}'
            getent passwd | awk -F : '$4=='$gid' {print $1}'
        ) | sort -u
    done
    Puisqu'on en est au code review, la commande uniq que tu as utilisée n'est pas suffisante pour supprimer les doublons car les identifiants ne sont pas nécessairement ordonnés, sort -u est approprié ici.
    Moui bien vu. Je voulais (là encore) n'utiliser que la commande la plus appropriée. Mais je ne la connaissais pas assez et ne savais pas qu'elle ne fonctionne que sur un ensemble trié. Bien joué

    Citation Envoyé par jlliagre Voir le message
    Un profilage des deux versions ne montre pas de différence significative en durée d'exécution (entre 0 et 8ms elapsed suivant les exécutions, user et sys non mesurable par la commande time), une réduction de 50 à 75 % du nombre de changements de contexte (~25 vs 56 à 109) avec la version "awk" , une réduction de 25% en nombre d'appels système avec la version "awk" (764 vs 1024), et en revanche 28% de mémoire utilisée (max rss) en plus (1.28 Mo vs 1 Mo). Rien qui ne permette de conclure qu'awk soit un outil "très lourd" comparé à des outils plus simples et spécialisés.

    J'ai utilisé dash pour tester les scripts. La surcharge en terme de nombre d'appels système est de l'ordre de 40% avec ksh93 et de 50% avec bash, ce qui montre que le shell utilisé peut avoir un impact important sur les performances.

    L'empreinte mémoire s'établit autour de 1.8 Mo avec ksh93 et 1.4 Mo avec bash, cette fois sans différence entre la version "awk" et la version "cut/grep/sed".

    Pas de quoi fouetter un chat donc ... et je suis sûr que mistertiger29 sera satisfait des performances de l'un ou l'autre de ces scripts
    Oui, comme tout le monde quand ils verront sur quoi on se masturbe

    Citation Envoyé par jlliagre Voir le message
    PS: pour m'amuser un peu, je viens d'écrire cette version où toute la logique est implémentée en GNU awk :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #!/bin/bash
    for group
    do
      awk -F: '
      FNR==NR&&$1==g{gid=$3;c=split($4,u,",");for(i in u)v[u[i]]=1;nextfile;next}
      gid&&$4==gid{v[$1]=1}
      END{m=asorti(v,w);for(i=1;i<m;i++)print w[i]}
      ' g=$group <(getent group) <(getent passwd)
    done
    Cette syntaxe (en rouge) je connaissais pas. Double les entrées ? Manque pas un $(getent ...) ?

    Mais chez-moi il me dit que la fonction assorti() n'est pas définie (nawk ? gawk ?)

    Citation Envoyé par N_BaH Voir le message
    et je me pose la question de celle de la boucle for.
    ? Ben permet de traiter n groupes l'un après l'autre...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  17. #17
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Cette syntaxe (en rouge) je connaissais pas. Double les entrées ? Manque pas un $(getent ...) ?
    C'est une extension non standard (process substitution) créée par ksh93 et que bash a repris aussi.

    Elle permet de passer comme paramètre un fichier qui contient le résultat de la commande entre parenthèses.

    Avec les shells ou OS qui ne la supportent pas, on peut s'en sortir avec des fifos.

    Mais chez-moi il me dit que la fonction assorti() n'est pas définie (nawk ? gawk ?)
    Comme indiqué, j'ai utilisé GNU awk. C'est une extension de gawk, attention, "asorti" avec un seul "s".

  18. #18
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    dans la deuxième version (±full awk) getent me semble avoir perdu son utilité
    Je pourrais être full awk en récupérant les bases group et passwd dans le script lui-même via deux pipes et des getline, mais il me faudrait quand même utiliser getent.

  19. #19
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 658
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 658
    Par défaut
    [...] il me faudrait quand même utiliser getent.
    <jpp> bah, pourquoi ? </jpp>

    getent, utilisé avec le seul nom de la base, retourne le fichier qui sert pour créer la base.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if diff -q <(getent passwd) /etc/passwd; then echo "pareil"; else echo "pas pareil"; fi
    pareil
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  20. #20
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Par défaut
    ou pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if diff -q <(getent passwd) /etc/passwd; then echo "pareil"; else echo "pas pareil"; fi
    pas pareil
    $ grep "^passwd" /etc/nsswitch.conf
    passwd: files ldap
    $
    http://man.developpez.com/man1/getent:
    La commande getent affiche les entrées des bases de données prises en charge par les bibliothèques du Name Service Switch (NSS), qui sont configurées dans /etc/nsswitch.conf.

    http://man.developpez.com/man5/nsswitch.conf:
    À l'origine, il n'y avait qu'une seule source pour les renseignements de service, souvent sous forme d'un simple fichier de configuration (par exemple /etc/passwd). Cependant, puisque d'autres services de noms, comme NIS (« Network Information Service ») et le DNS (« Domain Name Service »), sont devenus populaires, une méthode plus flexible était nécessaire par rapport aux ordonnancements des recherches codés dans la bibliothèque C. Le mécanisme NSS (« Name Service Switch »), qui était basé sur le mécanisme utilisé par Sun Microsystems dans la bibliothèque C de Solaris 2, a introduit une solution plus propre au problème.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Lister les utilisateurs d'un groupe AD
    Par Represente37 dans le forum VBScript
    Réponses: 0
    Dernier message: 17/02/2012, 14h17
  2. [Débutant] Lister les utilisateur d'un groupe ACTIVE DIRECTORY
    Par FromHell04 dans le forum VB.NET
    Réponses: 0
    Dernier message: 01/02/2012, 18h23
  3. LDAP Active directory récupérer les utilisateurs d'un groupe
    Par *alexandre* dans le forum API standards et tierces
    Réponses: 4
    Dernier message: 19/01/2012, 09h58
  4. recherche code pour limiter une lister et utiliser les bouton suivant precedent
    Par carmen256 dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 29/09/2006, 17h43

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