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 :

[JQ] Afficher les keys d'une array dont les valeurs contiennent des valeurs spécifiques


Sujet :

Shell et commandes GNU

  1. #1
    Membre à l'essai
    Homme Profil pro
    Consultant fonctionnel
    Inscrit en
    Juillet 2006
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Consultant fonctionnel
    Secteur : Service public

    Informations forums :
    Inscription : Juillet 2006
    Messages : 32
    Points : 20
    Points
    20
    Par défaut [JQ] Afficher les keys d'une array dont les valeurs contiennent des valeurs spécifiques
    Bonjour à toutes et à tous,

    Je maintiens un script de vérification de fonctionnalités étalé sur plusieurs serveurs remplissant des fonctions diverses. Une famille de serveurs (une douzaine) exposent via une api un retour JSON sur l'état de leurs composants (topics Kafka et consommateurs)

    Chaque serveur exécute une série de topics (TOPIC_x), et pour chacun d'entre eux des consommateurs sont assignés (worker-TOPIX_x-n) auquel s'ajoute leur état ([RUNNING], [TERMINATED] ou [FAILED])

    La structure du retour json est la suivante :

    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
    {
      "status": "UP",
      "components": {
        "workersHealth": {
          "status": "UP",
          "details": {
            "TOPIC_A": [
              "worker-TOPIC_A-0 [RUNNING]"
            ],
            "TOPIC_B": [
              "worker-TOPIC_B-0 [RUNNING]",
              "worker-TOPIC_B-1 [RUNNING]",
              "worker-TOPIC_B-2 [RUNNING]",
              "worker-TOPIC_B-3 [RUNNING]",
              "worker-TOPIC_B-4 [RUNNING]",
              "worker-TOPIC_B-5 [RUNNING]"
            ],
            "TOPIC_C": [
              "worker-TOPIC_C-0 [RUNNING]"
            ],
            "TOPIC_D": [
              "worker-TOPIC_D-0 [RUNNING]"
            ],
            "TOPIC_E": [
              "worker-TOPIC_E-0 [RUNNING]",
              "worker-TOPIC_E-1 [RUNNING]",
              "worker-TOPIC_E-2 [RUNNING]"
            ],
            "TOPIC_F": [
              "worker-TOPIC_F-0 [RUNNING]"
            ],
            "TOPIC_G": [
              "worker-TOPIC_G-0 [RUNNING]"
            ],
            "TOPIC_H": [
              "worker-TOPIC_H-0 [TERMINATED]"
            ],
            "TOPIC_I": [
              "worker-TOPIC_I-0 [RUNNING]",
              "worker-TOPIC_I-1 [FAILED]",
              "worker-TOPIC_I-2 [RUNNING]",
              "worker-TOPIC_I-3 [RUNNING]",
              "worker-TOPIC_I-4 [RUNNING]",
              "worker-TOPIC_I-5 [RUNNING]"
            ],
            "TOPIC_J": [
              "worker-TOPIC_J-0 [RUNNING]"
            ],
            "TOPIC_K": [
              "worker-TOPIC_K-0 [RUNNING]",
              "worker-TOPIC_K-1 [RUNNING]",
              "worker-TOPIC_K-2 [RUNNING]"
            ],
            "TOPIC_L": [
              "worker-TOPIC_L-0 [RUNNING]"
            ],
            "TOPIC_M": [
              "worker-TOPIC_M-0[RUNNING]",
              "worker-TOPIC_M-1[RUNNING]",
              "worker-TOPIC_M-2[RUNNING]"
            ]
          }
        }
      }
    }
    Actuellement, je suis capable de boucler pour ma douzaine de serveurs et faire pour chacun d'entre eux un curl suivi d'un jq puis un egrep pour ne récupérer que la partie qui m'intéresse (c'est à dire pointer tous les workers qui ont une valeur FAILED ou TERMINATED afin que la personne qui fasse le contrôle effectue les actions nécessaires à leur correction).

    Cela prend la forme suivante, plutôt crados (histoire d'avoir une v0 qui fonctionne rapidement) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TESTWORKER = $(curl -sm 3000 "https://${SERVEUR}/${URL_HEALTH}" | jq -r .components.workersHealth.details | egrep 'FAILED|TERMINATED')
    Le retour ressemble actuellement à ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        "worker-TOPIC_A-0 [FAILED]"
    Sauf que maintenant j'aimerais faire un truc un peu plus propre, surtout quand je vois la puissance de jq :

    • Pour des raisons de lisibilité, je ne veux pas remonter la valeur complète de l'array (donc le consumer), mais plutôt le nom du topic contenant des consommateurs satisfaisant aux critères FAILED ou TERMINATED. Donc je sais déjà que je veux terminer ma commande par un | keys[]
    • Mon idée c'est d'utiliser select avec un contains, mais pour l'instant tout ce que récupère, c'est un "jq: error: array and string cannot have their containment checked"


    Actuellement ma commande juste pour afficher les noms des arrays dont une valeur contient "FAILED" ou "TERMINATED" est la suivante (je ne cherche pas à compter) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    jq -r 'select(.components.workersHealth.details[] | contains ("TERMINATED") or contains ("FAILED"))| keys[]'
    Je m'attends à avoir un retour (avec l'exemple ci-dessus) :


    Ma difficulté par rapport aux exemples que je trouve à droite à gauche sur les internets, c'est que la plupart des recherches dans des arrays portent sur des objets (donc "array1":["property": "value"]) ou bien spécifient une valeur exacte.

    Je vous remercie par avance pour votre aide et conseils
    Cordialement

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 392
    Points
    19 392
    Par défaut
    Bonjour,

    est-il possible que pour un même "TOPIC" plusieurs signaux devant être signalés soient présents ?
    par exemple, pour le TOPIC_I, peut-il y avoir plus d'une "instance" : une ou plusieurs FAIL, et une ou plusieurs TERMINATED ?
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Consultant fonctionnel
    Inscrit en
    Juillet 2006
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Consultant fonctionnel
    Secteur : Service public

    Informations forums :
    Inscription : Juillet 2006
    Messages : 32
    Points : 20
    Points
    20
    Par défaut
    Bonjour,

    un TOPIC dispose de 1 à n consommateurs ("worker-TOPIC_x-0') dont chacun peut prendre une des trois valeurs ("Running", "Terminated" ou "Failed").

    L'état normal est qu'un TOPIC dispose de tous ses consommateurs à l'état "Running". Tout autre état ("Failed" ou "Terminated") doit remonter dans le retour du script pour pouvoir former une ligne "sur [SERVEUR], le TOPIC_x a des consommateurs à relancer"

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 392
    Points
    19 392
    Par défaut

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ jq -r '.components.workersHealth.details | [to_entries [] | "\(.key+" : "+.value[] | select(contains("FAILED") or contains("TERMINATED")))"| sub(" .*";"")] | unique[]' /tmp/workers.json                     
    TOPIC_H                                                                                                                                                                                                                                        
    TOPIC_I
    EDIT : un petit poil plus court
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $ jq -r --arg re '\[FAILED|TERMINATED\]$' '.components.workersHealth.details | [to_entries [] | "\(.key+" "+.value[] | select(test($re)))"| sub(" .*";"")] | unique[]' /tmp/workers.json
    EDIT 2 : on peut indiquer le libellé que tu veux en remplaçant le sub() par celui-ci : sub("(?<head>[^ ]*) .*";"le \(.head) a des consommateurs à relancer"), qui affichera la sortie suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    le TOPIC_H a des consommateurs à relancer
    le TOPIC_I a des consommateurs à relancer
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  5. #5
    Membre à l'essai
    Homme Profil pro
    Consultant fonctionnel
    Inscrit en
    Juillet 2006
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Consultant fonctionnel
    Secteur : Service public

    Informations forums :
    Inscription : Juillet 2006
    Messages : 32
    Points : 20
    Points
    20
    Par défaut
    chapeau, j'étais très loin de la solution !
    Je testerai ça lundi, merci beaucoup et meilleurs vœux

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 392
    Points
    19 392
    Par défaut
    plus simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $ jq -r --arg re '\[FAILED|TERMINATED\]$' '[ .components.workersHealth.details | to_entries[] | select( .value[]|test($re) ) | "le " + .key + " a des consommateurs à relancer." ] | unique[]' /tmp/workers.json
    ?
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  7. #7
    Membre à l'essai
    Homme Profil pro
    Consultant fonctionnel
    Inscrit en
    Juillet 2006
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Consultant fonctionnel
    Secteur : Service public

    Informations forums :
    Inscription : Juillet 2006
    Messages : 32
    Points : 20
    Points
    20
    Par défaut
    Bonjour et meilleurs voeux.

    Je viens de tester les différentes propositions malheureusement aucune ne répond sur mon environnement, j'ai bien peur en raison de l'ancienneté de la version de jq sur mes serveurs (1.3 sur des Rhel 6.10, je n'aurais pas pensé qu'il y aurait eu autant de versions de jq sorties depuis). J'ai bien des serveurs en Rhel 7.4 ou 7.6 mais jq ne doit pas être installé dessus (je vais voir si sur un environnement plus à ma main je peux l'installer, mais actuellement ma prod reste majoritairement en Rhel 6.10)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    error: test is not defined
    [ .components.workersHealth.details | to_entries[] | select( .value[]|test($re) ) | "le " + .key + " a des consommateurs à relancer." ] | unique[]
                                                                          ^^^^
    jq -r '.components.workersHealth.details | [to_entries [] | "\(.key+" : "+.value[] | select(contains("FAILED") or contains("TERMINATED")))"| sub(" .*";"")] | unique[]'              <
    error: sub is not defined
    .components.workersHealth.details | [to_entries [] | "\(.key+" : "+.value[] | select(contains("FAILED") or contains("TERMINATED")))"| sub(" .*";"")] | unique[]
                                                                                                                                          ^^^
    Le mieux que j'arrive à afficher est la première proposition (avec le unique[]

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ | jq -r '.components.workersHealth.details | [to_entries [] | "\(.key+" : "+.value[] | select(contains("FAILED") or contains("TERMINATED")))"] | unique[]'                        <
    TOPIC_J : worker-TOPIC_J-0 [FAILED]
    Ce qui est déjà un progrès par rapport à mon egrep dégeu

    Je vais regarder ce que je peux faire avec cette base

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 392
    Points
    19 392
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    jq -r '.components.workersHealth.details | to_entries[] | [ select(.value[] | contains("FAILED") or contains("TERMINATED")) | .key ] | unique[]'
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    jq -r '.components.workersHealth.details | to_entries[] | [ select(.value[] |match("FAILED|TERMINATED")) | .key ] | unique[]'
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

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

Discussions similaires

  1. [Système] Afficher les valeurs d'arguments d'une fonction
    Par EXPERMEGAS dans le forum Langage
    Réponses: 2
    Dernier message: 07/09/2007, 11h56
  2. afficher les valeur d'une requete dans une combobox
    Par carlos587261 dans le forum Bases de données
    Réponses: 3
    Dernier message: 15/06/2007, 08h45
  3. Afficher les valeurs d'une structure dans une matrice
    Par yabbiyou dans le forum MATLAB
    Réponses: 1
    Dernier message: 22/02/2007, 12h26
  4. Réponses: 1
    Dernier message: 13/02/2007, 16h03
  5. comment afficher les valeurs d'une semaine
    Par duck54 dans le forum Langage SQL
    Réponses: 1
    Dernier message: 28/05/2006, 22h57

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