Problème sur une boucle

Salut,

J’ai un petit souci sur une boucle dans un script bash … :confused:

#!/bin/bash

cores="$(lscpu | grep -E 'Cœur|Coeur' | tr -s ' ' | tr -d ':' | sed 's/.* //')"
cores=$((cores-1))
cpus="$(lscpu | grep -E 'Socket|Support\(' | tr -s ' ' | sed 's/.* //')"
cpus=$((cpus-1))
sens="$(sensors | grep 'Core' | cut -d "(" -f 1 | cut -d "+" -f 2 | cut -c 1-4)"

echo "$sens"

echo "{"
echo "\"data\":["

comma=""
for cpu in $(seq 0 "$cpus")
do
        for core in $(seq 0 "$cores")
        do
                for temp in $sens
                do
                        echo "    $comma{\"{#CPUID}\":\"$cpu\":\"{#COREID}\":\"$core\":\"{#TEMPID}\":\"$temp\"}"
                    comma=","
                done
        done
done

echo "]"
echo "}"

Techniquement la sortie devrait être du genre :

 
{
"data":[
    {"{#CPUID}":"0":"{#COREID}":"0":"{#TEMPID}":""}
    ,{"{#CPUID}":"0":"{#COREID}":"1":"{#TEMPID}":""}
    ,{"{#CPUID}":"0":"{#COREID}":"2":"{#TEMPID}":""}
    ,{"{#CPUID}":"0":"{#COREID}":"3":"{#TEMPID}":""}
    ,{"{#CPUID}":"0":"{#COREID}":"4":"{#TEMPID}":""}
    ,{"{#CPUID}":"0":"{#COREID}":"5":"{#TEMPID}":""}
    ,{"{#CPUID}":"1":"{#COREID}":"0":"{#TEMPID}":""}
    ,{"{#CPUID}":"1":"{#COREID}":"1":"{#TEMPID}":""}
    ,{"{#CPUID}":"1":"{#COREID}":"2":"{#TEMPID}":""}
    ,{"{#CPUID}":"1":"{#COREID}":"3":"{#TEMPID}":""}
    ,{"{#CPUID}":"1":"{#COREID}":"4":"{#TEMPID}":""}
    ,{"{#CPUID}":"1":"{#COREID}":"5":"{#TEMPID}":""}
]
}

La boucle sur laquelle je butte actuellement me permet de récupérer les températures par cores de chaque de chaque CPU (dans le cas de multi cpu.

Ayant trouvé le moyen d’exploiter la température des cores et non simplement des CPU sur l’ensemble du matériel hétérogène je me suis donc résigné à gérer les sondes de cette manière (c’est overkill mais ça marchera au moins :stuck_out_tongue: ).

LA première boucle me permet de récupérer le nombre de socket physique, la seconde me permet de lui attribuer selon le nombre de core un numéro pour l’identifier.

la troisième boucle devrait pouvoir normalement lire un résultat et lui attribué une valeur à chaque ligne pour chaque core.
Mais c’est la que le bas blesse, j’ai des erreurs sur chaques méthodes d’exploitations testé jusqu’alors :persevere:

Je récupère une liste de la sorte avec ma variable $sens :

69.0
69.0
68.0
69.0
67.0
65.0
55.0
51.0
52.0
48.0
51.0
52.0

Et donc je pensé faire une extraction lié au numéro de core +1 (car cela commence par zéro) afin de pouvoir dynamiquement utilisé ce type de script quelques soit le nombre de socket physique ou de cores par CPU.

Bien entendu je ne suis pas arrêté au BASH si vous avez une solution de remplacement à proposé en Perl ou en Python, mais je pense que le BASH sera plus simple à gérer.

Tu chercherais pas à faire du json, sans en avoir l’air ! :stuck_out_tongue:

Bon, j’allume ma Sid, histoire de voir :wink:

1 J'aime

Si si ,j’avoue :stuck_out_tongue:

Attend je sort ma boule de cristale :crystal_ball:

J’ai testé ton script et … malheureusement il est inutilisable chez moi. Je dois avoir un CPU un peu trop ancien et il ne donne pas la température de chaque CPU.

Tu peux toujours mettre cette ligne en début de script pour faire du debug, tu verra ce qu’il se passe

set -x

Mais dans la logique ça semble correcte.

Salut,

moi non plus je n’ai pas sensors d’installé, mais j’ai écrit en dur dans le script des valeurs comme indiqué par Clochette.
Mais le problème est plutôt conceptuel d’après moi:
dans $sens tu as toutes les valeurs relevées par sensors, donc pour tous les coeurs. Or, dans ta 2e boucle for, tu es normalement au niveau de chaque coeur d’un CPU donné, donc tu ne devrais pas reboucler un for sur toutes les valeurs de $sens.
Parce que là ça donne ça:

sens: 69.0
52.0
cpus: 0
cores: 1
{
"data":[
    {"{#CPUID}":"0":"{#COREID}":"0":"{#TEMPID}":"69.0"}
    ,{"{#CPUID}":"0":"{#COREID}":"0":"{#TEMPID}":"52.0"}
    ,{"{#CPUID}":"0":"{#COREID}":"1":"{#TEMPID}":"69.0"}
    ,{"{#CPUID}":"0":"{#COREID}":"1":"{#TEMPID}":"52.0"}
]
}

Donc tu ne devrais pas faire le 3e for, mais plutôt chercher à indicer les valeurs de $sens pour récupérer la bonne une fois que tu es dans ta 2e boucle.

Oh que oui, si jamais je laisse tel quel ça ne va pas et c’est justement pour le traitement finale de la température que je suis venu poster :stuck_out_tongue:

En gros cherche à conserver une boucle car le parc machine dispose de machine de 1 à 8 CPU et de 4 à 12 cores.

Du coup je cherche à exploiter une liste ‘verticale’ de valeur que j’attribue via une boucle for (tant qu’il y a des valeur en fin de compte) à chaque core renseigner par mes deux boucles précédentes.

Mais je conçoit que c’est tordu comme fonctionnement.

J’ai surtout besoin de générer une *@#><!$? de json avec les trois valeurs :confused:

Mode verbeux attention les yeux :slight_smile:

[root@cs-eu-fr-ikdc1-mysql01 scripts]# /etc/zabbix/scripts/discover_cores-V2.sh

cores="$(lscpu | grep -E 'Cœur|Coeur' | tr -s ' ' | tr -d ':' | sed 's/.* //')"
lscpu | grep -E 'Cœur|Coeur' | tr -s ' ' | tr -d ':' | sed 's/.* //')"
lscpu | grep -E 'Cœur|Coeur' | tr -s ' ' | tr -d ':' | sed 's/.* //')
lscpu | grep -E 'Cœur|Coeur' | tr -s ' ' | tr -d ':' | sed 's/.* //'
++ lscpu
++ grep -E 'Cœur|Coeur'
++ tr -s ' '
++ tr -d :
++ sed 's/.* //'
+ cores=6
cores=$((cores-1))
+ cores=5
cpus="$(lscpu | grep -E 'Socket|Support\(' | tr -s ' ' | sed 's/.* //')"
lscpu | grep -E 'Socket|Support\(' | tr -s ' ' | sed 's/.* //')"
lscpu | grep -E 'Socket|Support\(' | tr -s ' ' | sed 's/.* //')
lscpu | grep -E 'Socket|Support\(' | tr -s ' ' | sed 's/.* //'
++ lscpu
++ grep -E 'Socket|Support\('
++ tr -s ' '
++ sed 's/.* //'
+ cpus=2
cpus=$((cpus-1))
+ cpus=1
sens="$(sensors | grep 'Core' | cut -d "(" -f 1 | cut -d "+" -f 2 | cut -c 1-4)"
sensors | grep 'Core' | cut -d "(" -f 1 | cut -d "+" -f 2 | cut -c 1-4)"
sensors | grep 'Core' | cut -d "(" -f 1 | cut -d "+" -f 2 | cut -c 1-4)
sensors | grep 'Core' | cut -d "(" -f 1 | cut -d "+" -f 2 | cut -c 1-4
++ sensors
++ grep Core
++ cut -d '(' -f 1
++ cut -d + -f 2
++ cut -c 1-4
+ sens='67.0
69.0
67.0
69.0
66.0
66.0
54.0
50.0
51.0
49.0
53.0
53.0'

