我使用以下代码在 20 个文件夹中迭代写入文件以进行作业调度。
#!/bin/bash
for i in {1..20}
do
cd conf$i
cp ../nvt.mdp $PWD
cp ../topol.top $PWD
grompp -v -f nvt.mdp -c conf$i.gro -p topol.top -o conf_nvt$i.tpr >> nvt.log
cat<<KHIK >> run_nvt$i.pbs
#!/bin/bash
#PBS -l nodes=1:ppn=16
#PBS -l walltime=120:00:00
#PBS -N GROMACS:TAUAT_P
#PBS -q blaze
#PBS -j oe
#PBS -V
cd \$PBS_O_WORKDIR
export I_MPI_DEVICE=rdma
/home/apps/ics/impi/latest/bin64/mpiexec.hydra /home/braf/md/gromacs-4.5.6/bin/mdrun_mpi -deffnm conf_nvt$i
KHIK
cd ..
done
它给出了一个奇怪的错误。你能告诉我我需要做哪些改变吗?
./umbrnvt.sh: line 22: warning: here-document at line 9 delimited by end-of-file (wanted `KHIK')
./umbrnvt.sh: line 23: syntax error: unexpected end of file
答案1
您应该在行首有结束标记。所以你的脚本应该是这样的:
#!/bin/bash
for i in {1..20}
do
cd conf$i
cp ../nvt.mdp $PWD
cp ../topol.top $PWD
grompp -v -f nvt.mdp -c conf$i.gro -p topol.top -o conf_nvt$i.tpr >> nvt.log
cat<<KHIK >> run_nvt$i.pbs
#!/bin/bash
#PBS -l nodes=1:ppn=16
#PBS -l walltime=120:00:00
#PBS -N GROMACS:TAUAT_P
#PBS -q blaze
#PBS -j oe
#PBS -V
cd \$PBS_O_WORKDIR
export I_MPI_DEVICE=rdma
/home/apps/ics/impi/latest/bin64/mpiexec.hydra /home/braf/md/gromacs-4.5.6/bin/mdrun_mpi -deffnm conf_nvt$i
KHIK
cd ..
done
否则 bash 不会将 KHIK 识别为块的结尾
答案2
首先,由于没有其他人提到这一点,因此该错误与 无关cat
。对于任何程序,例如nl
、od
、tr
,甚至像1这样不存在的命令,您都会遇到相同的错误。dog
unicorn
tribble
真正的答案是你应该说<<-
而不是<<
.作为另一个答案几乎(但不完全)说,问题是,当您使用 时<<
,shell 会查找分隔符单词(KHIK
在您的示例中)作为终止“此处文档”的行上的唯一内容。不可能是FOOKHIKBAR
、、、甚至。当您使用 时,shell 会删除此处文档中每行开头的所有制表符,因此看起来就像普通的。FOO KHIK BAR
KHIK FU
TabKHIK
<<-
TabKHIK
KHIK
但同样重要的问题是,如果你说
cat<<KHIK >> run_nvt$i.pbs
#!/bin/bash
#PBS -l nodes=1:ppn=16
#PBS -l walltime=120:00:00
#PBS -N GROMACS:TAUAT_P
#PBS -q blaze
#PBS -j oe
#PBS -V
cd \$PBS_O_WORKDIR
export I_MPI_DEVICE=rdma
/home/apps/ics/impi/latest/bin64/mpiexec.hydra /home/braf/md/gromacs-4.5.6/bin/mdrun_mpi -deffnm conf_nvt$i
KHIK
那么你会得到
#!/bin/bash #PBS -l 节点=1:ppn=16 #PBS -l walltime=120:00:00 #PBS -N GROMACS:TAUAT_P #PBS -q 火焰 #PBS-乔伊 #PBS-V cd $PBS_O_WORKDIR 导出 I_MPI_DEVICE=rdma /home/apps/ics/impi/latest/bin64/mpiexec.Hydra /home/braf/md/gromacs-4.5.6/bin/mdrun_mpi -deffnm conf_nvt{的价值 $i}
在run_nvt$i.pbs
。那不好。为了使“shebang”(#!
行)正常工作,#!
必须是该行中的前两个字符。如果您遵循其他答案的建议,您的run_nvt$i.pbs
脚本将有一个不被尊重/认可的 shebang,并且它可能会与/bin/sh
其他 shell 一起运行(除了bash
) - 请参阅这个答案了解详情。 (由于第一行的第一个非空白字符是 a #
,因此该行将被视为注释。这是 shebang 工作方式的一个重要且经常被忽视的方面。)
与你的问题主体无关——你应该总是引用你的shell变量引用(例如,"$i"
和"$PBS_O_WORKDIR"
),除非你有充分的理由不这样做,并且你确定你知道你在做什么;看为什么我的 shell 脚本会因为空格或其他特殊字符而卡住?和忘记在 bash/POSIX shell 中引用变量的安全隐患。而且你不需要"$PWD"
像你想象的那样经常使用——通常使用就足够了.
。而且(IMNSHO)它有助于尽可能使用空格的可读性。所以我建议你修改你的脚本如下:
#!/bin/bash
for i in {1..20}
do
cd "conf$i"
cp ../nvt.mdp .
cp ../topol.top .
grompp -v -f nvt.mdp -c conf$i.gro -p topol.top -o "conf_nvt$i.tpr" >> nvt.log
cat <<- KHIK >> "run_nvt$i.pbs"
#!/bin/bash
#PBS -l nodes=1:ppn=16
#PBS -l walltime=120:00:00
#PBS -N GROMACS:TAUAT_P
#PBS -q blaze
#PBS -j oe
#PBS -V
cd "\$PBS_O_WORKDIR"
export I_MPI_DEVICE=rdma
/home/apps/ics/impi/latest/bin64/mpiexec.hydra /home/braf/md/gromacs-4.5.6/bin/mdrun_mpi -deffnm "conf_nvt$i"
KHIK
cd ..
done
请注意 之前和之后的空格<<-
以及附加引号。
我喜欢的一种风格选择是在此处缩进文档:
︙
grompp -v -f nvt.mdp -c conf$i.gro -p topol.top -o "conf_nvt$i.tpr" >> nvt.log
cat <<- KHIK >> "run_nvt$i.pbs"
#!/bin/bash
#PBS -l nodes=1:ppn=16
#PBS -l walltime=120:00:00
#PBS -N GROMACS:TAUAT_P
#PBS -q blaze
#PBS -j oe
#PBS -V
cd "\$PBS_O_WORKDIR"
export I_MPI_DEVICE=rdma
/home/apps/ics/impi/latest/bin64/mpiexec.hydra /home/braf/md/gromacs-4.5.6/bin/mdrun_mpi -deffnm "conf_nvt$i"
KHIK
cd ..
︙
我相信这样可以更轻松地浏览脚本,并查看哪些行是现在正在执行的命令,哪些行是数据(例如,输入到脚本,稍后可能会执行它们)。
PS 你不想chmod +x "run_nvt$i.pbs"
在某个时候做吗?
__________
1今天我了解到是程序称为dog
和unicorn
。