쉘의 고양이 오류

쉘의 고양이 오류

작업 예약을 위해 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 과 같은 존재하지 않는 명령 에서도 동일한 오류가 발생합니다.dogunicorntribble

실제 대답은 .as <<-대신에 말해야 한다는 것입니다.<<또 다른 대답거의 (그러나 완전히는 아니지만) 문제는 를 사용할 때 <<쉘이 KHIK"여기 문서"를 종료하는 줄에서 유일한 구분 기호 단어(예제에서는)를 찾는다는 것입니다. ,,,심지어 는 있을 수 없습니다 FOOKHIKBAR. 를 사용하면 셸은 여기 문서의 각 줄 시작 부분에 있는 모든 탭을 제거하므로 정상적으로 보입니다.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 월타임=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다른 쉘과 함께 실행될 수 있습니다 (제외 bash) - 참조이 답변더 알아보기. (첫 번째 줄의 공백이 아닌 첫 번째 문자는 이므로 #해당 줄은 주석으로 처리됩니다. 이것은 shebang 작동 방식에서 중요하면서도 종종 간과되는 측면입니다.)

질문 본문과 관련이 없습니다. 타당한 이유가 없고 현재 수행 중인 작업을 확실히 알고 있지 않는 한 항상 쉘 변수 참조(예: "$i"및 )를 인용해야 합니다."$PBS_O_WORKDIR"공백이나 기타 특수 문자 때문에 쉘 스크립트가 멈추는 이유는 무엇입니까?그리고bash/POSIX 쉘에서 변수를 인용하는 것을 잊어버리는 보안 위험. 그리고 "$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 ..

나는 이것이 스크립트를 더 쉽게 살펴보고 어떤 줄이 지금 실행 중인 명령이고 어떤 줄이 데이터인지(예: 나중에 실행될 수 있는 스크립트에 대한 입력) 확인하는 것을 더 쉽게 만든다고 믿습니다.

chmod +x "run_nvt$i.pbs"PS 언젠가는 하고 싶지 않으신가요 ?
__________
1오늘 나는 배웠다프로그램이 호출됩니다dog그리고unicorn.

관련 정보