update-grub(Grub 2)의 grub.cfg에 구문 오류가 있습니다(memtest86+).

update-grub(Grub 2)의 grub.cfg에 구문 오류가 있습니다(memtest86+).

update-grub을 실행하거나 다시 설치하려고 하면 "구문 오류"가 발생합니다.

출력은 다음과 같습니다.

error: syntax error.
error: Incorrect command.
error: syntax error.
error: line no: 262
Syntax errors are detected in generated GRUB config file.
Ensure that there are no errors in /etc/default/grub
and /etc/grub.d/* files or please file a bug report with
/boot/grub/grub.cfg.new file attached.

왜 이런 일이 발생합니까? 어떡해?

배경

Manjaro 업데이트 후 시스템이 더 이상 부팅되지 않습니다. "파일을 찾을 수 없습니다"라고 뜹니다 /boot/vmlinuz-316-x86_64. 그런 다음 "먼저 커널을 로드해야 합니다".

그런 다음 USB 스틱(manjaro 라이브/설치 프로그램 디스크)에서 부팅하고 아래 지침을 따랐습니다.https://wiki.manjaro.org/index.php/Restore_the_GRUB_Bootloader(UEFI 시스템) chroot 및 update-grub을 사용하십시오. 실제로 "구문 오류" 문제를 처음 발견한 것은 "EFI 변수는 이 시스템에서 지원되지 않습니다."라는 메시지를 받은 후 grub을 다시 설치하려고 시도하는 단계에서였습니다.

내 생각에는 (확실하지는 않지만) 이 일이 한동안 눈치채지 못한 채 진행되었을 수도 있습니다. grub.cfg에 대한 모든 업데이트가 실패했지만 이전 grub.cfg는 여전히 "충분히 양호"했습니다. 그러나 업데이트 후 vmlinuz 파일의 이름이 바뀌었고 grub.cfg는 더 이상 존재하지 않는 이전 vmlinuz 파일을 참조했습니다. 이것이 스타트업이 실패한 이유이다.


(이 글을 쓰면서 이미 답을 알고 있습니다. 완전한 설명은 아닐 수도 있지만 고치는 것만으로도 충분합니다. 다른 사람들의 수고를 덜어주기 위해 결과를 공유하고 싶었습니다.)

답변1

나에게 이것은 매우 구체적인 대답이지만, 이 문제를 해결하는 방법을 보다 일반적인 방법으로 설명하고 싶습니다.

실제로 오류 메시지에는 이미 많은 정보가 포함되어 있지만 처음에는 명확하지 않았습니다.

간단히 말해서:

  • /boot/grub/grub.cfg.new의 줄 번호를 따르십시오. 구문 오류가 나타나는 이유를 이해해 보세요.
  • /etc/default/grub 또는 /etc/grub/*의 특정 파일을 가리키는 이 파일의 설명을 따르십시오.
  • 프록시 스크립트인 경우 프롬프트에 따라 찾으십시오 /etc/grub.d/proxifiedScripts/.

자세한 문제 해결 단계

/boot/grub/grub.cfg다음 파일 수를 기반으로 "update-grub"에서 자동으로 생성됩니다: /etc/default/grub/etc/grub.d/*.

/boot/grub/grub.cfg.new
그러나 구문 오류(또는 제가 생각하는 오류)가 있는 경우 원본 파일을 /boot/grub/grub.cfg덮어쓰지 않고 /boot/grub/grub.cfg.new.

오류 메시지에는 파일을 참조하는 줄 번호(내 경우에는 262)가 포함되어 있습니다 /boot/grub/grub.cfg.new. 제 경우에는 262였습니다. 내가 찾은 파일을 보면 다음과 같습니다.

### BEGIN /etc/grub.d/60_memtest86+_proxy ###
if [ "${grub_platform}" == "pc" ]; then
fi
### END /etc/grub.d/60_memtest86+_proxy ###

빈 if/then/fi 블록은 쉘 스크립트에서 허용되지 않으므로 이는 구문 오류입니다. 제 생각에는 이것은 매우 어리석은 언어 설계이지만 실제로는 그렇습니다.

또한 블록에 말도 안되는 설명을 추가하여 수정 사항을 찾았습니다. Colon이 권장되지만 다른 해결 방법이 있을 수도 있습니다.

### BEGIN /etc/grub.d/60_memtest86+_proxy ###
if [ "${grub_platform}" == "pc" ]; then
    :
fi
### END /etc/grub.d/60_memtest86+_proxy ###

더 나은 접근 방식은 이 의미 없는 블록을 완전히 제거하는 것입니다.

이제 우리는 다음 update-grub에서 변경 사항이 지워질 것이기 때문에 이 파일을 수동으로 편집하고 싶지 않습니다(성공한 경우의 목표).

/etc/grub.d/*
이 코드 조각에는 다음에 살펴볼 위치에 대한 팁이 포함되어 있습니다 /etc/grub.d/60_memtest86+_proxy. 이 문서는 다음과 같이 말합니다.

#!/bin/sh
#THIS IS A GRUB PROXY SCRIPT
'/etc/grub.d/proxifiedScripts/memtest86+' | /etc/grub.d/bin/grubcfg_proxy "+*
+#text
-'Memory Tester (memtest86+)'~30b99791e52c3f0cb32601c5b8f57cc7~
"

/etc/grub.d/proxifiedScripts/*
관련 부분은 /etc/grub.d/proxifiedScripts/memtest86+이렇습니다.

    [..]
    cat << EOF
if [ "\${grub_platform}" == "pc" ]; then
    menuentry "Memory Tester (memtest86+)" ${CLASS} {
        search --fs-uuid --no-floppy --set=root ${_GRUB_MEMTEST_HINTS_STRING} ${_GRUB_MEMTEST_FS_UUID}
        linux16 ${_GRUB_MEMTEST_REL_PATH} ${GRUB_CMDLINE_MEMTEST86}
    }
fi
EOF
[..]

파일 자체는 쉘 스크립트이지만 "cat" 문이 있습니다. 이러한 인쇄 쉘 스크립트 조각은 /boot/grub/grub.cfg약간의 수정을 거쳐 결국 작동할 것입니다.

에서는 /boot/grub/grub.cfg.new"menuentry..." 내용이 실제로 손실되고 대신 빈 then..fi 블록을 얻는 것을 관찰합니다. 왜 "메뉴 항목..."이 사라졌는지 모르겠습니다. 어쩌면 grub은 그것이 필요하다고 생각하지 않을 수도 있습니다. 불행하게도 삭제로 인해 스크립트가 손상되었습니다.

해결책

트릭/해결 방법은 다음과 같이 이 파일에 콜론을 추가하는 것입니다.

if [ "\${grub_platform}" == "pc" ]; then
    :
    menuentry "Memory Tester (memtest86+)" ${CLASS} {
        search --fs-uuid --no-floppy --set=root ${_GRUB_MEMTEST_HINTS_STRING} ${_GRUB_MEMTEST_FS_UUID}
        linux16 ${_GRUB_MEMTEST_REL_PATH} ${GRUB_CMDLINE_MEMTEST86}
    }

grub.cfgupdate-grub을 실행하면 위의 해결 방법이 포함된 파일이 생성됩니다 .

배경/추가 조사

내 시스템의 폴더에는 /etc/grub.d/실제로 memtest86+_proxy: 60_memtest86+_proxy62_memtest86+_proxy. 하지만 모두 동일한 업데이트 타임스탬프를 갖고 있기 때문에 어느 항목을 삭제해도 안전한지 잘 모르겠습니다. 차이점은 다음과 같습니다.

--- /etc/grub.d/60_memtest86+_proxy 2015-01-08 15:54:02.228927526 +0100
+++ /etc/grub.d/62_memtest86+_proxy 2015-01-08 15:54:02.228927526 +0100
@@ -1,6 +1,6 @@
 #!/bin/sh
 #THIS IS A GRUB PROXY SCRIPT
-'/etc/grub.d/proxifiedScripts/memtest86+' | /etc/grub.d/bin/grubcfg_proxy "+*
-+#text
--'Memory Tester (memtest86+)'~30b99791e52c3f0cb32601c5b8f57cc7~
+'/etc/grub.d/proxifiedScripts/memtest86+' | /etc/grub.d/bin/grubcfg_proxy "+'Memory Tester (memtest86+)'~30b99791e52c3f0cb32601c5b8f57cc7~
+-*
+-#text
 "
\ No newline at end of file

따라서 두 파일 모두 동일한 프록시 스크립트를 참조하지만 결과는 다른 매개변수를 사용하여 grubcfg_proxy 바이너리를 통해 파이프됩니다. 이러한 다양한 매개변수가 60_memtest86+_proxy.

결론적으로

다른 사람들에게는 완전히 다른 문제가 있을 수 있습니다. 그러나 적어도 첫 번째 단계의 문제 해결은 매우 유사해야 합니다.

답변2

@donquixote의 탁월한 문제 해결 단계(+1 찬성)

제 경우에는 Windows/Ubuntu 듀얼 부팅에 대한 재정렬 메뉴 옵션을 설정할 때 Ubuntu에 대한 부팅/파티션을 설정하지 않았기 때문에 오류가 발생했습니다.

나에게 도움이 된 것은 grub-customizer 메뉴의 목록에서 메뉴 옵션을 위아래로 이동하고 id 구문 오류 변경의 줄 번호를 관찰하는 것이었습니다. 그렇게 하면 옵션에 추가 주의가 필요하다는 것을 알 수 있습니다.

답변3

정말 도움이 되었습니다.

제 경우에는 그 파일이었습니다/etc/grub.d/proxifiedScripts/custom

grub-customizer루트 경로의 디렉터리에서 Prime OS를 부팅하기 위한 사용자 정의 스크립트를 생성하려고 합니다 .

파일을 삭제하고 명령이 update-grub오류 없이 완료된 다음 다음을 사용하여 사용자 정의 스크립트를 다시 생성했는데 grub-customizer제대로 실행되었습니다.

답변4

사용자님, 저는 일반 리눅스 초보자인데 날이 갈수록 강해지고 있습니다. 아직 몇 가지 새로운 명령을 배우고 있지만 곧 Linux에 익숙해질 것입니다.

귀하의 질문과 제공된 답변에 따르면 문제가 해결되었음에 틀림없지만 이에 대한 의견은 계속 말씀드리겠습니다.

인터넷의 일부 출처에 따르면 이전 Kali 커널을 제거(퍼지)할 때도 이 문제에 직면했기 때문에 이러한 방법을 모두 시도했지만 그 중 어느 것도 내 문제를 해결하지 못했습니다.

나는 내 자신의 Linux 지식을 사용하여 짜잔! 해결책을 찾았습니다. "update-grub"을 실행할 때마다 다음과 같은 결과가 나타납니다. https://im.ge/i/9MH08 그런 다음 /boot/grub/grub.cfg.new를 확인했는데 오류 줄이 260이었으므로 먼저 터미널에서 해당 작업을 수행했습니다.

nano /boot/grub/grub.cfg.new 그런 다음 Ctrl</kbd+Shift</kbd+_잘못된 줄 번호를 누르고 입력했습니다(제 것은 260이었습니다).

오류가 발생하는 메뉴 항목이 있지만 문제가 무엇인지 알 수 없습니다. 전체 메뉴 항목을 제거하고 "update-grub"을 실행했지만 grub 구성 파일은 읽기 전용이므로 변경 사항이 적용되지 않았습니다.

다시 한 번 소식통에 따르면 "update-grub" 중에 원본 grub.cfg는 변경되지 않았지만 새 grub.cfg.new가 생성되므로 원본 내용이 포함되지 않은 grub.cfg(너무 읽기 전용입니다.)가 표시됩니다. 오류나 메뉴 항목이 있으므로 모든 줄이나 오류에 대해 이 솔루션은 100% 작동합니다.

루트가 아닌 터미널 사용자를 시작하십시오. 먼저 실행한 sudo su다음 솔루션으로 이동하십시오. 루트 사용자: 솔루션으로 직접 이동하십시오.

  1. 다음을 통해 grub.cfg.new 파일을 삭제했습니다(완전히 백업은 아님).

    mv /boot/grub/grub.cfg.new /home/grub.cfg.new.bak

  2. 그런 다음 원래 grub.cfg를 grub.cfg.new로 교체했습니다.

    mv /boot/grub/grub.cfg /boot/grub/grub.cfg.new

새 항목이 "/home" 디렉터리에 백업되고 "/boot/grub/" 디렉터리에서 제거되었으므로 이전 항목이 새 항목으로 대체됩니다.

  1. 그런 다음 터미널에서 "update-grub"을 실행하고 다음을 얻습니다. https://im.ge/i/9QnRx

누구나 이 간단한 솔루션을 시도해 볼 수 있습니다.

관련 정보