[TOC]

0x00 前言简述

描述: apt 全称是 Advanced Packaging Tool是Linux系统下的一款安装包管理工具,可以说是Ubuntu系统下最为重要的命令安装、更新、卸载软件升级系统内核都离不开apt命令。

apt(apt-get)命令是apt包的管理工具他们根据/etc/apt/sources.list里的软件源地址列表搜索目标软件、并通过维护本地软件包列表来安装和卸载软件。

Ubuntu可以使用apt-get来获取系统或者软件的更新,并且把这些更新从网络上下载下来安装到电脑上

apt工作原理:
描述: Ubuntu采用集中式的软件仓库机制,将各式各样的软件包分门别类地存放在软件仓库中,进行有效地组织和管理,然后将软件仓库置于许许多多的镜像服务器中,并保持基本一致。这样所有的Ubuntu用户随时都能获得最新版本的安装软件包。
因此对于用户这些镜像服务器就是他们的软件源(Reposity), 然而由于每位用户所处的网络环境不同, 不可能随意地访问各镜像站点。

WeiyiGeek.apt工作原理

WeiyiGeek.apt工作原理


apt 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
$vi /etc/apt/sources.list   #更改更新源

#文件的内容是软件包的描述信息, 该软件包括当前系统所使用的 ubunt 安装源中的所有软件包,其中包括当前系统中已安装的和未安装的软件包.
/var/lib/dpkg/available

#目录是在用 apt-get install 安装软件时,软件包的临时存放路径
/var/cache/apt/archives

#存放的是软件源站点
/etc/apt/sources.list

#使用apt-get update命令会从/etc/apt/sources.list中下载软件列表,并保存到该目录
/var/lib/apt/lists


0x01 命令一览

apt 命令 - 软件包管理工具

描述: 使用Ubuntu软件中心或命令行实用程序(例如apt或apt-get)安装软件包时,这些软件包是从一个或多个apt软件存储库中下载的。 我们可以使用 apt 命令安装、更新、卸载软件包。

Ubuntu 软件包查找: https://packages.ubuntu.com/

Tips : APT存储库是一个网络服务器或本地目录,其中包含可被APT工具读取的deb包和元数据文件。

Tips : 尽管默认的Ubuntu存储库中有成千上万的应用程序可用,但有时您可能需要从第三方存储库中安装软件,所以我们常常会添加apt仓库地址。

1
2
3
4
5
6
#第一步,需要修改软件源配置文件的各个配置项中的版本标识。类似于将以下配置项。
deb http://cn.archive.ubuntu.com/ubuntu/ dapper main restricted
#修改为:
deb http://cn.archive.ubuntu.com/ubuntu/ feisty main restricted
#第二步,使用“ apt-get update ”命令刷新软件包更新列表。
#第三步,使用“ apt-get dist-upgrade ”命令为系统升级新的版本。 #更新系统版本


语法参数:
apt-get 是一个用于下载和安装软件包的简易命令行界面,最常用命令是 update 和 install。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# 语法参数:
apt [-h] [-o=config_string] [-c=config_file] [-t=target_release] [-a=architecture] {list | search | show | update | install pkg [{=pkg_version_number | /target_release}]... | remove pkg... | upgrade | full-upgrade | edit-sources | {-v | --version} | {-h | --help}}

# 命令:
update - 取回更新的软件包列表信息
upgrade - 进行一次升级
install - 安装新的软件包(注:软件包名称是 libc6 而非 libc6.deb)
remove - 卸载软件包
autoremove - 卸载所有自动安装且不再使用的软件包
purge - 卸载并清除软件包的配置
source - 下载源码包文件
build-dep - 为源码包配置所需的编译依赖关系
dist-upgrade - 发布版升级,见 apt-get(8)
dselect-upgrade - 根据 dselect 的选择来进行升级
clean - 删除所有已下载的包文件
autoclean - 删除已下载的旧包文件
check - 核对以确认系统的依赖关系的完整性
changelog - 下载指定软件包,并显示其changelog
download - 下载指定的二进制包到当前目录

