mattintosh note

Hello Raspberry Pi!

電子書籍の情報を Elasticsearch で収集する

Raspberry Pi Elasticsearch の検証用に色々とデータを収集。

最近 Amazon プライムで色々と漫画を見てるのだけど、他のストアではどうなんだろうなと思って電子書籍のランキングなんかを拾ってきてる。

ストアによってランキングから拾える情報が異なるため、ストア間の値の紐付けもしないといけないんだけどまだそこまでは手が回っていない。例えば Google Play にはランキングページに出版社情報が無いため、書く書籍のページも巡回しなきゃいけない、など。また、単に電子書籍で漫画と言ってもカテゴリが細かく分かれているのでその辺りの調査も必要だったりする。

Amazon はランキングの更新間隔が1時間と公表されているので毎日よく変動していて、週刊誌の発売(公開)日は特に変動が激しい。逆に Google Play は1日1回程度とあまり変動は見られない。

Amazon は期間限定無料配信をよくやっているので「お、これちょっと読んでみたかったんだよな」と、割と役に立っている。

最近はどのストアを見ても「転スラ」が上位にランクインしていて人気あるのだなぁと感じる。(自分も全巻揃えた)

f:id:mattintosh4:20190109223612p:plain
Elasticsearch/Kibana - Amazon Books

f:id:mattintosh4:20190109223519p:plain
Elasticsearch/Kibana - App Store Books

f:id:mattintosh4:20190109223746p:plain
Elasticsearch/Kibana - Google Play Books

リモートの IP を拾っている部分があるのは API サーバの仕様調査のため。一般に公開されている情報ではないので経験談だが、App StoreiTunes Search APICDN の振り分けで「キャッシュ有り」と「キャッシュ無し」のどこに繋ぎに行くかわからず、ただ単にクローリングしただけでは正しい結果にならない可能性がある(同じ日本国内の同じタイミングでも A さんが見ているランキング結果と B さんが見ているランキング結果が異なることがあるということ)。キャッシュを回避する問い合わせ方法もあるけどそちらは多分推奨されていない。

とりあえずいまはストアごとにクローラーを作ってデータを拾ってこれるかどうか実験中。それが終わったらインデックスの設計やらなんやら考えて、ゆくゆくは電子書籍の新刊情報や無料配信中の情報なんかを全ストアまとめて見れるようなものを作る予定。

最近ようやく Elasticsearch のことがなんとなくわかるようになってきたのでセミナーにでも行って情報収集してみようかな。

Raspberry Pi で Elasticsearch と Kibana

AWS Elasticsearch Service をお試してで使ってみたけど用途に対してコスパが悪いので、余ってる Raspberry Pi 3 Model B で運用することにした。Elasticsearch と Kibana を1台の Raspberry Pi 3 Model B で稼働させるのは重いので現在は ASUS Tinker Board や PINE64 Rock64 4GB を使ったり、Kibana だけ手元の Ubuntu で実行していたりする。

各種バージョン

Elasticsearch や Kibana は依存関係のバージョンが厳しいので(例えば Node.js のバージョンが 8.15.0 だと動かない、など)今回は下記の通りに合わせる。Java は Elasticsearch、Node.js は Kibana で使用する。

  • Elasticsearch: 6.5.2
  • OpenJDK: 1.8.0
  • Kibana: 6.5.2
  • Node.js: 8.14.0
  • curator: 5.6.0

Elasticsearch のセットアップ

Debian 系で Elasticsearch を使う場合は DEB パッケージを使うか、MACOS/LINUX 用の TAR を解凍して使う方法がある。今回は保存用のストレージ等も分けるので TAR ファイルを使う方法にする。

Java Runtime Environment 8 をインストールする。特に Java で開発する予定もないのでヘッドレス版。

※そのうち直るかもしれないが、openjdk-8-jre-headless のインストール後処理でエラーが発生する。もう一度 openjdk-8-jre-headless をインストールすれば正常に終了する。

sudo apt-get update
sudo apt-get install openjdk-8-jre-headless

Elasticsearch をダウンロードする。

wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.5.2.tar.gz
tar xf elasticsearch-6.5.2.tar.gz

elasticsearch-6.5.2/config/jvm.optionsJVM のメモリ設定を変更する。Raspberry Pi 3 Model B はメモリが 1 GB なので 512 MB くらいにしておく。

