Comando cp simples não funciona (dentro do shell script e enviado usando sbatch em um cluster)
Estou trabalhando em um cluster que executa o RHEL e envio trabalhos usando o seguinte comando.
sbatch MyScript.sh
O conteúdo do MyScript.sh é o seguinte.
#!/bin/sh
# ....
# Other SBATCH related commands are here
# ....
## Script begins here
for d in lambda.*/
do
cd ${d%?} echo "Changed Directory" cp -r ../Transfer/${d%?}/ENMIN/ ./
echo "Transferred"
rm -rf ../Transfer/${d%?} echo "Removed" cd ENMIN time mpirun -np $SLURM_NTASKS gmx_mpi mdrun -v -stepout 1000 -s enmin.tpr -deffnm enmin
echo "Energy minimization done of $d cycle" echo "Copying to OutboundTransfer" mkdir ../../Transfer/${d%?}
cp -r ../ENMIN ../../Transfer/${d%?}
echo "Copied"
cd ../../
done
O problema é a linha cp -r ../Transfer/${d%?}/ENMIN/ ./, que não está funcionando. O script não está indo além dessa linha. Ele copia um arquivo e é isso .. ele para de fazer qualquer coisa produtiva. Ele imprime "Diretório alterado" no log e nada mais.
Duas coisas estranhas: (1) o "cp" (dentro do vi) é colorido de forma diferente dos outros comandos e (2) quando eu verifico squeue, o trabalho parece estar em execução sem que nada realmente aconteça (como se estivesse em um loop).
A estrutura de diretório pertinente é a seguinte (saída da árvore).
|-- lambda.00
|-- lambda.01
|-- lambda.02
|-- lambda.03
|-- lambda.04
|-- lambda.05
|-- lambda.06
|-- lambda.07
|-- lambda.08
|-- lambda.09
|-- lambda.10
|-- lambda.11
|-- lambda.12
|-- lambda.13
|-- lambda.14
|-- lambda.15
|-- lambda.16
|-- lambda.17
|-- lambda.18
|-- lambda.19
|-- lambda.20
|-- lambda.21
|-- lambda.22
|-- lambda.23
|-- lambda.24
|-- lambda.25
|-- lambda.26
|-- lambda.27
|-- lambda.28
|-- lambda.29
`-- Transfer
|-- lambda.00
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.01
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.02
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.03
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.04
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.05
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.06
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.07
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.08
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.09
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.10
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.11
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.12
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.13
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.14
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.15
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.16
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.17
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.18
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.19
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.20
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.21
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.22
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.23
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.24
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.25
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.26
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.27
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
|-- lambda.28
| `-- ENMIN
| |-- enmin.tpr
| `-- mdout.mdp
`-- lambda.29
`-- ENMIN
|-- enmin.tpr
`-- mdout.mdp
Tenho controle limitado sobre este cluster. Quais são minhas opções para fazer este script funcionar?
Respostas
A ${d%?}construção não funciona em shells POSIX como sh. Dependendo do seu sistema operacional, você shserá um shell POSIX simples como dash(por exemplo, no Debian ou Ubuntu) ou talvez bashrodando no modo POSIX. Em qualquer um dos casos, o ${d%?}não será compreendido e é provavelmente isso que está quebrando seu script.
Uma solução simples seria usar #!/bin/bashpara executá-lo. No entanto, seu script também parece desnecessariamente complicado. Por um lado, o ${d%?}simplesmente remove a barra final do nome do diretório, mas não há nenhum benefício em fazer isso:
$ d="bar/"
$ cd $d
$ pwd
/home/terdon/foo/bar
Ter uma (ou mais) barras no final de um nome de diretório é bom. Você poderia muito bem fazer cd barcomo cd bar/ou cd bar//////////.
Dito isso, também não há necessidade cdem primeiro lugar, isso apenas adiciona uma camada de complicação sem um bom motivo. Esta é uma versão simplificada do seu script:
#!/bin/bash
for d in lambda.*/
do
mv Transfer/"$d"/ENMIN/ "$d" echo "Transferred" ( ## open a subshell so the cd only hapens in the subshell ## and doesn't affect the script cd "$d"/ENMIN/ &&
time mpirun -np $SLURM_NTASKS gmx_mpi mdrun -v -stepout 1000 -s enmin.tpr -deffnm enmin ) echo "Energy minimization done of $d cycle"
echo "Copying to OutboundTransfer"
mkdir Transfer/"$d" cp -r "$d"/ENMIN Transfer/"$d"
echo "Copied"
done
Não sei como sbatchfunciona, mas pelo que você descreve, parece provável que ele esteja executando o script sh, ignorando a coisa. Você também pode tentar sbatch bash MyScript.shou simplesmente tentar a minha versão acima, que deve ser portátil para qualquer shell estilo sh. O único bashism que você tinha era o ${d%?}mesmo, então removê-lo deve resolver todos os seus problemas.