# 选项:
-h 本帮助文档。
-q 让输出可作为日志 - 不显示进度
-qq 除了错误外,什么都不输出
-d 仅仅下载 - 【不】安装或解开包文件
-s 不作实际操作。只是依次模拟执行命令
-y 对所有询问都回答是(Yes),同时不作任何提示
-f 当出现破损的依赖关系时,程序将尝试修正系统
-m 当有包文件无法找到时,程序仍尝试继续执行
-u 显示已升级的软件包列表
-b 在下载完源码包后,编译生成相应的软件包
-V 显示详尽的版本号
-c=? 读取指定配置文件
-o=? 设置任意指定的配置选项,例如 -o dir::cache=/tmp



#apt [选项] 命令
apt search|install|remove [package] #搜索安装移除
apt reinstall [package] #重新安装
apt update #- 更新可用软件包列表
apt upgrade #- 通过 安装/升级 软件来更新系统
apt full-upgrade #- 通过 卸载/安装/升级 来更新系统
apt edit-sources #- 编辑软件源信息文件
apt autoremove #卸载所有自动安装且不再使用的软件包
apt show [package] #显示软件包具体信息例如:版本号,安装大小,依赖关系,bug报告等等。
apt list --upgradeable #显示可升级的软件包
apt list --installed #显示已安装的软件包


# apt-get [选项] 命令
# apt-get [选项] source 软件包1 [软件包2 ...
apt-get search [package] #搜索软件包
apt-get install|remove [package] #安装或移除软件包
apt-get reinstall [package] #重新安装

apt-get update #取回更新的软件包列表信息,返回三种状态:一是命中,一是获取,一是忽略。
apt-get update --fix-missing [package] #更新软件列表/更新异常索引文件
apt-get upgrade #更新升级软件包
apt-get dselect-upgrade #使用 dselect 升级
apt-get dist-upgrade # 发行版升级 (升级系统到新版本)

apt-get purge #卸载并清除软件包的配置
apt-get --purge remove|autoremove # package 删除包及其依赖的软件包+配置文件等

apt-get autoclean #删除已下载的旧包文件
apt-get clean && sudo apt-get autoclean #清理无用的包
apt-get check #核对以确认系统的依赖关系的完整性

apt-get source package #下载该包的源代码
apt-get build-dep package #为源码包配置所需的编译依赖关系

# By default apt-get -d install will save .deb in /var/cache/apt/archives and apt-get download in current directory
apt-get download [package] # 下载指定的二进制包到当前目录
apt-get -d install [package] # 下载指定的二进制包到当前目录

apt-get changelog [package] #下载指定软件包,并显示其变更日志(changelog)


基础实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 1) 安装软件包
apt-get install PackageName # 普通安装
apt-get --reinstall install PackageName # 重新安装
apt-get install PackageName=VersionName # 安装指定包的指定版本
apt-get install -f # 修复依赖关系
apt-get build-dep PackageName # 安装源码包所需要的编译环境
apt-get source PackageName # 下载软件包的源码
# - 只下载`nfs-common rpcbind`相关软件包和依赖包不进行安装其下载目录为`/var/apt/cache/archive`
apt install -d nfs-common rpcbind
apt --fix-broken install linux-headers-5.4.0-47 # 修理坏的软件包

# 2) 卸载软件包
apt-get remove PackageName # 删除软件包, 保留配置文件
apt-get purge PackageName # 删除软件包, 同时删除配置文件
apt-get autoremove PackageName # 删除软件包, 同时删除为满足依赖而自动安装且不再使用的软件包
apt-get --purge remove PackageName # 删除软件包, 同时删除配置文件
apt-get --purge autoremove PackageName # 删除软件包, 删除配置文件, 删除不再使用的依赖包
apt-get clean && apt-get autoclean # 清除已下载的软件包 和 旧软件包

# 3) 更新软件包
apt-get clean && apt-get update # 更新安装源(Source)
apt-get upgrade # 更新已安装的软件包
apt-get dist-upgrade # 更新已安装的软件包(识别并处理依赖关系的改变)

