Bash Shell Scripts: Embora o apt-get update tenha falhado, o status de saída é 0, escrevendo scripts de atualização automática utilizando o Exit Staus

Bash Shell Scripts: Embora o apt-get update tenha falhado, o status de saída é 0, escrevendo scripts de atualização automática utilizando o Exit Staus

Estou tentando escrever um script de atualização e atualização automática.

Quero utilizar o status de saída da execução do comando,

mas mesmo que o comando apt-get update falhe, ele retornará o status de saída 0.

Portanto, meu script não consegue atingir o propósito.

PERGUNTAS ===========

Por que o apt-get update retorna 0, quero obter outros números em vez de 0 quando o comando falha?

E para que meu script atinja o objetivo, como posso modificá-lo?

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

Obrigado pela sua leitura!

Aqui está a parte de atualização do meu script;

#!/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

Responder1

Para entender por que aptor apt-getretorna 0, mesmo quando você encontra um erro, primeiro você deve saber que esses comandos também são um programa desenvolvido por algum programador. Assim, os valores retornados ao terminal também são decididos pelo desenvolvedor do programa.

O único caso em que não vi aptfuncionar é quando ele é executado sem. sudo
Aqui está um trecho quando o apt é executado sem privilégio de superusuário:

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

Como você pode ver que o código de saída não é 0. Portanto, podemos concluir que o comando ou programa não foi executado.
Vejamos outro caso, quando não há conexão com a internet:

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

Como você pode ver, o código de saída é 0, embora tenhamos encontrado um erro. A razão para isso é que o programa ou comando foi executado com êxito. No entanto, não foi possível atualizar as listas de pacotes para atualizações de pacotes que precisam de atualização.

A única explicação para isso é que o desenvolvedor do aptcomando não considerou a falha na atualização da lista de pacotes como um erro para interromper o comando em si e retornar um código de status de saída de erro. Em vez disso, o comando fornece avisos após a execução.

Para entender melhor vou dar um exemplo de programa 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;
}

Saída:

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

Como você pode ver, existem 2 códigos de status de saída diferentes, porque como programador considerei que o comando executado sem nenhum argumento é um erro e deve ser finalizado com o código de saída "1". (eu poderia escolher qualquer valor). E se o comando for executado com sucesso, retornei "0" como código de status de saída, o que significa que nenhum erro foi encontrado.

Vamos dar outro exemplo:

#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;
}

Saída:

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

Novamente o mesmo programa, mas desta vez o programador (ou seja, eu) não considerou encerrar o programa com um código de status de saída diferente. Portanto, mesmo que o terminal imprima uma saída Error, o código de status de saída é "0".

Conclusão

Cabe ao desenvolvedor do programa qual valor retornar (ou seja, código de status de saída) dependendo da situação.
Espero que isso esclareça o conceito de código de status de saída.

Sugestão no seu script bash

Vi que você está usando um loop que tentará executar apt updateo comando 10 vezes se não for executado com sucesso. Para ser honesto, se não funcionou na primeira vez, não funcionará nas próximas 9 vezes também. Portanto, criar um loop é simplesmente inútil.

Agora, se você quiser verificar se há um erro, use condições if-else aninhadas. Você pode verificar o código de status no primeiro nível e para verificar se há erros na execução do aptsegundo nível (ou seja, com o código de saída "0"), você pode usar algo como:

sudo apt update | grep "Err"

se grepfoi possível buscar uma linha, armazene-a como um erro em seu arquivo de log, caso contrário, a atualização foi bem-sucedida.

Responder2

Por que o apt-get update retorna 0, quero obter outros números em vez de 0 quando o comando falha?

O apt considera erros transitórios de rede como avisos (não erros) que não causam um código de saída diferente de zero. Vereste código fonte.

E para que meu script atinja o objetivo, como posso modificá-lo?

No código-fonte vinculado acima, você notará outra cláusula na condicional ( errorMode != ErrorMode::Any). Para tratar avisos como erros, tente:

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

Isso fará com que o apt trate os avisos como erros. Erros transitórios de rede farão com que o apt saia diferente de zero.

Você pode adicionar isso ao apt conf, se desejar.

informação relacionada