"apt list"コマンドの出力をパイプに渡すと発生する、"WARNING: apt does not have a stable CLI interface. Use with caution in scripts."というエラーについて


# "WARNING: apt does not have a stable CLI interface. Use with caution in scripts." というエラー
「Ubuntuにapache2のパッケージがインストール済みか確認しよう」といったケースにおいて、`apt list`の出力をパイプに渡すと以下のようなWARNINGのエラーが発生します。

```
$ apt list --installed | grep apache2

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

apache2/bionic-updates,bionic-security,now 2.4.29-1ubuntu4.13 amd64 [installed]
apache2-bin/bionic-updates,bionic-security,now 2.4.29-1ubuntu4.13 amd64 [installed,automatic]
apache2-data/bionic-updates,bionic-updates,bionic-security,bionic-security,now 2.4.29-1ubuntu4.13 all [installed,automatic]
apache2-utils/bionic-updates,bionic-security,now 2.4.29-1ubuntu4.13 amd64 [installed,automatic]
libapache2-mod-php7.2/bionic-updates,bionic-security,now 7.2.24-0ubuntu0.18.04.6 amd64 [installed]
```

[こちら](https://askubuntu.com/questions/990823/apt-gives-unstable-cli-interface-warning)の記事にある通り、`apt`のmanページに以下のような記載があります。

```
SCRIPT USAGE AND DIFFERENCES FROM OTHER APT TOOLS
       The apt(8) commandline is designed as an end-user tool and it may change behavior between versions. While it tries not to break backward compatibility this is not guaranteed either if a change seems
       beneficial for interactive use.

       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.
```

記載の通り、`apt`コマンドは対話的な用途のために設計されているため、人間が使いやすいよう今後出力が変更される可能性があるとのことです。スクリプトにおける利用においては、`apt-get`, `apt-cache`コマンド等の利用を推奨するという内容です。

# `apt list`コマンドの代替が `apt-get`, `apt-cache`コマンドに存在しない件

ただ一つ問題が。`apt list`コマンドと同じような動作をするコマンドが`apt-get`, `apt-cache`にありません。

## WARNINGエラーを握りつぶして`apt`コマンドを利用し続ける
`apt list`コマンドのエラー出力は標準エラーに出力されるため、以下のように標準エラー出力を`/dev/null`にリダイレクトしてしまえば消すことができます。
ref: https://serverfault.com/questions/958003/how-to-disable-warning-apt-does-not-have-a-stable-cli-interface

```
$ apt list --installed 2>/dev/null | grep apache2
apache2/bionic-updates,bionic-security,now 2.4.29-1ubuntu4.13 amd64 [installed]
apache2-bin/bionic-updates,bionic-security,now 2.4.29-1ubuntu4.13 amd64 [installed,automatic]
apache2-data/bionic-updates,bionic-updates,bionic-security,bionic-security,now 2.4.29-1ubuntu4.13 all [installed,automatic]
apache2-utils/bionic-updates,bionic-security,now 2.4.29-1ubuntu4.13 amd64 [installed,automatic]
libapache2-mod-php7.2/bionic-updates,bionic-security,now 7.2.24-0ubuntu0.18.04.6 amd64 [installed]
```

## `dpkg -l`コマンドを利用する
出力が変わってしまうリスクを懸念する場合は、`dpkg -l`コマンドを利用し、同様の意味を持つ出力を得ることができます。

```
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                                       Version                                          Architecture Description
+++-==========================================-================================================-============-===============================================================================
ii  accountsservice                            0.6.45-1ubuntu1                                  amd64        query and manipulate user account information
ii  acl                                        2.2.52-3build1                                   amd64        Access control list utilities
ii  acpi-support                               0.142                                            amd64        scripts for handling many ACPI events
ii  acpid                                      1:2.0.28-1ubuntu1                                amd64        Advanced Configuration and Power Interface event daemon
ii  adduser                                    3.116ubuntu1                                     all          add and remove users and groups
ii  adium-theme-ubuntu                         0.3.4-0ubuntu4                                   all          Adium message style for Ubuntu
ii  adwaita-icon-theme                         3.28.0-1ubuntu1                                  all          default icon theme of GNOME (small subset)
ii  alsa-base                                  1.0.25+dfsg-0ubuntu5                             all          ALSA driver configuration files
ii  alsa-utils                                 1.1.3-1ubuntu1                                   amd64        Utilities for configuring and using ALSA
ii  amd64-microcode                            3.20191021.1+really3.20181128.1~ubuntu0.18.04.1  amd64        Processor microcode firmware for AMD CPUs
ii  anacron                                    2.3-24                                           amd64        cron-like program that doesn't go by time
rc  ansible                                    2.5.1+dfsg-1ubuntu0.1                            all          Configuration management, deployment, and task execution system
```

記載の通り、Install済みのものはStatusが"i"となるので、

```
$ dpkg -l | grep '^ii' | grep apache2
ii  apache2                                    2.4.29-1ubuntu4.13                               amd64        Apache HTTP Server
ii  apache2-bin                                2.4.29-1ubuntu4.13                               amd64        Apache HTTP Server (modules and other binary files)
ii  apache2-data                               2.4.29-1ubuntu4.13                               all          Apache HTTP Server (common files)
ii  apache2-utils                              2.4.29-1ubuntu4.13                               amd64        Apache HTTP Server (utility programs for web servers)
ii  libapache2-mod-php7.2                      7.2.24-0ubuntu0.18.04.6                          amd64        server-side, HTML-embedded scripting language (Apache 2 module)
```

のようにコマンドを発行すれば、インストール済みのパッケージの情報を引っ張ってくることができます。[^1]
[^1]: "Desired" については、パッケージにマークをつけることができるようで、その情報を出力するようです。(https://askubuntu.com/questions/947192/how-is-the-desired-status-in-the-debian-package-manager-determined)

# どっちを使う？
`apt update`, `apt upgrade`等のコマンドについては、CLIにて利用する場合は`apt`, 出力をパイプにつなげる用途で利用する場合は`apt-get`という使い分けで決まりかなと思います。
`apt list --installed | grep 〇〇`についてはWARNINGエラーが出るのは気にせず、今後も使い続けようかなと思います。
出力が変わって想定した結果にならなくてもそこまでインパクトがないような用途なので。打ち込むコマンドの文字数が増えることのほうが面倒だなということで。

# 参考
https://itsfoss.com/apt-vs-apt-get-difference/
https://mvogt.wordpress.com/2014/04/04/apt-1-0/