Ric*_*rri 82 ubuntu systemd cloud-init
Ubuntu 16.04 服务器 VM 映像显然每 12 小时左右启动一次“apt-daily.service”;此服务执行各种与 APT 相关的任务,例如刷新可用软件包列表、在需要时执行无人值守升级等。
当从虚拟机“快照”启动时,服务会立即触发,因为(我认为)systemd 很快意识到计时器早就应该关闭了。
但是,正在运行的 APT 会阻止其他apt进程运行,因为它持有/var/lib/dpkg. 指示这的错误消息如下所示:
E: Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource temporarily unavailable)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?
Run Code Online (Sandbox Code Playgroud)
我需要禁用这个自动化的 APT 任务,直到 Ansible 完成机器设置(通常涉及安装包);有关更多信息和上下文,请参阅https://github.com/gc3-uzh-ch/elasticluster/issues/304。
我尝试了各种选项来通过“用户数据”脚本禁用“无人值守升级”功能cloud-init,但到目前为止所有这些都失败了。
systemd 任务apt-daily.service由apt-daily.timer. 我尝试使用以下命令的各种组合来禁用一个或另一个,或同时禁用两者;仍然,在apt-daily.serviceVM 准备好接受 SSH 连接后不久就启动了:
#!/bin/bash
systemctl stop apt-daily.timer
systemctl disable apt-daily.timer
systemctl mask apt-daily.service
systemctl daemon-reload
Run Code Online (Sandbox Code Playgroud)
APT::Periodic::Enable脚本/usr/lib/apt/apt.systemd.daily读取一些 APT 配置变量;该设置APT::Periodic::Enable完全禁用该功能(第 331--337 行)。我尝试使用以下脚本禁用它:
#!/bin/bash
# cannot use /etc/apt/apt.conf.d/10periodic as suggested in
# /usr/lib/apt/apt.systemd.daily, as Ubuntu distributes the
# unattended upgrades stuff with priority 20 and 50 ...
# so override everything with a 99xxx file
cat > /etc/apt/apt.conf.d/99elasticluster <<__EOF
APT::Periodic::Enable "0";
// undo what's in 20auto-upgrade
APT::Periodic::Update-Package-Lists "0";
APT::Periodic::Unattended-Upgrade "0";
__EOF
Run Code Online (Sandbox Code Playgroud)
然而,尽管APT::Periodic::Enable有0来自命令行的值(见下文),该unattended-upgrades程序仍在运行......
ubuntu@test:~$ apt-config shell AutoAptEnable APT::Periodic::Enable
AutoAptEnable='0'
Run Code Online (Sandbox Code Playgroud)
/usr/lib/apt/apt.systemd.daily完全删除以下cloud-init脚本完全删除了无人值守升级脚本:
#!/bin/bash
mv /usr/lib/apt/apt.systemd.daily /usr/lib/apt/apt.systemd.daily.DISABLED
Run Code Online (Sandbox Code Playgroud)
尽管如此,任务仍在运行,我可以在进程表中看到它!虽然如果从命令行探测该文件不存在::
ubuntu@test:~$ ls /usr/lib/apt/apt.systemd.daily
ls: cannot access '/usr/lib/apt/apt.systemd.daily': No such file or directory
Run Code Online (Sandbox Code Playgroud)
看起来cloud-init脚本(连同 SSH 命令行)和 root systemd 进程在单独的文件系统和进程空间中执行......
有什么明显的我遗漏了吗?或者是否有一些我不知道的命名空间魔法?
最重要的是:如何apt-daily.service通过
cloud-init脚本禁用?
Ric*_*rri 50
是的,我显然遗漏了一些东西。
Systemd是所有关于服务的同时启动,所以cloud-init脚本运行的同时将apt-daily.service被触发。到
cloud-init执行用户指定的有效负载时,apt-get update它已经在运行。所以尝试 2. 和 3. 失败不是因为一些命名空间魔法,而是因为他们改变系统太晚而apt.systemd.daily无法获取更改。
这也意味着基本上没有办法阻止
apt.systemd.daily运行——只有在它启动后才能杀死它。
这个“用户数据”脚本采用这条路线::
#!/bin/bash
systemctl stop apt-daily.service
systemctl kill --kill-who=all apt-daily.service
# wait until `apt-get updated` has been killed
while ! (systemctl list-units --all apt-daily.service | egrep -q '(dead|failed)')
do
sleep 1;
done
# now proceed with own APT tasks
apt install -y python
Run Code Online (Sandbox Code Playgroud)
仍然有一个时间窗口,在此期间 SSH 登录是可能的apt-get
,但不会运行,但我无法想象另一个可以在 Ubuntu 16.04 云映像上运行的解决方案。
Ano*_*non 20
注意:不幸的是,下面的部分解决方案不适用于 Ubuntu 16.04 系统(例如提问者的系统),因为建议的systemd-run调用仅适用于Ubuntu 18.04 及更高版本(有关详细信息,请参阅评论)。我会在这里留下答案,因为无论您使用的是哪个 Ubuntu 版本,这个问题仍然很受欢迎……
在 Ubuntu 18.04(及更高版本)上,启动时更新/升级可能涉及最多两个服务。第一个apt-daily.service刷新包列表。然而,可以有第二个apt-daily-upgrade.service实际安装安全关键包。“在命令返回之前终止并禁用/删除无人值守升级”问题的答案提供了一个很好的示例,说明如何等待这两个操作完成(为了方便起见,复制到此处):
systemd-run --property="After=apt-daily.service apt-daily-upgrade.service" --wait /bin/true
Run Code Online (Sandbox Code Playgroud)
(请注意,这必须以 root 身份运行)。如果您尝试在以后的启动中禁用这些服务,则需要屏蔽这两个服务:
systemctl mask apt-daily.service apt-daily-upgrade.service
Run Code Online (Sandbox Code Playgroud)
或者,您可以systemctl disable同时使用服务及其相关计时器(即apt-daily.timer和apt-daily-upgrade.timer)。
请注意,此答案中的屏蔽/禁用技术只会阻止将来启动时的更新/升级 - 如果它们已经在当前启动中运行,则不会停止它们。
您可以通过“bootcmd”cloud-init 模块禁用此功能。这在网络启动之前运行,这是 apt update 有机会运行之前所必需的。
#cloud-config
bootcmd:
- echo 'APT::Periodic::Enable "0";' > /etc/apt/apt.conf.d/10cloudinit-disable
- apt-get -y purge update-notifier-common ubuntu-release-upgrader-core landscape-common unattended-upgrades
- echo "Removed APT and Ubuntu 18.04 garbage early" | systemd-cat
Run Code Online (Sandbox Code Playgroud)
一旦您通过 ssh 进入实例,您还应该等待 cloud-init 的最后阶段完成,因为它会移动 apt 源/列表。
# Wait for cloud-init to finish moving apt sources.list around...
# a good source of random failures
# Note this is NOT a replacement for also disabling apt updates via bootcmd
while [ ! -f /var/lib/cloud/instance/boot-finished ]; do
echo 'Waiting for cloud-init to finish...'
sleep 3
done
Run Code Online (Sandbox Code Playgroud)
这也有助于了解 bootcmd 运行的时间:
# Show microseconds in systemd journal
journalctl -r -o short-precise
Run Code Online (Sandbox Code Playgroud)
您可以按如下方式验证这是否有效:
apt-config dump | grep Periodic
# Verify nothing was updated until we run apt update ourselves.
cd /var/lib/apt/lists
sudo du -sh . # small size
ls -ltr # old timestamps
Run Code Online (Sandbox Code Playgroud)