]> git.saurik.com Git - apt.git/blame - debian/apt.cron.daily
merged from debian
[apt.git] / debian / apt.cron.daily
CommitLineData
0c132682
MZ
1#!/bin/sh
2#
0c132682
MZ
3
4#set -e
8a139d4d
MV
5#
6# This file understands the following apt configuration variables:
7#
8# "APT::Periodic::Update-Package-Lists=1"
9# - Do "apt-get update" automatically every n-days (0=disable)
10#
11# "APT::Periodic::Download-Upgradeable-Packages=0",
12# - Do "apt-get upgrade --download-only" every n-days (0=disable)
13#
14# "APT::Periodic::AutocleanInterval"
15# - Do "apt-get autoclean" every n-days (0=disable)
16#
fdd15654
MV
17# "APT::Periodic::Unattended-Upgrade"
18# - Run the "unattended-upgrade" security upgrade script
19# every n-days (0=disabled)
20# Requires the package "unattended-upgrades" and will write
21# a log in /var/log/unattended-upgrades
22#
8a139d4d
MV
23# "APT::Archives::MaxAge",
24# - Set maximum allowed age of a cache package file. If a cache
25# package file is older it is deleted (0=disable)
26#
27# "APT::Archives::MaxSize",
28# - Set maximum size of the cache in MB (0=disable). If the cache
29# is bigger, cached package files are deleted until the size
30# requirement is met (the biggest packages will be deleted
31# first).
32#
33# "APT::Archives::MinAge"
34# - Set minimum age of a package file. If a file is younger it
35# will not be deleted (0=disable). Usefull to prevent races
36# and to keep backups of the packages for emergency.
37#
0c132682 38
05f6a46a 39check_stamp()
0c132682 40{
05f6a46a
MZ
41 stamp="$1"
42 interval="$2"
43
10946ddc 44 if [ $interval -eq 0 ]; then
53391d0f 45 debug_echo "check_stamp: interval=0"
ff7c76f8 46 # treat as no time has passed
10946ddc
MZ
47 return 1
48 fi
49
05f6a46a 50 if [ ! -f $stamp ]; then
ff7c76f8
OA
51 debug_echo "check_stamp: missing time stamp file: $stamp."
52 # treat as enough time has passed
05f6a46a 53 return 0
0c132682 54 fi
05f6a46a
MZ
55
56 # compare midnight today to midnight the day the stamp was updated
9c2d35fa
MV
57 stamp_file="$stamp"
58 stamp=$(date --date=$(date -r $stamp_file --iso-8601) +%s 2>/dev/null)
59 if [ "$?" != "0" ]; then
60 # Due to some timezones returning 'invalid date' for midnight on
61 # certain dates (eg America/Sao_Paulo), if date returns with error
62 # remove the stamp file and return 0. See coreutils bug:
63 # http://lists.gnu.org/archive/html/bug-coreutils/2007-09/msg00176.html
64 rm -f "$stamp_file"
65 return 0
66 fi
67
68 now=$(date --date=$(date --iso-8601) +%s 2>/dev/null)
69 if [ "$?" != "0" ]; then
70 # As above, due to some timezones returning 'invalid date' for midnight
71 # on certain dates (eg America/Sao_Paulo), if date returns with error
72 # return 0.
73 return 0
74 fi
75
05f6a46a 76 delta=$(($now-$stamp))
05f6a46a 77
8a139d4d
MV
78 # intervall is in days,
79 interval=$(($interval*60*60*24))
80 #echo "stampfile: $1"
81 #echo "interval=$interval, now=$now, stamp=$stamp, delta=$delta"
82
adbce121
MV
83 # remove timestamps a day (or more) in the future and force re-check
84 if [ $stamp -gt $(($now+86400)) ]; then
85 echo "WARNING: file $stamp_file has a timestamp in the future: $stamp"
86 rm -f "$stamp_file"
87 return 0
88 fi
89
6e7c6c3f
MV
90 # remove timestamps a day (or more) in the future and force re-check
91 if [ $stamp -gt $(($now+86400)) ]; then
92 echo "WARNING: file $stamp_file has a timestamp in the future: $stamp"
93 rm -f "$stamp_file"
94 return 0
95 fi
96
05f6a46a
MZ
97 if [ $delta -ge $interval ]; then
98 return 0
99 fi
100
101 return 1
102}
103
104update_stamp()
105{
106 stamp="$1"
107
108 touch $stamp
0c132682
MZ
109}
110
6cce801a 111# we check here if autoclean was enough sizewise
2e8a92e5 112check_size_constraints()
6cce801a 113{
6cce801a 114 MaxAge=0
6cce801a 115 eval $(apt-config shell MaxAge APT::Archives::MaxAge)
c98870b0
MV
116 eval $(apt-config shell MaxAge APT::Periodic::MaxAge)
117
118 MinAge=2
8a139d4d 119 eval $(apt-config shell MinAge APT::Archives::MinAge)
c98870b0
MV
120 eval $(apt-config shell MinAge APT::Periodic::MinAge)
121
122 MaxSize=0
6cce801a 123 eval $(apt-config shell MaxSize APT::Archives::MaxSize)
c98870b0
MV
124 eval $(apt-config shell MaxSize APT::Periodic::MaxSize)
125
126 CacheDir="var/cache/apt/"
6cce801a 127 eval $(apt-config shell CacheDir Dir::Cache)
c98870b0
MV
128 CacheDir=${CacheDir%/}
129
130 CacheArchive="archives/"
6cce801a 131 eval $(apt-config shell CacheArchive Dir::Cache::archives)
c98870b0 132 CacheArchive=${CacheArchive%/}
6cce801a
MV
133
134 # sanity check
135 if [ -z "$CacheDir" -o -z "$CacheArchive" ]; then
136 echo "empty Dir::Cache or Dir::Cache::archives, exiting"
137 exit
138 fi
01717245
MV
139
140 Cache="${Dir%/}/${CacheDir%/}/${CacheArchive%/}/"
6cce801a
MV
141
142 # check age
8a139d4d 143 if [ ! $MaxAge -eq 0 ] && [ ! $MinAge -eq 0 ]; then
c98870b0 144 debug_echo "aged: ctime <$MaxAge and mtime <$MaxAge and ctime>$MinAge and mtime>$MinAge"
8e29e348 145 find $Cache -name "*.deb" \( -mtime +$MaxAge -and -ctime +$MaxAge \) -and -not \( -mtime -$MinAge -or -ctime -$MinAge \) -print0 | xargs -r -0 rm -f
8a139d4d 146 elif [ ! $MaxAge -eq 0 ]; then
c98870b0 147 debug_echo "aged: ctime <$MaxAge and mtime <$MaxAge only"
8e29e348 148 find $Cache -name "*.deb" -ctime +$MaxAge -and -mtime +$MaxAge -print0 | xargs -r -0 rm -f
c98870b0
MV
149 else
150 debug_echo "skip aging since MaxAge is 0"
6cce801a
MV
151 fi
152
153 # check size
154 if [ ! $MaxSize -eq 0 ]; then
8a139d4d
MV
155 # maxSize is in MB
156 MaxSize=$(($MaxSize*1024))
157
158 #get current time
159 now=$(date --date=$(date --iso-8601) +%s)
160 MinAge=$(($MinAge*24*60*60))
161
6cce801a 162 # reverse-sort by mtime
3408b58c 163 for file in $(ls -rt $Cache/*.deb 2>/dev/null); do
6cce801a
MV
164 du=$(du -s $Cache)
165 size=${du%%/*}
166 # check if the cache is small enough
167 if [ $size -lt $MaxSize ]; then
c98870b0 168 debug_echo "end remove by archive size: size=$size < $MaxSize"
6cce801a
MV
169 break
170 fi
8a139d4d
MV
171
172 # check for MinAge of the file
c98870b0 173 if [ $MinAge -ne 0 ]; then
8e29e348 174 # check both ctime and mtime
3971f8e8 175 mtime=$(stat -c %Y $file)
8e29e348
MV
176 ctime=$(stat -c %Z $file)
177 if [ $mtime -gt $ctime ]; then
178 delta=$(($now-$mtime))
179 else
180 delta=$(($now-$ctime))
181 fi
8a139d4d 182 if [ $delta -le $MinAge ]; then
c98870b0 183 debug_echo "skip remove by archive size: $file, delta=$delta < $MinAgeSec"
3408b58c 184 break
c98870b0
MV
185 else
186 # delete oldest file
187 debug_echo "remove by archive size: $file, delta=$delta >= $MinAgeSec (sec), size=$size >= $MaxSize"
188 rm -f $file
8a139d4d
MV
189 fi
190 fi
6cce801a
MV
191 done
192 fi
193}
194
c98870b0
MV
195# deal with the Apt::Periodic::BackupArchiveInterval
196do_cache_backup()
197{
198 BackupArchiveInterval="$1"
199 if [ $BackupArchiveInterval -eq 0 ]; then
200 return
201 fi
202
203 # Set default values and normalize
204 Dir="/"
205 eval $(apt-config shell Dir Dir)
206 Dir=${Dir%/}
207
208 CacheDir="var/cache/apt/"
209 eval $(apt-config shell CacheDir Dir::Cache)
210 CacheDir=${CacheDir%/}
211 if [ -z "$CacheDir" ]; then
212 debug_echo "practically empty Dir::Cache, exiting"
213 return 0
214 fi
215
216 CacheArchive="archives/"
217 eval $(apt-config shell CacheArchive Dir::Cache::Archives)
218 CacheArchive=${CacheArchive%/}
219 if [ -z "$CacheArchive" ]; then
220 debug_echo "practically empty Dir::Cache::archives, exiting"
221 return 0
222 fi
223
224 BackupLevel=3
225 eval $(apt-config shell BackupLevel APT::Periodic::BackupLevel)
226 if [ $BackupLevel -le 1 ]; then
227 BackupLevel=2 ;
228 fi
229
230 CacheBackup="backup/"
231 eval $(apt-config shell CacheBackup Dir::Cache::Backup)
232 CacheBackup=${CacheBackup%/}
233 if [ -z "$CacheBackup" ]; then
234 echo "practically empty Dir::Cache::Backup, exiting" 1>&2
235 return
236 fi
237
238 Cache="${Dir}/${CacheDir}/${CacheArchive}/"
239 Back="${Dir}/${CacheDir}/${CacheBackup}/"
240 BackX="${Back}${CacheArchive}/"
241 for x in $(seq 0 1 $((${BackupLevel}-1))); do
242 eval "Back${x}=${Back}${x}/"
243 done
244
245 # backup after n-days if archive contents changed.
246 # (This uses hardlink to save disk space)
247 BACKUP_ARCHIVE_STAMP=/var/lib/apt/periodic/backup-archive-stamp
248 if check_stamp $BACKUP_ARCHIVE_STAMP $BackupArchiveInterval; then
249 if [ $({(cd $Cache 2>/dev/null; find . -name "*.deb"); (cd $Back0 2>/dev/null;find . -name "*.deb") ;}| sort|uniq -u|wc -l) -ne 0 ]; then
250 mkdir -p $Back
251 rm -rf $Back$((${BackupLevel}-1))
252 for y in $(seq $((${BackupLevel}-1)) -1 1); do
253 eval BackY=${Back}$y
254 eval BackZ=${Back}$(($y-1))
255 if [ -e $BackZ ]; then
256 mv -f $BackZ $BackY ;
257 fi
258 done
259 cp -la $Cache $Back ; mv -f $BackX $Back0
260 update_stamp $BACKUP_ARCHIVE_STAMP
261 debug_echo "backup with hardlinks. (success)"
262 else
263 debug_echo "skip backup since same content."
264 fi
265 else
266 debug_echo "skip backup since too new."
267 fi
268}
269
d047c6da 270# sleep for a random interval of time (default 30min)
604c9ee8
MV
271# (some code taken from cron-apt, thanks)
272random_sleep()
273{
274 RandomSleep=1800
275 eval $(apt-config shell RandomSleep APT::Periodic::RandomSleep)
276 if [ $RandomSleep -eq 0 ]; then
277 return
278 fi
279 if [ -z "$RANDOM" ] ; then
280 # A fix for shells that do not have this bash feature.
281 RANDOM=$(dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -c"1-5")
282 fi
283 TIME=$(($RANDOM % $RandomSleep))
c98870b0 284 debug_echo "sleeping for $TIME seconds"
604c9ee8
MV
285 sleep $TIME
286}
287
604c9ee8 288
ff7c76f8 289debug_echo()
6cce801a 290{
ff7c76f8
OA
291 # Display message if $VERBOSE >= 1
292 if [ "$VERBOSE" -ge 1 ]; then
293 echo $1 1>&2
6cce801a 294 fi
ff7c76f8
OA
295}
296
c98870b0 297# ------------------------ main ----------------------------
69c28efc 298
ff7c76f8
OA
299# check apt-config exstance
300if ! which apt-config >/dev/null ; then
18d38975
OS
301 exit 0
302fi
87ddfb96 303
ff7c76f8
OA
304# Set VERBOSE mode from apt-config (or inherit from environment)
305eval $(apt-config shell VERBOSE APT::Periodic::Verbose)
c98870b0 306debug_echo "verbose level $VERBOSE"
ff7c76f8
OA
307if [ -z "$VERBOSE" ]; then
308 VERBOSE="0"
309fi
310if [ "$VERBOSE" -le 2 ]; then
311 # quiet for 0,1,2
312 XSTDOUT=">/dev/null"
313 XSTDERR="2>/dev/null"
314 XAPTOPT="-qq"
315 XUUPOPT=""
316else
317 XSTDOUT=""
318 XSTDERR=""
319 XAPTOPT=""
320 XUUPOPT="-d"
321fi
322if [ "$VERBOSE" -ge 3 ]; then
323 # trace output
324 set -x
325fi
8a139d4d 326
ff7c76f8
OA
327# laptop check, on_ac_power returns:
328# 0 (true) System is on main power
329# 1 (false) System is not on main power
330# 255 (false) Power status could not be determined
331# Desktop systems always return 255 it seems
332if which on_ac_power >/dev/null; then
333 on_ac_power
334 POWER=$?
335 if [ $POWER -eq 1 ]; then
c98870b0 336 debug_echo "exit: system NOT on main power"
18d38975 337 exit 0
ff7c76f8 338 elif [ $POWER -ne 0 ]; then
c98870b0 339 debug_echo "power status ($POWER) undetermined, continuing"
6cce801a 340 fi
ff7c76f8
OA
341 debug_echo "system is on main power."
342fi
8a139d4d 343
ff7c76f8 344# check if we can lock the cache and if the cache is clean
aff278bf 345if which apt-get >/dev/null && ! eval apt-get check -f $XAPTOPT $XSTDERR ; then
ff7c76f8
OA
346 debug_echo "error encountered in cron job with \"apt-get check\"."
347 exit 0
18d38975 348fi
87ddfb96 349
ff7c76f8
OA
350# Global current time in seconds since 1970-01-01 00:00:00 UTC
351now=$(date +%s)
6cce801a 352
ff7c76f8
OA
353# Support old Archive for compatibility.
354# Document only Periodic for all controling parameters of this script.
ff7c76f8 355
0c132682 356UpdateInterval=0
05f6a46a 357DownloadUpgradeableInterval=0
9bd1cf87
MZ
358eval $(apt-config shell UpdateInterval APT::Periodic::Update-Package-Lists DownloadUpgradeableInterval APT::Periodic::Download-Upgradeable-Packages)
359AutocleanInterval=$DownloadUpgradeableInterval
0eb7056b 360eval $(apt-config shell AutocleanInterval APT::Periodic::AutocleanInterval)
fdd15654
MV
361UnattendedUpgradeInterval=0
362eval $(apt-config shell UnattendedUpgradeInterval APT::Periodic::Unattended-Upgrade)
363
ff7c76f8
OA
364AutocleanInterval=0
365eval $(apt-config shell AutocleanInterval APT::Periodic::AutocleanInterval)
366
c98870b0
MV
367BackupArchiveInterval=0
368eval $(apt-config shell BackupArchiveInterval APT::Periodic::BackupArchiveInterval)
ff7c76f8 369
5f71505b
MV
370# check if we actually have to do anything
371if [ $UpdateInterval -eq 0 ] &&
372 [ $DownloadUpgradeableInterval -eq 0 ] &&
373 [ $UnattendedUpgradeInterval -eq 0 ] &&
374 [ $AutocleanInterval -eq 0 ]; then
375 exit 0
376fi
fdd15654 377
55fb35e8
MV
378# set the proxy based on the admin users gconf settings
379admin_user=$(getent group admin|cut -d: -f4|cut -d, -f1)
380if [ -n "$admin_user" ] && [ -x /usr/bin/sudo ] && [ -z "$http_proxy" ] && [ -x /usr/bin/gconftool ]; then
381 use=$(sudo -u "$admin_user" gconftool --get /system/http_proxy/use_http_proxy 2>/dev/null)
382 host=$(sudo -u "$admin_user" gconftool --get /system/http_proxy/host 2>/dev/null)
383 port=$(sudo -u "$admin_user" gconftool --get /system/http_proxy/port 2>/dev/null)
384 if [ "$use" = "true" ] && [ -n "$host" ] && [ -n "$port" ]; then
385 export http_proxy="http://$host:$port/"
386 fi
0c132682
MZ
387fi
388
55fb35e8 389
c98870b0
MV
390# deal with BackupArchiveInterval
391do_cache_backup $BackupArchiveInterval
0c132682 392
5f71505b
MV
393# sleep random amount of time to avoid hitting the
394# mirrors at the same time
69c28efc
MV
395random_sleep
396
ff7c76f8 397# update package lists
aff278bf 398UPDATED=0
05f6a46a
MZ
399UPDATE_STAMP=/var/lib/apt/periodic/update-stamp
400if check_stamp $UPDATE_STAMP $UpdateInterval; then
2ce23a2a 401 # check for a new archive signing key (against the master keyring)
55fb35e8
MV
402 if eval apt-key net-update $XSTDERR; then
403 debug_echo "apt-key net-update (success)"
404 else
405 debug_echo "apt-key net-update (failure)"
406 fi
407 if eval apt-get $XAPTOPT -y update -o APT::Update::Auth-Failure::="cp /usr/share/apt/apt-auth-failure.note /var/lib/update-notifier/user.d/" $XSTDERR; then
ff7c76f8 408 debug_echo "download updated metadata (success)."
be993931 409 if which dbus-send >/dev/null && pidof dbus-daemon >/dev/null; then
ff7c76f8
OA
410 if dbus-send --system / app.apt.dbus.updated boolean:true ; then
411 debug_echo "send dbus signal (success)"
412 else
413 debug_echo "send dbus signal (error)"
414 fi
415 else
416 debug_echo "dbus signal not send (command not available)"
05f6a46a 417 fi
ff7c76f8 418 update_stamp $UPDATE_STAMP
aff278bf 419 UPDATED=1
c2d0fdd1
MV
420 # now run apt-xapian-index if it is installed to ensure the index
421 # is up-to-date
422 if [ -x /usr/sbin/update-apt-xapian-index ]; then
423 ionice -c3 update-apt-xapian-index -q
424 fi
ff7c76f8 425 else
c98870b0 426 debug_echo "download updated metadata (error)"
05f6a46a 427 fi
ff7c76f8
OA
428else
429 debug_echo "download updated metadata (not run)."
0c132682 430fi
c98870b0
MV
431
432# download all upgradeable packages (if it is requested)
05f6a46a 433DOWNLOAD_UPGRADEABLE_STAMP=/var/lib/apt/periodic/download-upgradeable-stamp
aff278bf 434if [ $UPDATED -eq 1 ] && check_stamp $DOWNLOAD_UPGRADEABLE_STAMP $DownloadUpgradeableInterval; then
c98870b0
MV
435 if eval apt-get $XAPTOPT -y -d dist-upgrade $XSTDERR; then
436 update_stamp $DOWNLOAD_UPGRADEABLE_STAMP
437 debug_echo "download upgradable (success)"
438 else
439 debug_echo "download upgradable (error)"
440 fi
441else
442 debug_echo "download upgradable (not run)"
0c132682 443fi
9bd1cf87 444
c98870b0 445# auto upgrade all upgradeable packages
fdd15654 446UPGRADE_STAMP=/var/lib/apt/periodic/upgrade-stamp
aff278bf 447if [ $UPDATED -eq 1 ] && which unattended-upgrade >/dev/null && check_stamp $UPGRADE_STAMP $UnattendedUpgradeInterval; then
c98870b0
MV
448 if unattended-upgrade $XUUPOPT; then
449 update_stamp $UPGRADE_STAMP
450 debug_echo "unattended-upgrade (success)"
451 else
452 debug_echo "unattended-upgrade (error)"
453 fi
454else
455 debug_echo "unattended-upgrade (not run)"
fdd15654
MV
456fi
457
ff7c76f8 458# autoclean package archive
de15fbae
MV
459AUTOCLEAN_STAMP=/var/lib/apt/periodic/autoclean-stamp
460if check_stamp $AUTOCLEAN_STAMP $AutocleanInterval; then
c98870b0 461 if eval apt-get $XAPTOPT -y autoclean $XSTDERR; then
ff7c76f8
OA
462 debug_echo "autoclean (success)."
463 update_stamp $AUTOCLEAN_STAMP
464 else
c98870b0 465 debug_echo "autoclean (error)"
ff7c76f8
OA
466 fi
467else
c98870b0 468 debug_echo "autoclean (not run)"
de15fbae
MV
469fi
470
47536509
MV
471# check cache size
472check_size_constraints
0fad7309 473
ff7c76f8
OA
474#
475# vim: set sts=4 ai :
476#
477