Bash 쉘 스크립트: apt-get 업데이트가 실패했지만 종료 상태는 0, 종료 상태를 활용하여 자동 업데이트 스크립트 작성

Bash 쉘 스크립트: apt-get 업데이트가 실패했지만 종료 상태는 0, 종료 상태를 활용하여 자동 업데이트 스크립트 작성

자동 업데이트 및 업그레이드 스크립트를 작성하려고 합니다.

명령 실행의 종료 상태를 활용하고 싶습니다.

그러나 apt-get update 명령이 실패하더라도 종료 상태 0을 반환합니다.

그래서 내 스크립트는 목적을 달성할 수 없습니다.

질문===========

apt-get update가 0을 반환하는 이유는 무엇입니까? 그런데 명령이 실패하면 0이 아닌 다른 숫자를 얻고 싶습니까?

그리고 내 스크립트가 목적을 달성하도록 하려면 어떻게 수정해야 합니까?

======================

읽어주셔서 감사합니다!

내 스크립트의 업데이트 부분은 다음과 같습니다.

#!/bin/bash -x 

### Variables
count=
command_result=""

### Main

echo "$(LC_TIME=en_US.UTF-8 date)" >> log_update

until [ "$count" = "10" ] || [ "$command_result" = "done" ]; do

    sudo apt-get update

    if [ "$?" = "0" ]; then
        echo "Update succeeds." >> ~/log_update
        command_result="done"
    fi

    count=$((count + 1)) 

done

if [ "$command" != "done" ]; then
    echo "Time Out: Update FAILED! Solve Problem." >> log_update
fi

답변1

apt오류가 발생 하더라도 0을 반환하는 이유를 이해하려면 apt-get먼저 이 명령도 일부 프로그래머가 개발한 프로그램이라는 점을 알아야 합니다. 따라서 터미널에 반환되는 값 역시 프로그램 개발자가 결정합니다.

내가 본 유일한 경우는 슈퍼유저 권한 없이 apt실행될 때입니다 sudo
. 다음은 apt가 슈퍼유저 권한 없이 실행될 때의 스니펫입니다.

mars@HP-Notebook:~/Desktop/Practice/cpp$ apt update
Reading package lists... Done
E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
E: Unable to lock directory /var/lib/apt/lists/
W: Problem unlinking the file /var/cache/apt/pkgcache.bin - RemoveCaches (13: Permission denied)
W: Problem unlinking the file /var/cache/apt/srcpkgcache.bin - RemoveCaches (13: Permission denied)
mars@HP-Notebook:~/Desktop/Practice/cpp$ echo $?
100

보시다시피 종료 코드는 0이 아닙니다. 따라서 명령이나 프로그램이 실행되지 않았다고 결론을 내릴 수 있습니다.
인터넷에 연결되어 있지 않은 경우를 다른 경우로 들어보겠습니다.

mars@HP-Notebook:~/Desktop/Practice/cpp$ sudo apt update
Err:1 http://security.ubuntu.com/ubuntu bionic-security InRelease
  Could not resolve 'security.ubuntu.com'
Err:2 http://dl.google.com/linux/chrome/deb stable InRelease                                                   
  Could not resolve 'dl.google.com'
Err:3 http://in.archive.ubuntu.com/ubuntu bionic InRelease                                                     
  Could not resolve 'in.archive.ubuntu.com'
Err:4 https://download.sublimetext.com apt/stable/ InRelease                     
  Could not resolve 'download.sublimetext.com'
Err:5 http://in.archive.ubuntu.com/ubuntu bionic-updates InRelease
  Could not resolve 'in.archive.ubuntu.com'
Err:6 http://in.archive.ubuntu.com/ubuntu bionic-backports InRelease
  Could not resolve 'in.archive.ubuntu.com'
Reading package lists... Done
Building dependency tree       
Reading state information... Done
All packages are up to date.
W: Failed to fetch http://in.archive.ubuntu.com/ubuntu/dists/bionic/InRelease  Could not resolve 'in.archive.ubuntu.com'
W: Failed to fetch http://in.archive.ubuntu.com/ubuntu/dists/bionic-updates/InRelease  Could not resolve 'in.archive.ubuntu.com'
W: Failed to fetch http://in.archive.ubuntu.com/ubuntu/dists/bionic-backports/InRelease  Could not resolve 'in.archive.ubuntu.com'
W: Failed to fetch http://security.ubuntu.com/ubuntu/dists/bionic-security/InRelease  Could not resolve 'security.ubuntu.com'
W: Failed to fetch https://download.sublimetext.com/apt/stable/InRelease  Could not resolve 'download.sublimetext.com'
W: Failed to fetch http://dl.google.com/linux/chrome/deb/dists/stable/InRelease  Could not resolve 'dl.google.com'
W: Some index files failed to download. They have been ignored, or old ones used instead.
mars@HP-Notebook:~/Desktop/Practice/cpp$ echo $?
0