echo "$sens"
+ echo '67.0
69.0
67.0
69.0
66.0
66.0
54.0
50.0
51.0
49.0
53.0
53.0'
67.0
69.0
67.0
69.0
66.0
66.0
54.0
50.0
51.0
49.0
53.0
53.0

echo "{"
+ echo '{'
{
echo "\"data\":["
+ echo '"data":['
"data":[

comma=""
+ comma=
for cpu in $(seq 0 "$cpus")
do
        for core in $(seq 0 "$cores")
        do
               for temp in $sens
               do
                        echo "    $comma{\"{#CPUID}\":\"$cpu\":\"{#COREID}\":\"$core\":\"{#TEMPID}\":\"$temp | head - "${$core+1}"\"}"
                    comma=","
               done
        done
done
seq 0 "$cpus")
seq 0 "$cpus"
++ seq 0 1
+ for cpu in '$(seq 0 "$cpus")'
seq 0 "$cores")
seq 0 "$cores"
++ seq 0 5
+ for core in '$(seq 0 "$cores")'
+ for temp in '$sens'
/etc/zabbix/scripts/discover_cores-V2.sh: line 23: "    $comma{\"{#CPUID}\":\"$cpu\":\"{#COREID}\":\"$core\":\"{#TEMPID}\":\"$temp | head - "${$core+1}"\"}" : mauvaise substitution