#-Xms1g
#-Xmx1g
-Xms512m
-Xmx512m

Elasticsearch の設定を elasticsearch-6.5.2/config/elasticsearch.yml で行う。xpack.ml.enabled: false の設定が無いと起動しない。localhost 以外からのアクセスも許可するので transport.hosttransport.tcp.port を設定する。

xpack.ml.enabled: false
network.host: 0.0.0.0
http.port: 9200
transport.host: localhost
transport.tcp.port: 9300

Elasticsearch を起動する。起動まで数分かかる。

elasticsearch-6.5.2/bin/elasticsearch

localhost:9200 にアクセスして Elasticsearch が起動しているか確認する。Raspberry Pi では avahi-daemon が有効になっているのでクライアントが対応していれば raspberrypi.local:9200 でもアクセスできる

curl localhost:9200
{
  "name" : "Z0Eokyo",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "NV6kGw3iQBiF7voqb6tIcA",
  "version" : {
    "number" : "6.5.2",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "9434bed",
    "build_date" : "2018-11-29T23:58:20.891072Z",
    "build_snapshot" : false,
    "lucene_version" : "7.5.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}

Kibana のセットアップ

Kibana には ARM 版が無いので Linux x86_64 版をダウンロードする。

wget https://artifacts.elastic.co/downloads/kibana/kibana-6.5.2-linux-x86_64.tar.gz
tar xf kibana-6.5.2-linux-x86_64.tar.gz

こちらもアクセス制限は設けないので kibana-6.5.2-linux-x86_64/config/kibana.ymlserver.host: 0.0.0.0 を設定する。

server.host: 0.0.0.0

Raspberry Pi などの ARM デバイスで Kibana を使う場合、同梱されている Node.js が x86_64 用だったりするので Node.js を別途用意する必要がある。ネットで一通り見た感じ「node/bin/node をバックアップして…」とか書かれているが、あまり好きな方法ではないかな。

kibana-6.5.2-linux-x86_64/bin/kibana を見てみると、自動で node ファイルを探すようになっているが、実行できなければ which で他の場所にある node ファイルを探しに行くようになっている。

#!/bin/sh
SCRIPT=$0

# SCRIPT may be an arbitrarily deep series of symlinks. Loop until we have the concrete path.
while [ -h "$SCRIPT" ] ; do
  ls=$(ls -ld "$SCRIPT")
  # Drop everything prior to ->
  link=$(expr "$ls" : '.*-> \(.*\)$')
  if expr "$link" : '/.*' > /dev/null; then
    SCRIPT="$link"
  else
    SCRIPT=$(dirname "$SCRIPT")/"$link"
  fi
done

DIR="$(dirname "${SCRIPT}")/.."
NODE="${DIR}/node/bin/node"
test -x "$NODE" || NODE=$(which node)
if [ ! -x "$NODE" ]; then
  echo "unable to find usable node.js executable."
  exit 1
fi

NODE_ENV=production exec "${NODE}" $NODE_OPTIONS --no-warnings "${DIR}/src/cli" ${@}

で、同梱されている node 実行ファイルは ARM 上では実行できない。

$ node/bin/node
-bash: node/bin/node: cannot execute binary file: Exec format error

同梱されている node は使わないので実行権限を削除する。

chmod -x kibana-6.5.2-x86_64/node/bin/node

https://nodejs.org/dist/v8.14.0/ からデバイスに合ったバイナリをダウンロードする。

wget https://nodejs.org/dist/v8.14.0/node-v8.14.0-linux-armv7l.tar.xz
tar xf node-v8.14.0-linux-armv7l.tar.xz

Node.js のインストールは下記のようなインストールスクリプトを使う方法もあるが、Kibana が Node.js のバージョンをチェックしているため、APT でアップデートが発生すると動かなくなってしまう可能性があり、Kibana との組み合わせではこの方法は向いていないと思われる。

curl -sL https://deb.nodesource.com/setup_8.x | bash -
apt-get install -y nodejs

node にパスを通して Kibana を起動する。

PATH=$HOME/node-v8.14.0-linux-armv7l/bin:$PATH kibana-6.5.2-x86_64/bin/kibana

Python でプログラムを書く

Python 3 用の PIP をインストールする。

sudo apt-get install python3-pip

今回はユーザ環境でしか使わないので ~/.config/pip/pip.conf を下記のように設定しておく。「GPIO にアクセスするのに root 権限必要なんじゃ!」っていうデバイスの倍は sudo でどうぞ。

[global]
user = true

PIP をアップグレードする。

pip3 install -U pip

PATH を通しておく。

PATH=$HOME/.local/bin:$PATH

Python 3 用の elasticsearch モジュールをインストールする。

pip3 install elasticsearch

まずは簡単に CPU の温度を投げるだけのプログラムを書いてみる。Pythonタイムゾーンを扱う場合、datetime.now(timezone(timedelta(hours=+9))) と書くのが最初は少々面倒に感じるが、慣れれば定型文のように感じる。

とりあえずデータを投げる場合

#!/usr/bin/env python3

from elasticsearch import Elasticsearch
from datetime import datetime, timedelta, timezone

es = Elasticsearch('localhost:9200')
with open('/sys/class/thermal/thermal_zone0/temp') as f:
    timestamp, cpu_temp = datetime.now(timezone(timedelta(hours=+9))), int(f.read())
body = {
    '@timestamp': timestamp.isoformat(),
    'temperature': cpu_temp,
}
response = es.index(index='foo', doc_type='_doc', body=body)
print(response)
{'_version': 1, '_type': '_doc', 'result': 'created', '_seq_no': 0, '_index': 'foo', '_shards': {'failed': 0, 'total': 2, 'successful': 1}, '_id': 'RFfzK2gBykMjt7Ru8Nx9', '_primary_term': 1}

インデックスのセッティングとマッピングを追加する場合はこんな感じ。実際には毎回データを投げるわけではなく elasticsearch.helpers を使って1秒間隔で取得したデータを60秒間隔でまとめて Elasticsearch に投げるようにしている。

セッティングとマッピングを行う場合

#!/usr/bin/env python3

from elasticsearch import Elasticsearch
from datetime import datetime, timedelta, timezone
import socket

hostname = socket.gethostname()
es = Elasticsearch('localhost:9200')

# CPU の温度を取得
with open('/sys/class/thermal/thermal_zone0/temp') as f:
    timestamp, cpu_temp = datetime.now(timezone(timedelta(hours=+9))), int(f.read())

# インデックス名の生成(logstash-%Y.%m.%d と同書式)
es_index = '-'.join([hostname, timestamp.strftime('%Y.%m.%d')])

# インデックス作成
if not es.indices.exists(index=es_index):
    es_setting = {
        'settings': {
            'number_of_shards'  : 1,
            'number_of_replicas': 0,
        }
    }
    es_mapping = {
        '_doc': {
            '_all': {
                'enabled': False,
            }
        }
    }
    es.indices.create(index=es_index, body=es_setting)
    es.indices.put_mapping(index=es_index, doc_type='_doc', body=es_mapping)

# ポストデータ作成
es_body = {
    '@timestamp': timestamp.isoformat(),
    'hostname'  : hostname,
    'name'      : 'temperature',
    'value'     : cpu_temp,
}

# ポスト
response = es.index(index=es_index, doc_type='_doc', body=es_body)

print(response)

elasticsearch.helpers で Bulk API

適当に書いたので真似しない方がいいかもしれない。

#!/usr/bin/env python3

from datetime import datetime, timedelta, timezone
from elasticsearch import Elasticsearch, helpers
from time import sleep
import socket

hostname = socket.gethostname()
es = Elasticsearch()

def getCpuTemp():
    with open('/sys/class/thermal/thermal_zone0/temp') as f:
        timestamp, temp = datetime.now(timezone(timedelta(hours=+9))), int(f.read())
    return timestamp, temp

data = []
while True:
    timestamp, cpu_temp = getCpuTemp()
    es_index = '-'.join([hostname, timestamp.strftime('%Y.%m.%d')])
    if not es.indices.exists(index=es_index):
        es.indices.create(index=es_index, body={'settings':{'number_of_shards': 1, 'number_of_replicas': 0}})
        es.indices.put_mapping(index=es_index, doc_type='_doc', body={'_doc':{'_all':{'enabled': False}}})
    source = {
        '@timestamp' : timestamp.isoformat(),
        'hostname'   : hostname,
        'temperature': cpu_temp,
    }
    data.append({
        '_index' : es_index,
        '_type'  : '_doc',
        '_source': source,
    })
    if len(data) >= 60:
        try:
            helpers.bulk(es, data)
            data = []
        except:
            pass
    sleep(1)

X-Pack Monitoring を無効にする

f:id:mattintosh4:20190108163654p:plain
Elasticsearch - X-Pack Monitoring

Monitoring を使うと細かくヘルスチェックデータを保存してくれるけど Raspberry Pi 3 Model B ではそれ自体が重い(CPU クロックが常に上がりっぱなし)。しかもインデックスのサイズが毎日 900 MB くらいになる。

クラスタを組んでいるわけでもないし、個人で使う分には必要ないので X-Pack Monitoring を無効にする。

elasticsearch-6.5.2/config/elasticsearch.yml

xpack.monitoring.enabled: false

家の外からのアクセス

家の中であればプライベート IP アドレスで問題ないんだけど、外でちょっと人に見せたりとかする場合に。めんどくさくて家には VPN 入れてないので SSH でやっている。SSH のローカルフォワードで Elasticsearch と Kibana を動かしている Raspberry Pi にそれぞれ接続している。

例えば Elasticsearch が入った Raspberry Pi192.168.1.1、Kibana が入った Raspberry Pi192.168.1.2 であれば下記のように ssh_config を設定すればよい。

Host home-bastion
    Hostname XXX.XXX.XXX.XXX
    Port XXXXX
    LocalForward 9200 192.168.1.1:9200
    LocalForward 5601 192.168.1.2:5601

これで手元の Ubuntu からは curllocalhost:9200 にアクセスすれば Elasticsearch に繋がるし、ブラウザで localhost:5601 にアクセスすれば Kibana に繋がる。

Amazon Elasticsearch Service 6.x 用に curator をインストールする

容量削減のためインデックス自動削除に curator を導入することにした。

Amazon Elasticsearch Service のバージョンは「6.2.3」。EC2 インスタンスの AMI は「Ubuntu Server 18.04 LTS (HVM), SSD Volume Type - ami-07ad4b1c3af1ea214」。

$ curl -sq 'https://search-XXXX-XXXX-XXXXXXXXXXXXXXXXXXXXXXXXXX.ap-northeast-1.es.amazonaws.com'
{
  "name" : "_XXXXXX",
  "cluster_name" : "XXXXXXXXXXXX:XXXX-XXXX",
  "cluster_uuid" : "XXXXXXXXXXXXXXXXXXXXXX",
  "version" : {
    "number" : "6.2.3",
    "build_hash" : "XXXXXXX",
    "build_date" : "2018-07-16T10:43:54.041989Z",
    "build_snapshot" : false,
    "lucene_version" : "7.2.1",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}
$ cat /etc/ec2_version 
Ubuntu 18.04.1 LTS (Bionic Beaver)

標準の APT でインストール出来る elasticsearch-curator はバージョンが 5.2.0 で、Amazon Elasticsearch Service 6.2.3 とは互換性エラーが発生するため 5.6.0 をインストールする必要があった。

www.elastic.co

DEB パッケージからインストールする場合

$ wget 'https://packages.elastic.co/curator/5/debian9/pool/main/e/elasticsearch-curator/elasticsearch-curator_5.6.0_amd64.deb'
$ sudo dpkg -i elasticsearch-curator_5.6.0_amd64.deb

リポジトリを登録してインストールする場合

$ wget -qO - https://packages.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
$ echo 'deb [arch=amd64] https://packages.elastic.co/curator/5/debian stable main' | sudo tee /etc/apt/sources.list.d/curator.list
deb [arch=amd64] https://packages.elastic.co/curator/5/debian stable main
$ sudo apt-get update
$ sudo apt-get install elasticsearch-curator

pip3 でインストールする場合

pip3 でも 5.6.0 がインストール可能だったので試してみたところ特に問題なかった。

$ pip3 install elasticsearch-curator

curator_cli でのテスト

curator_cli でひとまずインデックスが拾えるかどうかテストする。

Usage: curator_cli [OPTIONS] COMMAND [ARGS]...

Options:
  --config PATH       Path to configuration file. Default:
                      ~/.curator/curator.yml
  --host TEXT         Elasticsearch host.
  --url_prefix TEXT   Elasticsearch http url prefix.
  --port TEXT         Elasticsearch port.
  --use_ssl           Connect to Elasticsearch through SSL.
  --certificate TEXT  Path to certificate to use for SSL validation.
  --client-cert TEXT  Path to file containing SSL certificate for client auth.
  --client-key TEXT   Path to file containing SSL key for client auth.
  --ssl-no-validate   Do not validate SSL certificate
  --http_auth TEXT    Use Basic Authentication ex: user:pass
  --timeout INTEGER   Connection timeout in seconds.
  --master-only       Only operate on elected master node.
  --dry-run           Do not perform any changes.
  --loglevel TEXT     Log level
  --logfile TEXT      log file
  --logformat TEXT    Log output format [default|logstash|json].
  --version           Show the version and exit.
  --help              Show this message and exit.

Commands:
  alias             Add/Remove Indices to/from Alias
  allocation        Shard Routing Allocation
  close             Close Indices
  delete_indices    Delete Indices
  delete_snapshots  Delete Snapshots
  forcemerge        forceMerge Indices (reduce segment count)
  open              Open Indices
  replicas          Change Replica Count
  restore           Restore Indices
  rollover          Rollover Index associated with Alias
  show_indices      Show Indices
  show_snapshots    Show Snapshots
  shrink            Shrink Indices to --number_of_shards
  snapshot          Snapshot Indices

Amazon Elasticsearch Service は 9200 番ポートではなく 443 番ポートだが --host https:// であれば --port 443--use_ssl の指定が無くてもいいらしい。

$ curator_cli --host https://search-XXXX-XXXX-XXXXXXXXXXXXXXXXXXXXXXXXXX.ap-northeast-1.es.amazonaws.com show_indices
.kibana
 :
 :
$ curator_cli --host search-XXXX-XXXX-XXXXXXXXXXXXXXXXXXXXXXXXXX.ap-northeast-1.es.amazonaws.com --port 443 --use_ssl show_indices
.kibana
 :
 :

curator でテスト

~/.curator/curator.yml を作成。テストなので項目は最低限で済ませる。

client:
  hosts:
    - search-XXXX-XXXX-XXXXXXXXXXXXXXXXXXXXXXXXXX.ap-northeast-1.es.amazonaws.com:443
  use_ssl: True

~/.curator/delete_indices.yml を作成。logstash- で始まる日付ベースのインデックスを1日分残して削除する。

actions:
  1:
    action: delete_indices
    description: delete old logstash indexes.
    options:
      disable_action: False
      ignore_empty_list: True
    filters:
    - filtertype: pattern
      kind: prefix
      value: logstash-
    - filtertype: age
      source: name
      direction: older
      timestring: '%Y.%m.%d'
      unit: days
      unit_count: 1

テストなので --dry-run で実行。今日は 2018-11-21 なので 2018-11-20 のインデックスが削除される。

$ curator --dry-run ~/.curator/delete_indices.yml 
2018-11-21 22:20:39,436 INFO      Preparing Action ID: 1, "delete_indices"
2018-11-21 22:20:39,494 INFO      Trying Action ID: 1, "delete_indices": delete old logstash indexes.
2018-11-21 22:20:39,600 INFO      DRY-RUN MODE.  No changes will be made.
2018-11-21 22:20:39,600 INFO      (CLOSED) indices may be shown that may not be acted on by action "delete_indices".
2018-11-21 22:20:39,600 INFO      DRY-RUN: delete_indices: logstash-2018.11.20 with arguments: {}
2018-11-21 22:20:39,600 INFO      Action ID: 1, "delete_indices" completed.
2018-11-21 22:20:39,600 INFO      Job completed.

あとは保持期間を本来の運用に合わせて cron に登録しておく。


以下、elasticsearch-curator 5.2.0 での検証結果。

標準のリポジトリから elasticsearch-curator パッケージをインストール。

$ sudo apt-get install elasticsearch-curator
$ curator_cli --version
curator_cli, version 5.2.0

互換性エラーが発生した。

$ curator_cli show_indices
2018-11-21 20:33:05,764 ERROR     Elasticsearch version 6.2.3 incompatible with this version of Curator (5.2.0)
Traceback (most recent call last):
  File "/usr/bin/curator_cli", line 11, in <module>
    load_entry_point('elasticsearch-curator==5.2.0', 'console_scripts', 'curator_cli')()
  File "/usr/lib/python2.7/dist-packages/curator/curator_cli.py", line 5, in main
    cli(obj={})
  File "/usr/lib/python2.7/dist-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python2.7/dist-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/lib/python2.7/dist-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python2.7/dist-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/curator/singletons.py", line 531, in show_indices_singleton
    client = get_client(**c_args)
  File "/usr/lib/python2.7/dist-packages/curator/utils.py", line 800, in get_client
    'Error: {0}'.format(e)
elasticsearch.exceptions.ElasticsearchException: Unable to create client connection to Elasticsearch.  Error: Elasticsearch version 6.2.3 incompatible with this version of Curator (5.2.0)

Version Compatibility | Curator Reference [5.2] | Elastic を確認してみると Curator 5.2 は ES 5.x 系までの記載しかなかった。

f:id:mattintosh4:20181121203926p:plain

2018-11-21 時点の現行バージョンは 5.6.0 なのでそっちならいけるかと思い確認してみと注釈に AWS ES (which is different from installing Elasticsearch on your own EC2 instances) version 5.3 officially supports Curator. とは書いてあるが AWS ES 6.2 に関する記載は無かった。

f:id:mattintosh4:20181121204905p:plain

NanoPi-NEO2 で MIB の変換ができない

YAMAHA WLX202 が来たので snmpwalk でデータを取ってみたりしてるんだけど変換されない。というかエラーがゴソゴソと出る。

X86_64 Ubuntu には snmp-mib-downloader パッケージがあるけど NanoPi-NEO2 の aarch64 Ubuntu のパッケージリストには出てこない。APT のリポジトリを弄ったせいか?

アーカイブ見てみたらパッケージはあるので手動でインストールすることにした。

依存関係の smistrip を入れておく。

$ sudo apt-get install smistrip

snmp-mibs-downloaderDEB パッケージを拾ってきてインストールする。

$ wget 'http://jp.archive.ubuntu.com/ubuntu-ports/pool/multiverse/s/snmp-mibs-downloader/snmp-mibs-downloader_1.1+nmu1_all.deb'
$ sudo dpkg -i 'snmp-mibs-downloader_1.1+nmu1_all.deb'

テスト。

$ snmptranslate -m all .1.3.6.1.2.1.2.2.1.2
IF-MIB::ifDescr

fluentd で使うので実際は MIB の変換ができるかどうかは重要ではなかったりする。

いまの Kibana には Serial Differencing Aggregation というのがあるので IfInOctets/IfOutOctets などの総計から時系列で差分を計算してくれるらしい。欠点(?)として最初のポイントは差分が無いので必ず 0 になってしまう。回避方法はありそうだけど時間がないのでとりあえずこれでいいや。

f:id:mattintosh4:20181113013256p:plain

NanoPi NEO2 の APT サーバを JP サーバに変更

パッケージのアップデートしようと思ったらハッシュ不一致とか出るのでサーバ変更。

デフォルトの /etc/apt/source.list ではサーバは http://ports.ubuntu.com に設定されている。

# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
# newer versions of the distribution.

deb http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted

## Major bug fix updates produced after the final release of the
## distribution.
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted

## Uncomment the following two lines to add software from the 'universe'
## repository.
## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team. Also, please note that software in universe WILL NOT receive any
## review or updates from the Ubuntu security team.
deb http://ports.ubuntu.com/ubuntu-ports/ xenial universe
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial universe
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates universe
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates universe

## N.B. software from this repository may not have been tested as
## extensively as that contained in the main release, although it includes
## newer versions of some applications which may provide useful features.
## Also, please note that software in backports WILL NOT receive any review
## or updates from the Ubuntu security team.
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted

deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security universe
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security universe
deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security multiverse
deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security multiverse

http://jp.archive.ubuntu.com で ARM バイナリのミラーを提供しているとのことなのでこちらを利用させていただく。

$ sudo gzip /etc/apt/sources.list
$ gzip -dc /etc/apt/sources.list.gz | sed '/^deb/s|ports.ubuntu.com|jp.archive.ubuntu.com|' | sudo tee /etc/apt/sources.list

差分。

--- /dev/fd/63   2018-11-10 16:59:09.349566783 +0900
+++ sources.list  2018-11-10 16:58:16.946964003 +0900
@@ -1,35 +1,35 @@
 # See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
 # newer versions of the distribution.
 
-deb http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted
-deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted
+deb http://jp.archive.ubuntu.com/ubuntu-ports/ xenial main restricted
+deb-src http://jp.archive.ubuntu.com/ubuntu-ports/ xenial main restricted
 
 ## Major bug fix updates produced after the final release of the
 ## distribution.
-deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted
-deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted
+deb http://jp.archive.ubuntu.com/ubuntu-ports/ xenial-updates main restricted
+deb-src http://jp.archive.ubuntu.com/ubuntu-ports/ xenial-updates main restricted
 
 ## Uncomment the following two lines to add software from the 'universe'
 ## repository.
 ## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
 ## team. Also, please note that software in universe WILL NOT receive any
 ## review or updates from the Ubuntu security team.
-deb http://ports.ubuntu.com/ubuntu-ports/ xenial universe
-deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial universe
-deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates universe
-deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates universe
+deb http://jp.archive.ubuntu.com/ubuntu-ports/ xenial universe
+deb-src http://jp.archive.ubuntu.com/ubuntu-ports/ xenial universe
+deb http://jp.archive.ubuntu.com/ubuntu-ports/ xenial-updates universe
+deb-src http://jp.archive.ubuntu.com/ubuntu-ports/ xenial-updates universe
 
 ## N.B. software from this repository may not have been tested as
 ## extensively as that contained in the main release, although it includes
 ## newer versions of some applications which may provide useful features.
 ## Also, please note that software in backports WILL NOT receive any review
 ## or updates from the Ubuntu security team.
-deb http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
-deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
+deb http://jp.archive.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
+deb-src http://jp.archive.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
 
-deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted
-deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted
-deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security universe
-deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security universe
-deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security multiverse
-deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security multiverse
+deb http://jp.archive.ubuntu.com/ubuntu-ports/ xenial-security main restricted
+deb-src http://jp.archive.ubuntu.com/ubuntu-ports/ xenial-security main restricted
+deb http://jp.archive.ubuntu.com/ubuntu-ports/ xenial-security universe
+deb-src http://jp.archive.ubuntu.com/ubuntu-ports/ xenial-security universe
+deb http://jp.archive.ubuntu.com/ubuntu-ports/ xenial-security multiverse
+deb-src http://jp.archive.ubuntu.com/ubuntu-ports/ xenial-security multiverse

整形して並べるとこんな感じ。

deb      http://jp.archive.ubuntu.com/ubuntu-ports/  xenial            main        restricted
deb-src  http://jp.archive.ubuntu.com/ubuntu-ports/  xenial            main        restricted
deb      http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-updates    main        restricted
deb-src  http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-updates    main        restricted
deb      http://jp.archive.ubuntu.com/ubuntu-ports/  xenial            universe
deb-src  http://jp.archive.ubuntu.com/ubuntu-ports/  xenial            universe
deb      http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-updates    universe
deb-src  http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-updates    universe
deb      http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-backports  main        restricted
deb-src  http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-backports  main        restricted
deb      http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-security   main        restricted
deb-src  http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-security   main        restricted
deb      http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-security   universe
deb-src  http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-security   universe
deb      http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-security   multiverse
deb-src  http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-security   multiverse

短い方が管理しやすいかな。

$ gzip /etc/apt/sources.list
$ gzip -dc /etc/apt/sources.list.gz | sed -n '/^deb/s|ports.ubuntu.com|jp.archive.ubuntu.com|p' | column -t | sudo tee /etc/apt/sources.list
deb      http://jp.archive.ubuntu.com/ubuntu-ports/  xenial            main        restricted
deb-src  http://jp.archive.ubuntu.com/ubuntu-ports/  xenial            main        restricted
deb      http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-updates    main        restricted
deb-src  http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-updates    main        restricted
deb      http://jp.archive.ubuntu.com/ubuntu-ports/  xenial            universe
deb-src  http://jp.archive.ubuntu.com/ubuntu-ports/  xenial            universe
deb      http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-updates    universe
deb-src  http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-updates    universe
deb      http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-backports  main        restricted
deb-src  http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-backports  main        restricted
deb      http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-security   main        restricted
deb-src  http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-security   main        restricted
deb      http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-security   universe
deb-src  http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-security   universe
deb      http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-security   multiverse
deb-src  http://jp.archive.ubuntu.com/ubuntu-ports/  xenial-security   multiverse