尝试使用脚本取消注释无人值守升级行,需要帮助

尝试使用脚本取消注释无人值守升级行,需要帮助

我最近开始在一家全 Linux 公司担任 IT 人员,并注意到我们所做的一些任务可以“轻松”实现自动化。今天要自动化的任务是/etc/apt/apt.config.d/50unattended-upgrades在新电脑上安装软件和配置。我已经编写了软件安装脚本,但现在我被困在取消注释所需的无人值守升级行上。

我给你举个例子,这个:

// Automatically upgrade packages from these (origin:archive) pairs
//
// Note that in Ubuntu security updates may pull in new dependencies
// from non-security sources (e.g. chromium). By allowing the release
// pocket these get automatically pulled in.
Unattended-Upgrade::Allowed-Origins {
        "${distro_id}:${distro_codename}";
        "${distro_id}:${distro_codename}-security";
        // Extended Security Maintenance; doesn't necessarily exist for
        // every release and this system may not have it installed, but if
        // available, the policy for updates is such that unattended-upgrades
        // should also install from here by default.
        "${distro_id}ESMApps:${distro_codename}-apps-security";
        "${distro_id}ESM:${distro_codename}-infra-security";
//      "${distro_id}:${distro_codename}-updates";                             
//      "${distro_id}:${distro_codename}-proposed";
//      "${distro_id}:${distro_codename}-backports";
};

看起来应该是这样的:

// Automatically upgrade packages from these (origin:archive) pairs
//
// Note that in Ubuntu security updates may pull in new dependencies
// from non-security sources (e.g. chromium). By allowing the release
// pocket these get automatically pulled in.
Unattended-Upgrade::Allowed-Origins {
        "${distro_id}:${distro_codename}";
        "${distro_id}:${distro_codename}-security";
        // Extended Security Maintenance; doesn't necessarily exist for
        // every release and this system may not have it installed, but if
        // available, the policy for updates is such that unattended-upgrades
        // should also install from here by default.
        "${distro_id}ESMApps:${distro_codename}-apps-security";
        "${distro_id}ESM:${distro_codename}-infra-security";
        "${distro_id}:${distro_codename}-updates";                             
//      "${distro_id}:${distro_codename}-proposed";
//      "${distro_id}:${distro_codename}-backports";
};

(更新行应该取消注释)

我尝试使用 sed 来做这件事,但就是不行,可能是因为我是个菜鸟。这是我笨拙的 sed 代码,希望有人能向我解释我做错了什么!

#!/bin/bash

    sudo sed -i 's@//      "${distro_id}:${distro_codename}-updates"@        "${distro_id}:${distro_codename}-updates"@' /etc/apt/apt.conf.d/50unattended-upgrades

任何帮助都将不胜感激!祝您有美好的一天!

答案1

为什么不直接创建另一个/etc/apt/apt.config.d/51my-unattended-upgrades包含以下内容的文件:

Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}-updates";
};

选项已合并在一起。请使用 检查apt-config dump

此外,只需删除单个文件即可轻松删除更改。任何升级更改/etc/apt/apt.conf.d/50unattended-upgrades都不会破坏您的更改。

如果没有必要,最好不要更改他人的配置文件。

尝试解释一下:

从 的 python 源代码中unattended-upgrade可以看出,它不解析 中的配置文件/etc/apt/...。相反,它使用 python-apt-api。它类似于apt-config在 shell 中使用(您应该始终这样做,而不是读取配置文件)。

在这种特殊情况下,python-apt-api 会合并所有文件并返回一个列表Origins-Pattern,然后unattended-upgrade脚本会循环遍历所有文件。

我不知道有什么好的文档可以介绍这个。你能做的最好的事情就是查看源代码。

答案2

请参见Marco 的回答,这就是正确的做法®,我sed在这里只关注和正则表达式问题。


使用正则表达式的第一条规则是“少即是多”。不要尝试匹配整行,而是使用尽可能小的正则表达式来捕获您需要捕获的内容。例如,在这里,您不关心行首的空格,因此不必费心尝试匹配它们。此外,空格的数量很可能会发生变化,您不希望因此破坏您的脚本,所以请忽略它们!

据我所知,您真正想要做的就是//从包含字符串的任何行中删除前导-updates。如果是这样,您所需要的就是:

sed '/-updates/{s@^\s*//@@}' /etc/apt/apt.conf.d/50unattended-upgrades

这意味着“如果此行与 匹配-updates,则用 替换 后面的 0 个或更多前导空格字符(注释不必是行的第一个字符) ”。因此,这将删除与匹配的行中的//前导字符。//-updates

如您所见,这更容易编写和理解。也就是说,您的原始命令可以按预期在示例文件中运行,只是不必要地复杂和脆弱(如果添加空格,它会中断):

$ sed 's@//      "${distro_id}:${distro_codename}-updates"@        "${distro_id}:${distro_codename}-updates"@' file 
/ Automatically upgrade packages from these (origin:archive) pairs
//
// Note that in Ubuntu security updates may pull in new dependencies
// from non-security sources (e.g. chromium). By allowing the release
// pocket these get automatically pulled in.
Unattended-Upgrade::Allowed-Origins {
        "${distro_id}:${distro_codename}";
        "${distro_id}:${distro_codename}-security";
        // Extended Security Maintenance; doesn't necessarily exist for
        // every release and this system may not have it installed, but if
        // available, the policy for updates is such that unattended-upgrades
        // should also install from here by default.
        "${distro_id}ESMApps:${distro_codename}-apps-security";
        "${distro_id}ESM:${distro_codename}-infra-security";
        "${distro_id}:${distro_codename}-updates";                             
//      "${distro_id}:${distro_codename}-proposed";
//      "${distro_id}:${distro_codename}-backports";
};

最后,几点一般性观察:

  • 绝不在重要文件上使用sed -i而不进行备份。该-i选项允许您指定备份后缀,因此如果您运行sed -i.bak 's/a/b/' file,则会将原始文件复制为file.bak。因此,您应该在您的案例中执行类似操作sudo sed -i.bak ...,这样您就可以随时撤消操作。
  • 这很少是一个好主意在脚本中添加sudo。相反,编写脚本时不要使用sudo,然后使用 来调用sudosudo script.sh

相关内容