# 4) 查询软件包
apt list # 列出已安装的所有软件包 或者 dpkg -l
apt show git # 显示指定软件信息
# Package: git
# Version: 1:2.20.1-2
# Priority: optional
# Section: vcs
# Maintainer: Gerrit Pape <[email protected]>
# Installed-Size: 36.1 MB
apt-get check # 检查是否有损坏的依赖


补充使用:

  • 1.-o 选项使用以及代理获取更新
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 1.squid 代理使用进行获取更新
    sudo apt -o Acquire::http::proxy="http://192.168.12.215:3128/" update
    # 2.选择IPv4或IPv6通道方式下载更新(可以设置别名)
    sudo apt-get -o Acquire::ForceIPv4=true update
    sudo apt-get -o Acquire::ForceIPv6=true upgrade
    # alias apt-get=sudo apt-get -o Acquire::ForceIPv6=true’

    # 3.如果你希望 apt-get 强制使用 IPv6 可以创建如下apt-get配置文件
    /etc/apt/apt.conf.d/1000-force-ipv6-transport
    Acquire::ForceIPv6 "true";
    # 同样如果你希望 apt-get 强制使用 IPv4 可以创建如下配置文件
    etc/apt/apt.conf.d/1000-force-ipv4-transport
    Acquire::ForceIPv4 "true";


apt-cache 命令 - 软件包搜索

基础语法:

1
2
3
4
5
6
apt-cache search package    # 搜索包 与 apt search 类似
apt-cache show package # 获取包的相关信息,如说明、大小、版本等 与 apt show类似
apt-cache depends package # 查看该软件包需要哪些依赖包
apt-cache rdepends package # 查看该软件包被哪些包依赖
apt-cache pkgnames # 列出所有软件包的名字
apt-cache policy # 显示软件包的安装设置状态


基础示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 实例0.搜索命令在那些软件包之中
apt-cache search ifconfig
# iproute2 - networking and traffic control tools
# net-tools - NET-3 networking toolkit
# gnome-nettool - network information tool for GNOME

# 实例1.获取软件包的相关信息, 如说明、大小、版本等
apt-cache show net-tools
# Package: net-tools
# Architecture: amd64
# Version: 1.60+git20180626.aebd88e-1ubuntu1
# Multi-Arch: foreign
# Priority: optional
# Section: net
# Origin: Ubuntu
# Maintainer: Ubuntu Developers <[email protected]>
# Original-Maintainer: net-tools Team <[email protected]>
# Bugs: https://bugs.launchpad.net/ubuntu/+filebug
# Installed-Size: 844
# Depends: libc6 (>= 2.14), libselinux1 (>= 1.32)
# Filename: pool/main/n/net-tools/net-tools_1.60+git20180626.aebd88e-1ubuntu1_amd64.deb
# Size: 196392
# MD5sum: 9c0c2ef6e21c4366564f38b15023f329
# SHA1: f2c222b8afd37d8601335a3175976a1f4de43875
# SHA256: 591808d272508bcafb28ab0b151e0d03a0c922a7f7f7e6469b41ec64c46b4a90
# Homepage: http://sourceforge.net/projects/net-tools/


# 实例2.查看当前软包的补丁
$apt-cache policy git
# git:
# 已安装:1:2.20.1-2
# 候选: 1:2.20.1-2
# 版本列表:
# *** 1:2.20.1-2 500
# 500 http://mirrors.aliyun.com/kali kali-rolling/main amd64 Packages
# 100 /var/lib/dpkg/status

# 实例3.软件包版本选择
$ apt-cache madison gcc
# gcc | 4:9.3.0-1ubuntu2 | http://mirrors.aliyun.com/ubuntu focal/main amd64 Packages
# gcc-defaults | 1.185.1ubuntu2 | http://mirrors.aliyun.com/ubuntu focal/main Sources
# gcc-defaults-mipsen | 1.186.1 | http://mirrors.aliyun.com/ubuntu focal/universe Sources
PackageName


apt-mark 命令 - 软件包标记