echo "]"
+ echo ']'
]
echo "}"
+ echo '}'
}

Si tu veux afficher $core + 1, fais $(($core + 1)) car ${core+1} n’est pas correct.

Lors d’un de mes derniers essais del a journée j’avais aussi tenté :

echo "    $comma{\"{#CPUID}\":\"$cpu\":\"{#COREID}\":\"$core\":\"{#TEMPID}\":\"$($temp | head - "$(($core+1))")\"}"

Avec le mode debug je me rends bien compte que c’est mon head qui ne marche pas :confused:

+ for temp in '$sens'
$temp | head - "$(($core+1))")\"}"
$temp | head - "$(($core+1))")"}
$temp | head - "$(($core+1))"
++ 50.0
++ head - 6
/etc/zabbix/scripts/discover_cores-V2.sh: line 23: 50.0 : commande introuvable
head: impossible d'ouvrir « 6 » en lecture: Aucun fichier ou dossier de ce type
+ echo '    ,{"{#CPUID}":"1":"{#COREID}":"5":"{#TEMPID}":"==> entrée standard <=="}'
    ,{"{#CPUID}":"1":"{#COREID}":"5":"{#TEMPID}":"==> entrée standard <=="}
+ comma=,

MAis j’avaoue ne plus trop comment réussir à lui faire prendre la valeur à la ligne équivalent à $core + 1

@Clochette, m’est avis que tu t’y prends mal :wink:

un coup de man t’informerais de l’option -p <= tu vas voir comment cela va te faciliter la vie :wink:

lscpu -p | grep -v '#' | awk -F ',' '{ print "CPU: "$1"; Core: "$2 }'

(par exemple) :wink:

ensuite ta commande sensors, tu peux drastiquement réduire ton code ainsi :

sensors | awk '/Core/ { print susbstr($3, 2, 4) }'

1 J'aime

