shell 中的猫错误

shell 中的猫错误

我使用以下代码在 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。对于任何程序,例如nlodtr,甚至像1这样不存在的命令,您都会遇到相同的错误。dogunicorntribble

真正的答案是你应该说<<-而不是<<.作为另一个答案几乎(但不完全)说,问题是,当您使用 时<<,shell 会查找分隔符单词(KHIK在您的示例中)作为终止“此处文档”的行上的唯一内容。不可能是FOOKHIKBAR、、、甚至。当您使用 时,shell 会删除此处文档中每行开头的所有制表符,因此看起来就像普通的。FOO KHIK BARKHIK FUTabKHIK<<-TabKHIKKHIK

但同样重要的问题是,如果你说

        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/mp​​iexec.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今天我了解到程序称为dogunicorn

相关内容