描述: 显示、设置和取消设置软件包的各种设置 (手动/自动) 安装标记,也可以用来处理软件包的 dpkg(1) 选中状态,以及列出或过滤拥有某个标记的软件包。

语法格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 语法规则:
apt-mark {-f=filename | {auto | manual} pkg... | {showauto | showmanual} [pkg...] } | {-v | --version} | {-h | --help}
apt-mark {hold | unhold | install | remove | purge} pkg... | {showhold | showinstall | showremove | showpurge} [pkg...]

# 常用命令:
* auto - 标记指定软件包为自动安装
* manual - 标记指定软件包为手动安装
* minimize-manual - 最小化手动用于将元包的依赖项(可传递的)标记为自动安装
* hold - 标记指定软件包为保留 (held back) 阻止软件自动更新
* unhold - 取消指定软件包的保留 (held back) 标记解除阻止自动更新
* showauto - 列出所有自动安装的软件包
* showhold – 列出设为保留的软件包
* showmanual - 列出所有手动安装的软件包

# 选项说明:
`-f=filename, --file=filename` : 从参数`filename`指定的文件名(而不是从默认位置)读取/写入包统计信息,默认位置是由配置项`Dir::State`定义的目录中的扩展状态。
`-c, --config-file` : 配置文件指定要使用的配置文件,程序将读取默认配置文件然后读取此配置文件,如果在解析默认配置文件之前需要设置配置设置,请指定一个带有`apt config`环境变量的文件。
`-o, --option` : 设置任意配置选项。语法是 `-o Foo::Bar=Bar-o` 和`--option`可以多次用于设置不同的选项。


基础示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# (1) 针对软件包操作设置。
# 保留用于将包标记为已保留,这将阻止自动安装、升级或删除包。
apt-mark hold kubeadm
# 用于取消先前设置的对包的保留,以允许再次执行更新操作。
apt-mark unhold kubeadm
apt-mark unhold libsmbclient samba-libs
# 用于以与其他show命令相同的方式打印保留的包列表。
apt-mark showhold kubeadm # kubeadm
apt-mark showhold
# kubeadm
# kubectl
# kubelet

# (2) 列出所有手动安装的软件包。
apt-mark showmanual | wc -l # 61


add-apt-repository 命令 - 添加 apt 仓库

描述: 在Ubuntu和所有其他基于Debian的发行版中,apt软件存储库在/etc/apt/sources.list文件中或在/etc/apt/sources.list.d/目录下的单独文件中定义(目录中的存储库文件的名称必须以.list结尾)。

方式1
Tips : 除了上述方式进行添加apt仓库,其次是add-apt-repository命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# /etc/apt/sources.list 文件的常规语法采用以下格式:
deb http://repo.tld/ubuntu distro component

# 参数1: 定义档案的类型,存档类型可以是 deb 表示存储库包含.deb个软件包 或 deb-src 表示源软件包。
# 参数2: 存储库URL
# 参数3: 指定分发代码名称, 例如`beaver,xenial`等
# 参数4: 是存储库组件或类别, 默认的Ubuntu存储库分为四个部分组件,main 和 restricted与受限组件Universe和multiverse。通常第三方存储库只有一个类别。

# 实践 ( Ubuntu 20.04.2 LTS ) 案例
# 配置文件修改
deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse

# 手动命令添加存储库,您还需要手动将公共存储库密钥导入系统
curl -L https://couchdb.apache.org/repo/bintray-pubkey.asc | sudo apt-key add -
echo "deb https://apache.bintray.com/couchdb-deb $(lsb_release -cs) main" | sudo tee -a /etc/apt/sources.list.d/couchdb.list

Tips : 注意大多数存储库都提供公钥以对需要下载和导入的已下载软件包进行身份验证。

Tips : 当要添加或删除存储库,您需要以具有sudo访问权限或root用户的身份登录。


方式2
描述: add-apt-repository实用程序包含在software-properties-common程序包中。要安装它请运行以下命令:sudo apt install software-properties-common

基础语法:

1
2
3
4
5
# 语法
add-apt-repository [options] repository

# 参数
repository : 可以是可以添加到sources.list文件 (例如 `deb http://repo.tld/ubuntu distro component`)的常规存储库条目,也可以是`ppa:<user>/<ppa-name>`格式的PPA存储库。

Tips : PPA存储库个人软件包档案(PPA)是一项服务,允许用户上传使用Launchpad构建和发布的Ubuntu源软件包作为apt信息库。


基础示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 1.官方存储库中安装 MongoDB, 首先导入存储库公钥,其次添加MongoDB存储库
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4
sudo add-apt-repository 'deb [arch=amd64] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse'

# 2.如果出于任何原因要删除先前启用的存储库,请使用--remove选项:
sudo add-apt-repository --remove 'deb [arch=amd64] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse'

# 3.添加提供 FFmpeg 版本4.x的Jonathon F的PPA存储库, 此时它会在/etc/apt/sources.list.d/目录下创建一个新文件
sudo add-apt-repository ppa:jonathonf/ffmpeg-4
# Press [ENTER] to continue or Ctrl-c to cancel adding it. # 按 Enter 将启用存储库
sudo apt install ffmpeg

# 4.Ubuntu 软件源库添加设置稳定docker软件源存储库
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"


0x02 Apt 配置扩充

0.在Ubuntu 20.04 Focal Fossas进行APT Proxy 代理下载软件设置

Ubuntu 20.04 与 18.04 版本

1
2
3
4
5
6
7
8
9
10
11
12
13
# Ubuntu 18.04
sudo vi/etc/apt/apt.conf.d/98proxy
# Acquire::http::proxy "http://username:[email protected]_ip:proxy_port/";
# Acquire::ftp::proxy "ftp://username:[email protected]_ip:proxy_port/";
# Acquire::https::proxy "https://username:[email protected]_ip:proxy_port/";

# Ubuntu 20.04
sudo tee /etc/apt/apt.conf.d/30proxy <<'EOF'
Acquire::http::proxy "http://192.168.12.215:3128";
EOF

# 临时生效
sudo apt -o Acquire::http::proxy="http://192.168.12.215:3128/" update


1.在Ubuntu 20.04 Focal Fossas上进行Apt代理客户端配置与apt代理服务器配置

描述:你正在阅读一个关于如何配置apt代理服务器和客户端在Ubuntu 20.04 Focal Fossa 的快速教程
环境说明:

1
2
3
4
5
$lsb_release -crid
Distributor ID: Ubuntu
Description: Ubuntu 20.04.1 LTS
Release: 20.04
Codename: focal


Ubuntu apt 代理服务器安装操作流程:

  • Step 1.安装配置apt cacher代理服务
    1
    sudo apt install -o Acquire::http::proxy="http://192.168.12.215:3128/" apt-cacher -y

0x04 入坑出坑

问题1.运行apt-get进行安装软件时候提示E: Unable to locate package vim[软件名称];

  • 问题原因: 当然软件源仓库中没你要得软件或者您还未更新拉取软件仓库(在docker中常常遇到)
  • 解决方式:
    1
    2
    3
    # (1) 更换软件源(详看Linux发行版的镜像网站及开源软件收集)
    # (2) 更新软件源仓库
    apt update


问题2.E: Unmet dependencies. Try 'apt --fix-broken install' with no packages (or specify a solution).

  • 错误描述:
    1
    2
    3
    4
    5
    6
    7
    The following packages were automatically installed and are no longer required:
    linux-headers-5.4.0-42 linux-headers-5.4.0-42-generic linux-image-5.4.0-42-generic linux-modules-5.4.0-42-generic linux-modules-extra-5.4.0-42-generic
    Use 'sudo apt autoremove' to remove them.

    你可能想运行"apt—fix-broken install"来纠正这些错误。
    以下软件包有未满足的依赖性:
    linux-headers-generic:取决于:linux-headers-5.4.0-58-generic但它不会被安装
  • 解决方式:未满足的依赖关系。尝试不带软件包的“apt -fix-broken install”(或指定一个解决方案)。
    1
    2
    apt --fix-broken install
    sudo apt autoremove