J’en doute pas c’est un script vite fait mais qui doit être portable sur un maximum de machine.
Je viens de jeter un oeil, effectivement la commande -p de lscpu facilité le traitement, mais mon véritable souci c’est de pouvoir après coup envoyer en valeur la ligne adéquat en fonction du core de façon à me fournir un json correctement exploitable après coup.

Je vais regarder pour rendre déjà le traitement plus sexy, mais je vois pas (même si c’est relativement laid ce que je fais :stuck_out_tongue: ) pourquoi ça ne me traite pas mon head.

A croire que la valeur de $core disparait après traitement au lieu d’être conservée et modifée lors de la boucle d’après :thinking:

C’est justement tout le soucis. Sur ma sid, ton écriture “Coeur” et son équivalent n’existe pas, il faut le restituer par son terme anglais.
C’est pour cela que j’ai eu l’idée de regarder le man, me disant, au cas où qu’il faciliterait la vie avec une des options.
Il en est sorti l’option ‘-p’… d’ailleurs, l’option ‘-J’ est intéressante, mais te complexifiera le traitement…
alors qu’avec ‘-p’, tu vas direct à l’essentiel ! :wink:

1 J'aime

Désolé, je persiste à penser qu’avec 2 for ce sera plus simple :yum:

sens="temp1 temp2 ... tempN" # ou en liste verticale, c'est pareil
a=1
pour i=0 ; i <= $CPU ; i++
    pour j=0; j<=($Cores / $CPU) ; j++
        temp=$(echo $sens | cut -d ' ' -f $a) # température CPU i Core j
        a=a+1
    fin pour
fin pour

L’idée est de simplement parcourir la liste des coeurs, et pour chaque coeur récupérer l’indice de la variable $sens qui correspond, cet indice étant incrémenté à chaque nouveau coeur (dans la 2e boucle).

1 J'aime

Je vais regarder à ça dès que j’ai 5 minutes, merci déjà pour le temps passé à vous trois.

Bonsoir

si j’ai bien compris ce qu’il fallait,
Je pensais juste à ça :

#!/bin/bash

indent="        "
sortie="{\n \"data\":[\n$indent"

while read; do
    if [[ "$REPLY" =~ "Physical id "([0-9]*) ]]; then
        cpu=${BASH_REMATCH[1]}
        read
        while [[ "$REPLY" =~ "Core "([0-9]*)": "*\+(.*)°C" " ]]; do
           sortie+=' {"{#CPUID}":"'$cpu'":"{#COREID}":"'${BASH_REMATCH[1]}'":"{#TEMPID}":"'${BASH_REMATCH[2]}'"},\n'"$indent"
           read
        done
    fi
done <<< "$(sensors)"

echo -e "${sortie%,*}\n$indent]\n}\n"

Qui pourrait donner une sortie de ce genre :

{
 "data":[
          {"{#CPUID}":"0":"{#COREID}":"0":"{#TEMPID}":"37.0"},
          {"{#CPUID}":"0":"{#COREID}":"1":"{#TEMPID}":"37.0"},
          {"{#CPUID}":"0":"{#COREID}":"2":"{#TEMPID}":"31.0"},
          {"{#CPUID}":"0":"{#COREID}":"3":"{#TEMPID}":"27.0"},
          {"{#CPUID}":"1":"{#COREID}":"0":"{#TEMPID}":"35.0"},
          {"{#CPUID}":"1":"{#COREID}":"1":"{#TEMPID}":"39.0"},
          {"{#CPUID}":"1":"{#COREID}":"2":"{#TEMPID}":"34.0"},
          {"{#CPUID}":"1":"{#COREID}":"3":"{#TEMPID}":"26.0"}
        ]
}
3 J'aime

Alors la c’est exactement ça, et effectivement la solution de Sputnik93, m’avais amené a aussi un truc fonctionnel mais (et c’est surement lié à moi) beaucoup plus compliqué.

Merci à vous.