在网上浏览 Ubuntu 文章时,我遇到了这个命令:
sudo dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d' | xargs sudo apt-get -y purge
作者说这是一个单行命令,它将删除所有以前版本的Linux,只保留当前版本!
我实际上正在寻找这样的命令,但我不太确定它有多安全。我想知道:
- 执行该命令是否安全?
- 这个命令是如何工作的?即解释这么大的命令的一小部分
- 如果此命令有其他用途,那么什么命令才是正确的,才能实现作者声称它要做的事情呢?
当我尝试自己推断时,我感到非常困惑和沮丧。这个命令如何工作,因为它包含大量/
、|
、\
、*
和^
字符,这些字符很难在 Google 上找到。
我正在寻找一步一步翻译和解释对于这个命令,我在互联网上无法找到!
答案1
我想说:不要以目前的形式使用它
它会在不询问您的情况下进行更改。该
apt-get -y purge
部分允许单行程序开始执行清除包,而无需您的确认。如果脚本中存在任何错误,那么您可能会拧紧。没有来源,没有给出作者。它的来源在这里很重要。如果它来自经过彻底测试的系统包,我们可以追踪对它进行的测试。如果是随机来源,我们不能相信它。
dpkg -l
没有 也能正常运行sudo
。我不明白为什么原作者认为这是必要的。
运用常识
删除有害部分并删除以 root 身份运行的任何内容。
例如,将其简化为:
dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d'
这只是只输出东西并运行具有常规用户权限。同意删除这些内核后,您可以附加 | xargs sudo apt-get purge
自己确认。它-y
故意没有这个选项,所以系统会要求您确认即将对系统进行的更改。
解释
dpkg -l
输出所有软件包的列表。在本例中,它仅列出软件包开始以linux-
作为名称。|
(管道)将左边命令的输出(我们称之为stdout
)通过管道传输到右边命令的输入(我们称之为stdin
)。sed
是一个使用以下方法操作字符串的工具常用表达。在本例中,它操纵管道左侧命令的输出并过滤已安装的软件包(依赖于ii
给出的dpkg
)。在本例中它甚至是嵌套的。在这里解释 的整个用法太难了sed
,因为它的用法非常复杂,带有复杂的正则表达式。(\(.*\)-\([^0-9]\+\)"
是正则表达式的一个例子。- 常用表达被广泛用于根据它们所代表的表达式查找匹配项。
\1
是替换引用,用于执行某种通用搜索和替换(引用第一个“命中”1
)。正则表达式本身不会造成任何伤害。但是,如果它们以错误的方式操纵输入,它们可能会让您删除错误的软件包,甚至进行 shell 注入。在这种情况下,它看起来像是一种根据提供的版本查找内核软件包名称的方法uname -r
。 uname -r
输出当前运行的内核版本。xargs
将管道左侧输入的行作为参数附加到命令中。在这种情况下,每行上的内核版本将转换为水平空格分隔的列表并附加到命令中sudo apt-get
。sudo apt-get -y purge [packagename]
清除(删除所有内容)给定的包(作为参数)。
备择方案
可能已经有人问过这个问题了。我目前找到的相关问题如下:
- 更新后如何“清理”以前的内核?
- 如何删除旧内核版本来清理启动菜单?
从这个答案,以下命令似乎以更安全、更常见的方式执行相同操作:
sudo apt-get purge $( dpkg --list | grep -P -o "linux-image-\d\S+" | grep -v $(uname -r | grep -P -o ".+\d") )
答案2
您要求一步一步的解释,因此如下:
sudo dpkg -l 'linux-*'
列出linux-
包名中以 开头的包
| sed
并将列表导入sed
"s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d'
这将使用非常复杂的正则表达式来编辑列表
| xargs
xargs
它将把新列表输入到
sudo apt-get -y purge
这将清除这些包而不给你改变主意的机会。
或者更准确的说法是,它会将该列表发送到清除命令中,然后就此打住。无论是否有任何东西被清除——重要的是——被清除了什么取决于前面命令的输出。
它安全吗?在这种情况下,一切都取决于你找到它的帖子的作者对正则表达式和sed
语法的理解程度。关于这两个主题都有整本书。
答案3
我首先分析这些命令,然后阅读man
每个命令的页面。
dpkg -l
:列出软件包,因此dpkg -l linux-*
会列出所有以(通常是内核)开头的软件包linux-
。sed
:的输出通过dpkg -l linux-*
管道传输到sed
几个sed
解码的正则表达式。uname -r
uname
打印系统信息
uname—打印系统信息
该-r
句柄专门打印内核版本:
-r, --kernel-release 打印内核版本
uname -r
然后将的输出sed
通过更多正则表达式传输到xargs
因此将输出xargs
转换sed
为包名称并将它们传递给sudo apt-get purge -y
自动对所有提示回答“是”的包:
-y, --yes, --assume-yes 自动对提示回答“是”;假设所有提示的答案都是“是”,并以非交互方式运行。如果出现不良情况,例如更改保留的软件包、尝试安装未经认证的软件包或删除必需的软件包,则 apt-get 将中止。配置项:APT::Get::Assume-Yes。
总的来说,这个命令将要做你想做的事,但要确定我们必须翻译sed
的正则表达式。
我刚刚跑了:
dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d'
以下是截图:
据我回忆,所有内核版本都是旧的。
答案4
此脚本的一个不太危险的版本删除了未使用和过期的内核,它rc
在输出的行首匹配dpkg
,而不是ii
。 (见https://askubuntu.com/a/18807/220802对这些标志进行解释。)就我而言,这完全匹配所有未受保护的内核包/etc/apt/apt.conf.d/01autoremove-kernels
。
例如:
# sed -n '/to keep/,$p' /etc/apt/apt.conf.d/01autoremove-kernels
# Kernel versions list to keep:
5.4.0-58.64
5.4.0-60.67
# Kernel packages (version part) to protect:
5\.4\.0-58-generic
5\.4\.0-60-generic
*/
和
# dpkg -l 'linux-*' | sed '/^rc/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d'
linux-image-5.3.0-18-generic
linux-image-5.3.0-19-generic
linux-image-5.3.0-45-generic
linux-image-5.4.0-21-generic
linux-image-5.4.0-26-generic
linux-image-5.4.0-28-generic
linux-image-5.4.0-31-generic
linux-image-5.4.0-33-generic
linux-image-5.4.0-40-generic
linux-image-5.4.0-42-generic
linux-image-5.4.0-48-generic
linux-image-5.4.0-52-generic
linux-image-5.4.0-53-generic
linux-image-5.4.0-56-generic
linux-modules-5.3.0-18-generic
linux-modules-5.3.0-19-generic
linux-modules-5.3.0-45-generic
linux-modules-5.4.0-21-generic
linux-modules-5.4.0-26-generic
linux-modules-5.4.0-28-generic
linux-modules-5.4.0-31-generic
linux-modules-5.4.0-33-generic
linux-modules-5.4.0-40-generic
linux-modules-5.4.0-42-generic
linux-modules-5.4.0-48-generic
linux-modules-5.4.0-52-generic
linux-modules-5.4.0-53-generic
linux-modules-5.4.0-56-generic
linux-modules-extra-5.3.0-18-generic
linux-modules-extra-5.3.0-19-generic
linux-modules-extra-5.3.0-45-generic
linux-modules-extra-5.4.0-21-generic
linux-modules-extra-5.4.0-26-generic
linux-modules-extra-5.4.0-28-generic
linux-modules-extra-5.4.0-31-generic
linux-modules-extra-5.4.0-33-generic
linux-modules-extra-5.4.0-40-generic
linux-modules-extra-5.4.0-42-generic
linux-modules-extra-5.4.0-48-generic
linux-modules-extra-5.4.0-52-generic
linux-modules-extra-5.4.0-53-generic
linux-modules-extra-5.4.0-56-generic
现在您可以通过管道传输该消息| xargs apt purge -y
。请注意,省略该-y
标志将导致操作中止。
然后,您可以检查/boot
目录中是否有更多旧内核的残留。在我的例子中,还有更多文件挂在周围,不再被跟踪apt
,这些文件被删除,并被ls /boot/*-5.4.0-{00..56}* 2>/dev/null
小心地传送到| xargs rm -rf
。