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:
- Os nomes das funções são por convenção
snake_case. - Use More Quotes ™ .
- [[deve ser usado em vez de[ , porque é mais seguro.
[[ EXPRESSION ]] && [[ EXPRESSION ]]seria mais claro do que[[ EXPRESSION && EXPRESSION ]], na minha opinião.set -o errexit -o noclobber -o nounset -o pipefaileshopt -s globfailtornaria o tratamento de erros muito mais rígido.- 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:
- Executar
shellchecko script regularmente é uma boa maneira de capturar possíveis problemas. Neste caso, a única coisa que encontra é pararm -r *x*x*:SC2035: Use ./ glob ou - glob para que nomes com travessões não se tornem opções.
O que significa um erro “Não é possível encontrar o símbolo” ou “Não é possível resolver o símbolo”?