Script Bash pour automatiser les calculs HPC

Sep 01 2020

Je suis un étudiant en chimie travaillant sur un script bash simple pour automatiser les calculs de théorie fonctionnelle de densité HPC à l'aide de Quantum Espresso (pw.x). Je suis très novice en matière de scripts shell et j'apprécierais quelques critiques / commentaires avant d'essayer de l'implémenter sur le cluster. Le script appelle ingen.py qui est un script Python que j'ai écrit pour générer de nouveaux fichiers d'entrée si certains seuils de paramètres dans le fichier journal ne sont pas atteints.

#!/bin/bash
    
#SBATCH --job-name=2x2x6_PbCO3          # job name        
#SBATCH --output=slurm.out              # Output file name                                                                                                                                                
#SBATCH --error=slurm.err               # Error file name                                                                                                                                                 
#SBATCH --partition=batch               # Partition                                                                                                                                                       
#SBATCH --qos=medium+                   # Queue                                                                                                                                                           
#SBATCH --time=24:00:00                 # Time limit                                                                                                                                                      
#SBATCH --nodes=3                       # Number of nodes                                                                                                                                                 
#SBATCH --ntasks-per-node=16            # MPI processes per node 

errors='MPI_ABORT|error|aborted|SIGTERM|TIME|CANCELLED|SIGCONT|terminated|fork'
job='2x2x6_PbCO3'
max_runs=5
prefix=PbCO3

#-------------------------------------------------------------------------------
Clear () 
{
# Checks for input/log from a completed batch script
if [[ -f "$prefix.in" && -f "$prefix.log"  ]]; then
   # If both are found a new input file is generated
   python ~/path-to-in-gen.py $prefix.log $prefix.in $job override if [ -z "$(ls -A ../logs_and_inputs)" ]; then
      index=1
   else
      indices=()
      # Old input/log are tagged and stored
      for entry in "../logs_and_inputs"/$prefix.in-*; do indices+=("${entry: -1}")
      done
      max=${indices[0]} for n in "${indices[@]}" ; do
         ((n > max)) && max=$n done index=$((max+1))
      rm -r *x*x*
      mv $prefix.in ../logs_and_inputs/$prefix.in-$index mv $prefix.log ../logs_and_inputs/$prefix.log-$index
      mv $prefix.in-new $prefix.in
   fi
fi
}
#-------------------------------------------------------------------------------
# Creates a directory for old logs and inputs to be stored with a numerical tag from 1 to k
Sort ()
{
if [ ! -d "../logs_and_inputs" ]; then
    mkdir ../logs_and_inputs
    iter=1
else
   if [ -z "$(ls -A ../logs_and_inputs)" ]; then iter=1 else indices=() for entry in "../logs_and_inputs"/$prefix.in-*; do
         indices+=("${entry: -1}") done max=${indices[0]}
      for n in "${indices[@]}" ; do ((n > max)) && max=$n
      done
      iter=$((max+1)) fi fi max_iter=$((iter+max_runs))
}
#-------------------------------------------------------------------------------                                                                                                   
Automode () 
{
mpirun ~/path-to-pw.x < $prefix.in > $prefix.log
# Runs pw.x job, checks for completion and errors
if grep -E -q -- $errors "slurm.err"; then exit 1 fi if grep -q "job DONE." "$prefix.log"; then
   # Clear wavefunction files and temp directories
   rm -r *x*x*
   # Generates new input file
   python ~/path-to-in-gen.py $prefix.log $prefix.in $job # Tags and stores the previous input and log mv $prefix.in ../logs_and_inputs/$prefix.in-$iter
   mv $prefix.log ../logs_and_inputs/$prefix.log-$iter else exit 1 fi # Checks for generation of new input file if test -f "$prefix.in-new"; then
   mv $prefix.in-new $prefix.in
else
   exit 1
fi
let "iter=iter+1"
}
#-------------------------------------------------------------------------------                                                                                                   
Clear

Sort

while ((iter < max_iter)); do
   Automode
done

Réponses

4 l0b0 Sep 01 2020 at 10:02

Suggestions spécifiques:

  1. Les noms de fonction sont par convention snake_case.
  2. Utilisez More Quotes ™ .
  3. [[devrait être utilisé à la place[ , car il est plus sûr.
  4. [[ EXPRESSION ]] && [[ EXPRESSION ]]serait plus clair que [[ EXPRESSION && EXPRESSION ]], à mon avis.
  5. set -o errexit -o noclobber -o nounset -o pipefailet shopt -s globfailrendrait la gestion des erreurs beaucoup plus stricte.
  6. Ce n'est plus du code trivial, je vous recommande donc de l'implémenter dans un langage non-shell comme Python.

Suggestions d'outils:

  1. L'exécution shellcheckrégulière de votre script est un bon moyen de capturer d'éventuels problèmes. Dans ce cas, la seule chose qu'il trouve est pour rm -r *x*x*:

    SC2035: Utilisez ./ glob ou - glob pour que les noms avec des tirets ne deviennent pas des options.