重要なのに忘れがちなapt関係のコマンドのメモ

## いい加減にapt-getからaptに乗り換えようと思った
　Linux(Ubuntu)やラズパイ(Raspberry Pi OS)でよく使う、パッケージ管理コマンドの`apt`。今まで、互換性を重視して基本的に`apt-get`を使うようにしてきました。ただ、Ubuntuは6年前の14.04から、Raspberry Pi OSもRaspbian Jessieから`apt`コマンドが使えるようになったので、そろそろ互換性の問題が起こることもよほど無いだろうと思い`apt`コマンドに乗り換えることにしました。

　というわけで、`apt-get`と`apt`の違いと忘れがちな`apt`コマンドとかを備忘録がわりにまとめておきたいと思います。随時更新していきます。


## `apt-get`と`apt`の違い
　そもそも`apt`が何で、`apt-get(apt-cache)`と何が違うかというと、以下くらいのようです。

- `apt`は新しいパッケージ管理コマンドで `apt-get`と`apt-cache`が統合したもの
- `apt`はプログレスバーがついて進捗がわかりやすい
- upgradeのとき`apt`より`apt-get`の方が条件が厳しい（慎重）

　あんまり使い手側が意識する必要はないですね。`apt-cache`も古いから`apt`を使うようにした方がよいのと、`apt`はプログレスバーが出るのでちょっとカッコいい（？）くらいでしょうか。コマンドの対応表を最後の方にのっけたのでそちらも参考にしてみてください。

　他パッケージインストールするコマンドで似たものに`aptitude`や`snap`といったものがあります。`aptitude`は`apt`と似た外部パッケージですが、基本的に積極的に使用する必要はないと思います。`snap`は`apt`がdebパッケージをインストールするのに対して、`snap`は`snap`パッケージをインストールします。仕組みの詳細は割愛しますが`snap`パッケージはクリーンにインストールしやすく、`apt`とも共存可能なので、パッケージによっては`snap`を選択するのも良いかと思います。

## aptコマンド基本
　パッケージのリストをアップデートして、インストールするのが基本ですね。`<package>`のところは、対象のパッケージの名前を入れてください。

```sh
$ sudo apt update
$ sudo apt install <package>
```

　インストールするとき、いちいち Yes or Noを聞かれるのが嫌な場合（特にスクリプトで自動化したい場合）は、以下のように`-y`オプションをつけましょう。`-y`の位置はinstallの前でも後ろでもOKです。

```sh
$ sudo apt -y install <package>
```

　ログを極力表示させたくないときは`-qq`オプションを使います。

```sh
$ sudo apt -qq update
$ sudo apt -qq install <package>
```

　ログを全く表示させたくないときは、コマンドの後に`> /dev/null 2>&1`をつける。これは`apt`以外のコマンドでも使える。

```sh
$ sudo apt update > /dev/null 2>&1
$ sudo apt install <package> > /dev/null 2>&1
```

## パッケージのバージョン一覧確認
　インストール可能なパッケージのバージョンの一覧の確認方法です。`<package>`のところは、対象のパッケージの名前を入れてください。

```sh
$ apt list -a <package>
```

　インストール済みのパッケージのバージョンを確認する方法は、正確にはaptコマンドではないですが`apt-show-versions`というパッケージを使う方法があります。

```sh
$ apt-show-versions <package>
```

　`apt-show-versions`がインストールされていなかったら、以下コマンドでインストールしましょう。

```sh
$ sudo apt-get install apt-show-versions
```

　もしくは、以下のようにdpkgコマンドでも確認できます。

```sh
$ dpkg -l <package>
```

　ついでですが、aptでインストールしたパッケージのインストール場所を知りたい場合は、以下のように`-L`オプションを使います。

```sh
$ dpkg -L <package>
```

## 自動更新を止める
　パッケージの更新を止める場合は以下です。

```sh
$ sudo apt-mark hold <package>
```

　使うのは、例えばCUDA関係とかですかね。ついでに、aptではないですがカーネルの自動更新を止める方法は以下です。

```sh
$ sudo dpkg-reconfigure --priority=low unattended-upgrades
```

　続いて出てくる画面で「自動的に安定版の更新をダウンロードしてインストールしますか？」というようなことが聞かれるので「いいえ」を選択すれば自動更新を止められます（「はい」にすると、自動で更新されます）。

　実際に設定されるのは以下のファイルです。