问题3.安装环境包时出现Could not get lock /var/lib/dpkg/lock - open解决方法

  • 问题复原:
    1
    2
    3
    $ sudo apt autoremove --purge -y snapd
    Waiting for cache lock: Could not get lock /var/lib/dpkg/lock. It is held by process 321016 (dWaiting for cache lock: Could not get lock /var/lib/dpkg/lock. It is held by process 321016 (dWaiting for cache lock: Could not get lock /var/lib/dpkg/lock. It is held by process 321016 (dpkg)... Error!
    E: dpkg was interrupted, you must manually run 'sudo dpkg --configure -a' to correct the problem.
  • 问题原因: 在这个时候主要是因为apt还在运行或者上次执行内核安装或者apt升级时出现错误;
  • 解决办法:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 方法1:找到并且杀掉所有的apt-get 和 apt进程
    ps -A | grep apt
    sudo kill -9 进程ID

    # 方法2.删除锁定文件 /var/lib/apt/lists/、/var/lib/dpkg/、/var/cache/apt/archives/ 中
    # (1) 首先运行下面的命令来移除 `/var/lib/dpkg/` 文件夹下的锁定文件:
    $ sudo rm /var/lib/dpkg/lock
    $ sudo dpkg --configure -a

    # (2) 也可以如下删除 /var/lib/apt/lists/ 以及缓存文件夹下的锁定文件:
    $ sudo rm /var/lib/apt/lists/lock
    $ sudo rm /var/cache/apt/archives/lock


问题4.apt安装软件时提示Target Packages (multiverse/binary-amd64/Packages) is configured multiple times in /etc/apt/sources.list错误

  • 错误信息:
    1
    W: Target Packages (multiverse/binary-amd64/Packages) is configured multiple times in /etc/apt/sources.list:26 and /etc/apt/sources.list:53
  • 问题原因:更新源重复配置
  • 解决办法: 将 /etc/apt/sources.list apt仓库地址的重复源删掉即可

错误演示: https://blog.csdn.net/qingfengxiaosong/article/details/87889995
(Reading database … 149871 files and directories currently installed.)
Removing linux-modules-extra-5.4.0-59-generic (5.4.0-59.65) …
dpkg: error processing package linux-modules-extra-5.4.0-59-generic (–remove):
unable to securely remove ‘/lib/modules/5.4.0-59-generic/kernel/drivers/input/keyboard/xtkbd.ko.dpkg-tmp’: Input/output error
dpkg: too many errors, stopping
Errors were encountered while processing:
linux-modules-extra-5.4.0-59-generic
Processing was halted because there were too many errors.
E: Sub-process /usr/bin/dpkg returned an error code (1)
[email protected]:~# cd /var/lib/dpkg
[email protected]:/var/lib/dpkg# ls
alternatives available cmethopt diversions diversions-old info lock lock-frontend parts statoverride status status-old triggers updates
[email protected]:/var/lib/dpkg# sudo mv info info.bak
[email protected]:/var/lib/dpkg# sudo mkdir info
[email protected]:/var/lib/dpkg# sudo apt-get upgrade

1
2
3
4
5
6
7
8
9
10
sudo apt update -qq && sudo apt install -qq -y podman kubelet kubeadm kubectl 
cp -a /var/cache/apt/archives/containernetworking-plugins_0.8.7~1_amd64.deb /tmp/
mkdir container
dpkg-deb -R containernetworking-plugins_0.8.7~1_amd64.deb container/
sed -i -e '/^Version:/s/$/~conflictfree/' -e '/^Conflicts: kubernetes-cni/d' container/DEBIAN/control
rm -f container/opt/cni/bin/*
sudo dpkg -b container/ containernetworking-plugins_0.8.7~1_amd64_custom.deb
sudo dpkg -i containernetworking-plugins_0.8.7~1_amd64_custom.deb
sudo apt update -qq && sudo apt install -qq -y podman kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl podman containernetworking-pluginsap