8

How check the status of apt-get update?

$ apt-get update ; echo "status is: $?"

Err http://security.debian.org stable/updates Release.gpg
Could not resolve 'security.debian.org'
Hit http://192.168.1.100 stable Release.gpg
Hit http://192.168.1.100 stable Release
Hit http://192.168.1.100 stable/main i386 Packages
Hit http://192.168.1.100 stable/contrib i386 Packages
Hit http://192.168.1.100 stable/non-free i386 Packages
Ign http://192.168.1.100 stable/contrib Translation-en
Ign http://192.168.1.100 stable/main Translation-en
Ign http://192.168.1.100 stable/non-free Translation-en
Reading package lists... Done
W: Failed to fetch http://security.debian.org/dists/stable/updates/Release.gpg  Could not resolve 'security.debian.org'
W: Some index files failed to download. They have been ignored, or old ones used instead.

status is: 0

Here there's an error with fetch of security updates but exit status is 0

My goal is a script to check if apt-get update runs correctly.

6

In your example apt-get update didn't exit with error, because it considered the problems as warnings, not as fatally bad. If there's a really fatal error, then it would exit with non-zero status.

One way to recognize anomalies is by checking for these patterns in stderr:

  • Lines starting with W: are warnings
  • Lines starting with E: are errors

You could use something like this to emulate a failure in case the above patterns match, or the exit code of apt-get update itself is non-zero:

if ! { sudo apt-get update 2>&1 || echo E: update failed; } | grep -q '^[WE]:'; then
    echo success
else
    echo failure
fi

Note the ! in the if. It's because the grep exits with success if the pattern was matched, that is if there were errors. When there are no errors the grep itself will fail. So the if condition is to negate the exit code of the grep.

1

If you want apt-get's out/err to not get eaten (e.g. if writing to a log file), this might be a simpler alternative:

sudo apt-get update 2>&1 | tee /tmp/apt.err && ! grep -q '^[WE]' /tmp/apt.err

It would be nice if this didn't leave a new file lying around to remove later, but if we, say, process substitute the grep into the tee output it seems to get more difficult to get the exit code.

0

I was faced with the same issue, and I would like to propose another solution that relies on tee (like @user4122451's solution), but doesn't create a temporary file, and also fails if sudo apt-get update returns a non-zero exit code without outputting some W: or E: or Err: string:

exec {fd}>&2 # copy stderr to some unused fd
bash -o pipefail -c "sudo apt-get update -y -q 2>&1 | tee /dev/fd/$fd | ( ! grep -q -e '^Err:' -e '^[WE]:' )"
result=$?
exec {fd}>&- # close file descriptor

Specifically, this solution relies on the set -o pipefail bash option (ensuring the pipeline returns the value of the rightmost command to exit with a non-zero status, otherwise zero) and uses an additional numbered file descriptor (see also this SO answer).

If you need not make the pipefail option local, you could write just as well:

set -o pipefail
exec {fd}>&2 # copy stderr to some unused fd
sudo apt-get update -y -q 2>&1 | tee /dev/fd/$fd | ( ! grep -q -e '^Err:' -e '^[WE]:' )
result=$?
exec {fd}>&- # close file descriptor

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.