#!/bin/bash # # Fonctions utiles pour les scripts de Pack IPSL # function DEM_read_state { # Lire l'état du pack pour une simulation local L_CONFIG_FILE=${1} local L_CONFIG_CARD=${2} local L_OLD_STATE=$( grep ${L_CONFIG_CARD} ${L_CONFIG_FILE} | awk '{print $2}' ) if [ ${?} -eq 0 ] then echo ${L_OLD_STATE} return 0 else return 1 fi return 0 } function DEM_write_state { # Mettre à jour l'état du pack pour une simulation local L_CONFIG_FILE=${1} local L_CONFIG_CARD=${2} local L_NEW_STATE=${3} local L_MAX_TRY=10 L_TRY=0 L_CHECK L_PP # On essaye ${L_MAX_TRY} fois de mettre à jour le fichier while [ ${L_TRY} -le ${L_MAX_TRY} ] do if [[ ! -f ${L_CONFIG_FILE}.lock ]] then echo ${$} >> ${L_CONFIG_FILE}.lock ; chmod -w ${L_CONFIG_FILE}.lock L_CHECK=$( wc -l ${L_CONFIG_FILE}.lock | awk '{print $1}' ) if [[ ${L_CHECK} -gt 1 ]] then DEM_log -0 "Erreur. Plusieurs processus on pose un verrou sur ${L_CONFIG_FILE}" for L_PP in $( awk '{print $1}' ${L_CONFIG_FILE}.lock ) do DEM_log -0 "Erreur. Process : ${L_PP}" done return 1 fi local L_OLD_LINE=$( grep ${L_CONFIG_CARD} ${L_CONFIG_FILE} ) [[ ${?} -eq 0 ]] || ( return 1 ; ) if [[ ${L_OLD_LINE} = "" ]] then DEM_log -0 "Erreur. Dans le fichier : ${L_CONFIG_FILE}, Experience ${L_CONFIG_CARD} non trouvee" return 1 fi local L_OLD_STATE=$( echo ${L_OLD_LINE} | awk '{print $2}' ) [[ ${?} -eq 0 ]] || ( return 1 ; ) L_NEW_LINE="${L_CONFIG_CARD} ${L_NEW_STATE}" sed -i "s%${L_OLD_LINE}%${L_NEW_LINE}%" ${L_CONFIG_FILE} rm -f ${L_CONFIG_FILE}.lock break else (( L_TRY = L_TRY + 1 )) DEM_log -3 "Fichier ${L_CONFIG_FILE} en cours de modif par un autre processus. Essai ${L_TRY}" sleep 1 fi done if [[ ${L_TRY} -ge ${L_MAX_TRY} ]] then DEM_log -0 "Erreur. Verrou sur le fichier : ${L_CONFIG_FILE}" return 1 fi return 0 } function DEM_min { # Calcul du minimum d'un nombre quelconque d'entiers local l_min=${1} l_xx for l_xx in ${*:2:${#}} do [[ ${l_xx} -lt ${l_min} ]] && l_min=${l_xx} done echo ${l_min} } function DEM_max { # Calcul du maximum d'un nombre quelconque d'entiers local l_max=${1} l_xx for l_xx in ${*:2:${#}} do [[ ${l_xx} -gt ${l_max} ]] && l_max=${l_xx} done echo ${l_max} } function DEM_log { # Affichage d'un message sur stdout et dans un fichier de log # DEM_log [-0|-1|-2|-3] Message # local MESSAGE P_LINE L_NAME LOG_LEV=${LOG_LEV:-3} local OPTARG OPTIND L_LOG=1 local L_DEM_LOG=${DEM_LOG:-dem_log.${$}} while getopts 0123 L_NAME do case ${L_NAME} in ( 0 ) L_LOG=1 ;; ( 1 ) L_LOG=1 ;; ( 2 ) L_LOG=2 ;; ( 3 ) L_LOG=3 ;; esac done shift $(( ${OPTIND} - 1 )) if [[ ${L_LOG} -le ${LOG_LEV} ]] then MESSAGE=${*} P_LINE="$(date) - ${MESSAGE}" echo ${P_LINE} echo ${P_LINE} >> ${L_DEM_LOG} fi return } # gpdebug : fonctions de gestion des erreurs ######################################################## function DEM_errorSend { # Envoi d'un msg d'erreur au programme principal. # Suppression des processus du programme principal au fils emetteur de l'erreur echo "########## DEM_errorSend : Error detected ==> Sending an error..." msgToSend=${1} listPIDtoKill=${2} if [ "x${listPIDtoKill}" == "x" ] then listPIDtoKill=${listPID} fi # -------------------------------- # Verif du format de listPIDtoKill # -------------------------------- listPIDformat='^[[:digit:]]*\([[:blank:]][[:digit:]]*\)*$' isListPIDformatOK=`echo ${listPIDtoKill} | grep -e ${listPIDformat} | wc -l ` if [ "x$isListPIDformatOK" == "x0" ] then echo " Attention : le format de la liste de PID est incorrecte :" echo " $listPIDtoKill" kill -TERM ${listPID} fi # ----------------------------------- # Verif du Format du ${msgToSend} # ----------------------------------- errorFormat='^[^:]*\.sh:[[:digit:]]*:.*$' isErrorFormatOK=`echo ${msgToSend} | grep -e ${errorFormat} | wc -l ` if [ "x$isErrorFormatOK" == "x0" ] then echo " Attention : le format du message d'erreur est incorrect :" echo " $msgToSend" fi # Envoi du msg dans le fichier d'erreur # ------------------------------------- # test sur la var contenant le nom du fichier d'erreur if [ "x${errorMsgFile}" != "x${PWD}/errorMsg.txt" ] then echo " Le fichier d'erreur a un nom incorrect" fi echo $msgToSend > $errorMsgFile echo "killing ${listPIDtoKill}" kill -TERM ${listPIDtoKill} exit -1 # utile : sinon le script qui appelle cette fonction continue un peu l'exec --> pas propre } function DEM_errorReceive { # Récupération et affichage du msg d'erreur emis par un processus fils # Lecture du msg dans le fichier d'erreur # --------------------------------------- # test sur la var contenant le nom du fichier d'erreur if [ "x${errorMsgFile}" != "x${PWD}/errorMsg.txt" ] then echo " Le fichier d'erreur a un nom incorrect" exit -1 fi # Lecture errorReceived=`cat $errorMsgFile ` # ----------------------------------- # Verif du Format du ${errorReceived} # ----------------------------------- errorFormat='^[^:]*\.sh:[[:digit:]]*:.*$' isErrorFormatOK=`echo ${errorReceived} | grep -e ${errorFormat} | wc -l ` if [ "x$isErrorFormatOK" == "x0" ] then echo " Attention : le format du message d'erreur est incorrect :" echo " $errorReceived" exit -1 fi echo "########## DEM_errorReceive : $SCRIPT_NAME received an error..." echo $errorReceived # echo "Current PID:$$" # echo "FatherPID:$FatherPID" # On fait un bilan de la progression seulement si c'est une erreur bloquante : lorsque le proc pere est tue. if [ "x${FatherPID}" == "x$$" ] then ./showListsProgress.sh $FileParam fi exit -1 } # Verification de la version de nco chargee function check_nco_version { # nom du présent prog (pour gestion des erreurs) PROGNAME="DEM_utilities.sh" ######### . /etc/profile module list >& myModuleList.txt if [ "x$?" != "x0" ] then # echo "La commande module list a rencontre un pb !" DEM_errorSend "${PROGNAME}:${LINENO}:La commande module list a rencontre un pb !" fi if [ ! -e myModuleList.txt ] then # echo "Le fichier 'myModuleList.txt' n existe pas" DEM_errorSend "${PROGNAME}:${LINENO}:Le fichier 'myModuleList.txt' n'existe pas." fi # Presence de la chaine "n) nco/" ou n est un nombre ncoLines=` grep -e '[[:digit:]]*) nco/' myModuleList.txt ` # ncoLines=` grep -e '[[:digit:]]*) nco/' moduleList.txt ` # echo "ncoLines=${ncoLines}|" # echo "----------------------------------------" # Plus besoin du myModuleList.txt rm -f myModuleList.txt # La chaine "nco" est remplacee par le caractere "#" temp1=`echo $ncoLines | sed 's;nco;#;g' ` # echo "$temp1" # echo "----------------------------------------" # On supprime tout ce qui n'est pas "n) #/..." avec n un nombre et "..." une chaine sans blanc temp2=`echo $temp1 | sed 's;[[:blank:]]*[[:digit:]]*) [^#][^[:blank:]]*;;g' ` # echo "$temp2" # echo "----------------------------------------" # Recuperation du numero de version du nco au format x.y.z # C'est une liste de num de version (a priori ici, il pourrait y en avoir plusieurs, # mais dans les faits, les nco s'excluent les uns les autres) temp3=`echo $temp2 | sed 's;[[:blank:]]*[[:digit:]]*) #/;|;g' ` temp3=`echo $temp3 | sed 's;^|;;g' ` temp3=`echo $temp3 | sed 's;|; ;g' ` # echo "$temp3" # echo "----------------------------------------" # comptage du nombre de nco versionNCO= count=0 for ver in $temp3 do # echo "ver=$ver" versionNCO=$ver count=$(( $count + 1 )) done # echo "count=$count" # si aucun nco n'est charge, on sort. if [ $count -eq 0 ] then # echo "nco pas charge" DEM_errorSend "${PROGNAME}:${LINENO}:Aucun nco n'est charge" fi # si plus d'un nco sont charges, on sort (n'arrive jamais en pratique). if [ $count -gt 1 ] then DEM_errorSend "${PROGNAME}:${LINENO}:Au moins 2 versions de nco sont chargees" fi # Si un seul nco est charge, on supprime les "." de son numero de version (x.y.z ==> xyz) verNCOnumber=`echo $versionNCO | sed 's;[^[:digit:]];;g' ` # echo "versionNCO=$versionNCO" # On verifie que xyz est un nombre a 3 chiffres if ! [[ "$verNCOnumber" =~ ^[0-9]\{3\}$ ]] then # echo "verNCOnumber is not a number" DEM_errorSend "${PROGNAME}:${LINENO}:La variable verNCOnumber n'est pas un nombre --> $verNCOnumber" fi # On verifie que le num de version est >= 4.1.0 if [ $verNCOnumber -lt 410 ] then # echo "version < 4.1.0 . STOP." DEM_errorSend "${PROGNAME}:${LINENO}:La version de nco < 4.1.0 ==> $versionNCO" fi echo "La version de nco chargee est : $versionNCO" } function prepareMonitoringDir { # nom du présent prog (pour gestion des erreurs) PROGNAME="DEM_utilities.sh" ######### MonitoringDirDefined=`echo $MonitoringDir | grep "SuiviListes" | wc -l ` if [ "x${workFlowDirDefined}" == "x0" ] then DEM_errorSend "${PROGNAME}:${LINENO}:Le repertoire de suivi est mal defini." fi # Si l'option de forcage de toute les etapes est activee, # on vide le fichier if [ "x${execEveryStep}" == "x1" ] then echo "${MonitoringDir}:destruction..." rm -rf ${MonitoringDir} fi # Si le rep de suivi n'existe pas, on le créé. if [ ! -d ${MonitoringDir} ] then mkdir ${MonitoringDir} fi } function generalMonitoring { # Si l'etape courante a ete executee (correctement), on sort du script appelant cette fonction # nom du présent prog (pour gestion des erreurs) PROGNAME="DEM_utilities.sh" ######### currentStep=${1} stepMsg=`echo $currentStep | grep -e '^.*\.sh-->OK$' | wc -l ` if [ "x{stepMsg}" == "x0" ] then DEM_errorSend "${PROGNAME}:${LINENO}:Le nom de l'etape courante n'est pas au bon format !" fi currentStepScriptName=`echo $currentStep | sed 's;\.sh-->OK;;' ` # si le fichier de suivi general n'existe pas, il n'y a pas eu de passage de script de liste avant. # ==> on sort normalement if [ ! -e ${generalMonitorFile} ] then return 0 fi currentStepPassed=`grep ${currentStep} ${generalMonitorFile} | wc -l ` if [ "x${currentStepPassed}" != "x0" ] then echo "${currentStepScriptName} a deja ete passee ..." exit 0 fi } function createListingMonitoring_Check { # La presence de createListingOK.txt dans le sous rep (associe a un rep de param_AC.txt) du rep de suivi # indique que le bon deroulement de l'action de create_listing.sh sur le repertoire de param_AC.txt DIR=$(basename ${1}) MonitSubDir=${MonitoringDir}/${DIR} createListingOK=${MonitSubDir}/createListingOK.txt if [ -e $createListingOK ] then echo "create_listing a deja ete passe pour ${DIR}..." exit 0 fi } function createListingMonitoring_OK { # A partir du nom du rep courant (contenant des res de simulation), creation d'un sous rep de suivi DIR=$(basename ${1}) MonitSubDir=${MonitoringDir}/${DIR} mkdir $MonitSubDir # dans ce sous rep de suivi, creation d'un fichier dont la presence indique le bon deroulement # de l'action de create_listing.sh sur le repertoire en argument (celui contenant des simus) createListingOK=${MonitSubDir}/createListingOK.txt touch $createListingOK } function simuMonitoring_check { # nom du présent prog (pour gestion des erreurs) PROGNAME="DEM_utilities.sh" ######### currentStep=${1} config=${2} # echo "######### simuMonitoring_check --> config:$config" # former le nom du fichier de suivi de la simu a partir de "config" getSimuMonitFileName $config # si le fichier de suivi de simu n'existe pas, il n'y a pas eu de passage de script de liste avant. # ==> on sort normalement if [ ! -e ${simuMonitoringFile} ] then return 0 fi stepMsg=`echo $currentStep | grep -e '^.*\.sh-->OK$' | wc -l ` if [ "x{stepMsg}" == "x0" ] then DEM_errorSend "${PROGNAME}:${LINENO}:Le nom de l'etape courante n'est pas au bon format !" fi currentStepScriptName=`echo $currentStep | sed 's;\.sh-->OK;;' ` currentStepPassed=`grep ${currentStep} ${simuMonitoringFile} | wc -l ` # echo "######### simuMonitoring_check --> currentStep:$currentStep" # echo "######### simuMonitoring_check --> simuMonitoringFile:$simuMonitoringFile" # echo "######### simuMonitoring_check --> currentStepPassed:$currentStepPassed" if [ "x${currentStepPassed}" != "x0" ] then echo "${currentStepScriptName} a deja ete passee ..." # echo "-----------------------------------------------------------------------------" exit 0 fi } function simuMonitoring_OK { currentStep=${1} config=${2} # echo "######### simuMonitoring_OK --> config:$config" # former le nom du fichier de suivi de la simu a partir de "config" getSimuMonitFileName $config echo $currentStep >> $simuMonitoringFile } function getSimuMonitFileName { # nom du présent prog (pour gestion des erreurs) PROGNAME="DEM_utilities.sh" ######### config=${1} # echo "######### getSimuMonitFileName --> config:$config" configBaseName=$(basename ${config}) # On cherche dans quel sous rep du rep de suivi on va chercher le fichier de suivi de la simu listMonitSubDir=`ls -l ${MonitoringDir} | grep -e '^d' | awk '{print $NF}' ` # echo "######### getSimuMonitFileName --> listMonitSubDir:$listMonitSubDir" searchedDir= for dir in $listMonitSubDir do found=`echo $config | grep "/${dir}/" | wc -l ` if [ "x${found}" != "x0" ] then searchedDir=$dir break fi done if [ "x$searchedDir" == "x" ] then DEM_errorSend "${PROGNAME}:${LINENO}:Sous rep de suivi non trouve !" fi # On forme le nom du fichier de suivi pour la simu courante # ... on debarasse config du fichier de config repConfig=$(dirname $config) # ... on supprime du path tout ce qui est devant le nom du sous rep simu=`echo $repConfig | sed "s;^.*/$searchedDir;$searchedDir;" ` # ... remplacement des "/" par des "_#_" (les "/" ne sont pas acceptes dans les noms de fichiers) simuMonitoringFile=`echo $simu | sed 's;/;_#_;g' ` # ... On rajoute un ".txt" a la fin du nom de fichier simuMonitoringFile="${simuMonitoringFile}.txt" simuMonitoringFile="${MonitoringDir}/${searchedDir}/${simuMonitoringFile}" } # gpdebug : fin #####################################################################################