`/etc/apt/apt.conf.d/20auto-upgrades`

　手動で設定したい場合は、以下の通りに`0`に設定することで自動更新を停止できます（`1`にすると自動更新します）。

```
APT::Periodic::Update-Package-Lists "0";
APT::Periodic::Unattended-Upgrade "0";
```


## aptコマンドとapt-get/apt-cacheコマンドの対応表
　代表的なコマンドの対応表を載せます。`apt-get`や`apt-cache`を使っている人は`apt`コマンドへ置き換えを進めると良いのではないかと思います。

| apt | apt-get/apt-cache/dpkg | 内容 |
|:-:|:-:|:-:|
| `sudo apt update`  | `sudo apt-get update`  | パッケージリストの更新  |
| `sudo apt install <package>`  | `sudo apt-get install <package>`  |  パッケージのインストール |
| `apt search <package>`  | `apt-cache search <package>`  |  パッケージの検索 |
| `sudo apt remove <package>`  | `sudo apt-get remove <package>`  |  パッケージの削除 |
| `sudo apt remove --purge <package>`  | `sudo apt-get remove --purge <package>`  |  パッケージの完全な削除 |
| `sudo apt upgrade`  | `sudo apt-get upgrade`  | パッケージの更新（apt-getの方が慎重）  |
| `apt list -a`  | `apt-cache policy <package>`  | バージョンの一覧確認  |
| `apt list --installed`  | `dpkg -l`  | インストールされているパッケージの一覧表示  |

## スクリプトではファイルではaptでなくapt-getが推奨
　もうこれで完全に`apt-get`から`apt`に乗り換えられますね。といいたいところですが、`apt`のマニュアルを読むと、ユーザーが使う場合は`apt`が推奨ですが、スクリプトに関してはなんと`apt-get`が推奨のようです。

> All features of apt(8) are available in dedicated APT tools like apt-get(8) and apt-
       cache(8) as well.  apt(8) just changes the default value of some options (see apt.conf(5)
       and specifically the Binary scope). So you should prefer using these commands (potentially
       with some additional options enabled) in your scripts as they keep backward compatibility
       as much as possible.

[Ubuntu aptのマニュアル](https://manpages.ubuntu.com/manpages/xenial/man8/apt.8.html)より引用

　bashのスクリプトの他、Dockerfile等も[Docker ドキュメント](http://docs.docker.jp/)をみたところ`apt`でなく`apt-get`が推奨されているのは、これが理由のようですね。

　全部`apt`に置き換えたいのに、紛らわしいです…

## apt関係Tips
### sudo apt updateでエラーがでる。
こんなエラーが出たりする場合。

```
E: ソース https://nvidia.github.io/libnvidia-container/stable/ubuntu18.04/amd64/ / に関してオプション Signed-By の値が競合します: /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg != 
E: ソースのリストを読むことができません。
````

`/etc/apt/sources.list`とか /etc/apt/sources.list.d/`の中にある`nvidia-container-toolkit.list`とかあやしそうなやつをエディタで開いて、とりあえずコメントアウトしていきましょう。



## まとめ
　`apt`関係の情報をまとめました。`apt-get`と`apt`を正しく使い分けていきましょう。

## 関連ページ
https://qiita.com/karaage0703/items/705f1b750c486f00d554

https://karaage.hatenadiary.jp/entry/2018/10/05/073000

https://karaage.hatenadiary.jp/entry/2019/05/17/073000


## 参考
- https://qiita.com/SUZUKI_Masaya/items/1fd9489e631c78e5b007
- https://qiita.com/ironsand/items/1a1612996b52b4d4c62e
- https://qiita.com/komeda-shinji/items/339b8e14b3f8b658b288
- https://www.atmarkit.co.jp/ait/articles/1709/07/news016.html
- https://linuxfan.info/package-management-ubuntu
- https://qiita.com/SUZUKI_Masaya/items/1fd9489e631c78e5b007
- https://askubuntu.com/questions/916199/install-apt-show-versions-inside-an-ubuntu-docker-container
- https://teratail.com/questions/158844
- https://news.mynavi.jp/article/20190222-775519/
- https://pc.watch.impress.co.jp/docs/column/ubuntu/1407176.html

## 変更履歴
- 2022/02/10 スクリプトに関しての注記を追記
- 2021/07/23 コマンド追加
- 2020/11/27 Dockerfileに関して追記
- 2020/11/04 基本コマンドと対応表を追記