Script Bash para automatizar cálculos HPC

Sep 01 2020

Sou um estudante de química trabalhando em um script bash simples para automatizar cálculos de teoria funcional de densidade de HPC usando Quantum Espresso (pw.x). Sou um novato em script de shell e gostaria de receber algumas críticas / comentários antes de tentar implementá-lo no cluster. O script chama in-gen.py, que é um script Python que escrevi para gerar novos arquivos de entrada se certos limites de parâmetro no arquivo de log não forem atendidos.

#!/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

Respostas

4 l0b0 Sep 01 2020 at 10:02

Sugestões específicas:

  1. Os nomes das funções são por convenção snake_case.
  2. Use More Quotes ™ .
  3. [[deve ser usado em vez de[ , porque é mais seguro.
  4. [[ EXPRESSION ]] && [[ EXPRESSION ]]seria mais claro do que [[ EXPRESSION && EXPRESSION ]], na minha opinião.
  5. set -o errexit -o noclobber -o nounset -o pipefaile shopt -s globfailtornaria o tratamento de erros muito mais rígido.
  6. Este não é mais um código trivial, então eu recomendo implementá-lo em uma linguagem não shell como Python.

Sugestões de ferramentas:

  1. Executar shellchecko script regularmente é uma boa maneira de capturar possíveis problemas. Neste caso, a única coisa que encontra é para rm -r *x*x*:

    SC2035: Use ./ glob ou - glob para que nomes com travessões não se tornem opções.