보시다시피 오류가 발생하더라도 종료 코드는 0입니다. 그 이유는 프로그램이나 명령이 성공적으로 실행되었기 때문입니다. 그러나 업그레이드가 필요한 패키지의 업그레이드에 대한 패키지 목록을 업데이트할 수 없습니다.

이에 대한 유일한 설명은 명령 개발자가 apt패키지 목록 업데이트 실패를 명령 자체를 중지하고 오류 종료 상태 코드를 반환하는 오류로 간주하지 않았다는 것입니다. 대신 명령은 실행 후 경고를 제공합니다.

더 나은 이해를 돕기 위해 C 프로그램의 예를 들어 보겠습니다.

#include<stdio.h>

int main(int argc, char *argv[]) {
    if(argc==2) 
        printf("Welcome Master %s\n", argv[1]);
    else {
        fprintf(stderr, "Usage : %s <name>\n", argv[0]);
        return 1;
    }
    return 0;
}

산출:

mars@HP-Notebook:~/Desktop/Practice/cpp$ ./batman
Usage : ./batman <name>
mars@HP-Notebook:~/Desktop/Practice/cpp$ echo $?
1
mars@HP-Notebook:~/Desktop/Practice/cpp$ ./batman Bruce
Welcome Master Bruce
mars@HP-Notebook:~/Desktop/Practice/cpp$ echo $?
0

보시다시피 두 가지 다른 종료 상태 코드가 있습니다. 프로그래머로서 저는 인수 없이 실행된 명령은 오류이므로 종료 코드 "1"로 종료되어야 한다고 생각했기 때문입니다. (어떤 값이든 선택할 수 있습니다). 그리고 명령이 성공적으로 실행되면 오류가 발생하지 않았음을 나타내는 종료 상태 코드로 "0"을 반환했습니다.

또 다른 예를 들어보겠습니다.

#include<stdio.h>

int main(int argc, char *argv[]) {
    if(argc==2) 
        printf("Welcome Master %s\n", argv[1]);
    else
        printf("ERROR!!\nUsage : %s <name>\n", argv[0]);

    return 0;
}

산출:

mars@HP-Notebook:~/Desktop/Practice/cpp$ ./batman_error 
ERROR!!
Usage : ./batman_error <name>
mars@HP-Notebook:~/Desktop/Practice/cpp$ echo $?
0
mars@HP-Notebook:~/Desktop/Practice/cpp$ ./batman_error Bruce
Welcome Master Bruce
mars@HP-Notebook:~/Desktop/Practice/cpp$ echo $?
0

다시 동일한 프로그램이지만 이번에는 프로그래머(예: 나)가 다른 종료 상태 코드로 프로그램을 종료하는 것을 고려하지 않았습니다. 따라서 터미널이 오류 출력을 인쇄하더라도 종료 상태 코드는 "0"입니다.

결론

상황에 따라 어떤 값을 반환할지(예: 종료 상태 코드)는 프로그램 개발자에게 달려 있습니다.
이것이 종료 상태 코드의 개념을 명확하게 해주기를 바랍니다.

Bash 스크립트에 대한 제안

apt update성공적으로 실행되지 않은 경우 명령을 10번 실행하려고 시도하는 루프를 사용하고 있는 것을 확인했습니다 . 솔직히 말해서 처음에 작동하지 않았다면 다음 9번도 작동하지 않을 것입니다. 따라서 루프를 만드는 것은 의미가 없습니다.

이제 오류를 확인하려면 중첩된 if-else 조건을 사용하세요. 첫 번째 수준에서 상태 코드를 확인하고 apt두 번째 수준(예: 종료 코드 "0")에서 실행 시 오류를 확인하려면 다음과 같이 사용할 수 있습니다.

sudo apt update | grep "Err"

한 줄을 가져올 수 있으면 grep이를 로그 파일에 오류로 저장하고 그렇지 않으면 업데이트가 성공한 것입니다.

답변2

apt-get update가 0을 반환하는 이유는 무엇입니까? 그런데 명령이 실패하면 0이 아닌 다른 숫자를 얻고 싶습니까?

apt는 일시적인 네트워크 오류를 0이 아닌 종료 코드를 발생시키지 않는 경고(오류 아님)로 간주합니다. 보다이 소스 코드.

그리고 내 스크립트가 목적을 달성하도록 하려면 어떻게 수정해야 합니까?

위에 링크된 소스 코드에서 조건부( errorMode != ErrorMode::Any)에 또 다른 절이 있는 것을 볼 수 있습니다. 경고를 오류로 처리하려면 다음을 시도하십시오.

# apt -o 'APT::Update::Error-Mode=any' update

이로 인해 경고를 오류로 처리하기 쉽습니다. 일시적인 네트워크 오류로 인해 apt가 0이 아닌 상태로 종료됩니다.

원하는 경우 대신 apt conf에 이를 추가할 수 있습니다.

관련 정보