cron 任务中的“apt-get -y upgrade”运行但不升级系统

Joh*_*nal 3 debian update cron apt

这台服务器运行 Debian 7,我面临着一个很大的谜团。

这是我的 cron 任务:

$ sudo crontab -e

42 15 * * * apt-get -y update >> /var/log/my-apt-update.txt
52 15 * * * apt-get -y upgrade >> /var/log/my-apt-upgrade.txt
Run Code Online (Sandbox Code Playgroud)

我添加了这">> /var/log/my-apt-upgrade.txt"部分是因为我试图理解为什么我的系统永远不会升级。

cron 任务运行。每天我在 /var/log/syslog 中有这些行:

Nov 14 15:42:01 myhostname /USR/SBIN/CRON[3374]: (root) CMD (apt-get -y update >> /var/log/my-apt-update.txt)
Nov 14 15:52:01 myhostname /USR/SBIN/CRON[3394]: (root) CMD (apt-get -y upgrade >> /var/log/my-apt-upgrade.txt)
Run Code Online (Sandbox Code Playgroud)

并且 /var/log/my-apt-upgrade.txt 有这样的段落(我只显示最近两天):

Reading package lists...
Building dependency tree...
Reading state information...
The following packages will be upgraded:
  file libmagic1
2 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B/256 kB of archives.
After this operation, 110 kB disk space will be freed.
Reading package lists...
Building dependency tree...
Reading state information...
The following packages will be upgraded:
  file libmagic1
2 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B/256 kB of archives.
After this operation, 110 kB disk space will be freed.
Run Code Online (Sandbox Code Playgroud)

如您所见,包“file”和“libmagic1”应该在第一天就升级了。但他们不是。所以第二天,他们又被提到了。但是没有升级。

而今天,如果我跑

$ sudo apt-get -y upgrade
Run Code Online (Sandbox Code Playgroud)

再次提到包“file”和“libmagic1”,它们得到升级(最终)。

因此,如您所见,我可以手动升级。但是这些包应该在 cron 任务运行时更早升级。

关于这个谜团有什么线索吗?

11 月 15 日星期六 11:48:

这是我的 /var/log/apt/history.log 在 cron 作业期间出现的内容。

Start-Date: 2014-11-13  15:52:03
Commandline: apt-get -y upgrade
Upgrade: file:amd64 (5.11-2+deb7u5, 5.11-2+deb7u6), libmagic1:amd64 (5.11-2+deb7u5, 5.11-2+deb7u6)
Error: Sub-process /usr/bin/dpkg returned an error code (2)
End-Date: 2014-11-13  15:52:03

Start-Date: 2014-11-14  15:52:03
Commandline: apt-get -y upgrade
Upgrade: file:amd64 (5.11-2+deb7u5, 5.11-2+deb7u6), libmagic1:amd64 (5.11-2+deb7u5, 5.11-2+deb7u6)
Error: Sub-process /usr/bin/dpkg returned an error code (2)
End-Date: 2014-11-14  15:52:03
Run Code Online (Sandbox Code Playgroud)

对于不同的包,在 /var/log/apt/history.log 中会出现相同类型的消息。例如,本月早些时候,“wget”包需要一些更新(这次我曾尝试使用 -qq 选项,但此选项似乎没有任何区别)。

Start-Date: 2014-11-03  15:52:02
Commandline: apt-get -y -qq upgrade
Upgrade: wget:amd64 (1.13.4-3+deb7u1, 1.13.4-3+deb7u2)
Error: Sub-process /usr/bin/dpkg returned an error code (2)
End-Date: 2014-11-03  15:52:02

Start-Date: 2014-11-04  15:52:02
Commandline: apt-get -y -qq upgrade
Upgrade: wget:amd64 (1.13.4-3+deb7u1, 1.13.4-3+deb7u2)
Error: Sub-process /usr/bin/dpkg returned an error code (2)
End-Date: 2014-11-04  15:52:03

Start-Date: 2014-11-05  15:52:03
Commandline: apt-get -y -qq upgrade
Upgrade: wget:amd64 (1.13.4-3+deb7u1, 1.13.4-3+deb7u2)
Error: Sub-process /usr/bin/dpkg returned an error code (2)
End-Date: 2014-11-05  15:52:03
Run Code Online (Sandbox Code Playgroud)

Joh*_*nal 7

看来我找到了问题的原因。

为了检测错误,我必须在自定义日志中捕获 stderr。事实证明这样做很有用,因为有些错误没有邮寄到 root,也没有写入其他日志。

为了在我的日志中捕获 stderr,我首先将 cron 任务更改为:

52 15 * * * apt-get -y upgrade >> /var/log/my-apt-upgrade.txt 2>&1
Run Code Online (Sandbox Code Playgroud)

今天要更新包“wlibgcrypt11”。这次,我的日志出错了。它比之前出现在 /var/log/apt/history.log 中的模糊错误消息更加明确。

今天在 /var/log/my-apt-upgrade.txt 中:

Reading package lists...
Building dependency tree...
Reading state information...
The following packages will be upgraded:
  libgcrypt11
debconf: unable to initialize frontend: Dialog
debconf: (TERM is not set, so the dialog frontend is not usable.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (This frontend requires a controlling tty.)
debconf: falling back to frontend: Teletype
dpkg-preconfigure: unable to re-open stdin: 
1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B/300 kB of archives.
After this operation, 35.8 kB of additional disk space will be used.
dpkg: warning: 'ldconfig' not found in PATH or not executable
dpkg: warning: 'start-stop-daemon' not found in PATH or not executable
dpkg: error: 2 expected programs not found in PATH or not executable
Note: root's PATH should usually contain /usr/local/sbin, /usr/sbin and /sbin
E: Sub-process /usr/bin/dpkg returned an error code (2)
Run Code Online (Sandbox Code Playgroud)

所以这是一个PATH错误。

我系统上的根路径包含所有必需的目录。visudo 中的 secure_path 变量也是如此。这就是为什么当我手动运行 sudo apt-get 时一切正常。

但是 cron 没有设置环境变量。所以我为每个 cron 任务添加了一个 PATH 环境变量。

$ sudo crontab -e

22 16 * * * PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' apt-get -y update >> /var/log/my-new-apt-update.txt 2>&1
32 16 * * * PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' apt-get -y upgrade >> /var/log/my-new-apt-upgrade.txt 2>&1
Run Code Online (Sandbox Code Playgroud)

它奏效了!该包已由 cron 任务成功更新。