mutao.net

いわゆる雑記。

GolangでLinebot

Herokuとは

Salesforceの提供するPaaS

価格アプリケーション起動時間の従量課金制。

マスに向けたWebサービスでなければ無料枠を超えるようなことはないと思う。

レンサバも持っていないので今回はHerokuを使っていく。

jp.heroku.com

go-Linebot

github.com

まずはgo.modの初期化をしてline-botsdkをgo getする。

go mod init github.com/${github URL}
go get github.com/line/line-bot-sdk-go/linebot
go mod tidy

一旦はmessage送信できるかどうかを確かめられればいいので、main.goの中身は以下の通り。

package main

import (
    "log"
    "os"
    "github.com/line/line-bot-sdk-go/linebot"
)

func main() {
    bot, err := linebot.New(
        os.Getenv("LINE_BOT_CHANNEL_SECRET"),
        os.Getenv("LINE_BOT_CHANNEL_TOKEN"),
    )
    if err != nil {
        log.Print(err)
    }
        // messageはLINEBOTで通知したい値を入れる。
    message := linebot.NewTextMessage("go-linebot!")
    if _, err := bot.BroadcastMessage(message).Do(); err != nil {
        log.Print(err)
    }
}

Heroku用のProcfileを作成

$ vi Procfile

web: ./bin/${directory_name}

Heroku上で使用するGoのversion指定

2パターンあります。

go.modに

// +heroku goVersion go1.16

と記載するか、環境変数での指定ができます。

### cli
$ heroku config:set GOVERSION 1.16

LINE Messaging APIの設定

developers.line.biz

channel type に Messaging API を指定して作成します。 providerがない場合はプルダウンで「Create a news provider」で作成します。

f:id:mutaonet:20210808171612p:plain

作成が終わったら、channelのBasing settingsから Channel secret tokenをコピーしておきます。Herokuの環境設定で使用します。

Messaging APIタブに移動して、Channel access tokenをコピーしておきます。これもHerokuの環境設定で使用します。

QRコードが表示されているのでLINEの友達追加から読み取って追加しておきます。

これで基本的な設定は完了です。

Herokuの設定

Heroku CLI で設定する場合と、ブラウザから設定する方法があります。

個人的にブラウザでやった方が簡単です。

Heroku CLIで設定する場合

Heroku CLI を installします。

devcenter.heroku.com

$ heroku create ${app name}

$ heroku config:set LINE_BOT_CHANNEL_SECRET ${Channel secret token}
$ heroku config:set LINE_BOT_CHANNEL_TOKEN ${Channel access token}

$ heroku git:remote -a ${app name}

ブラウザ(GUI)から設定する場合。

Herokuにログインしてダッシュボードを開きます。

Heroku

Create new appでapplicationを作成します。 f:id:mutaonet:20210808172738p:plain

f:id:mutaonet:20210808172958p:plain

Settingsタブを開いて環境変数を指定します。

GOVERSION は go.modに記載した場合不要です。 f:id:mutaonet:20210808173950p:plain

Deployタブを開いてGit Hubを選択します。

f:id:mutaonet:20210808173114p:plain

f:id:mutaonet:20210808173210p:plain

Enable Automatic Deploysは指定したブランチにpushすると自動的にbuild & deployが走るので便利です。

Deploy Branchでbuild deployが走ります。

以下のようにBotからメッセージが届けば完了です。 f:id:mutaonet:20210808174158p:plain

とりあえず、動作確認ができたのでDynoを停止します。

停止しとかないと定期的にメッセージがきます。

f:id:mutaonet:20210808174412p:plain

Grafana PrometheusでMySQL監視

f:id:mutaonet:20210727195248p:plain

アーカイブwget

## https://github.com/prometheus/mysqld_exporter/releases/tag/v0.13.0
$ wget https://github.com/prometheus/mysqld_exporter/releases/download/v0.13.0/mysqld_exporter-0.13.0.linux-arm64.tar.gz

$ tar xvzf mysqld_exporter-0.13.0.linux-arm64.tar.gz
$ cd mysqld_exporter-0.13.0.linux-arm64
$ cp mysqld_exporter /usr/local/bin/

mysqld_exporter用のユーザ作成

## see https://github.com/prometheus/mysqld_exporter/#required-grants
$ mysql -h localhost -u {username} -p
CREATE USER 'exporter'@'localhost' IDENTIFIED BY '{password}!';

Service化

$ vi /etc/systemd/system/mysqld-exporter.service 
[Unit]
Description=mysqld_exporter

[Service]
Restart=always
User=exporter ##お好みで
Environment="DATA_SOURCE_NAME=exporter:{password}!@(localhost:3306)/"
ExecStart=/usr/local/bin/mysqld_exporter

[Install]
WantedBy=multi-user.target

## 起動
$ systemctl daemon-reload
$ systemctl start mysqld-exporter.service

prometheus.yml修正

$ vi /etc/prometheus/prometheus.yml
## 以下を追記する。
- job_name: 'mysqld_exporter'
    static_configs:
      - targets: ['localhost:9104']
## Prometheus再起動
$ systemctl restart prometheus

ダッシュボード作成

以下のtemplateをimportしてダッシュボードを作成。

github.com

f:id:mutaonet:20210727194741p:plain

「Load」ボタンを押せばダッシュボードが作成される。

すごいきれいに見れます。

gccコマンド

Linuxを使っているとgccコマンドというのをよく目にする。

実際良くわかっていなかったのでメモする。

まず、GCCとは GNU Compiler Collectionの略でC,C++,Goなどのコンパイラコレクションとのこと。

linuxize.com

gccコマンドはGNU C Compilerの実行ファイルを呼び出すコマンドなので、正確には別物である。

ちなみにCenoOS8では下記のコマンドを実行することで、make gcc g++ などのパッケージをinstallすることが可能。

$ sudo dnf group install "Development Tools"

makeがついてくるのはbuildの過程でgcc g++を使用することが多いためなのではないかなと思う。

www.gnu.org

じゃあJavaはどうなってるんだ

GNU Compiler for Java というものが存在していた。2016年から GCJGCCのtrunckから削除され、GCC7.1のリリースから含まれていない。

gcc.gnu.org

以下のBlogにGCJ削除についてのPOSTがある。

(英語が読めないので翻訳して読みましたが、間違いがあるといけないので深入りしません。) tromey.com

gcj vs javacという感じでパフォーマンスについて言及されたPOSTも見つけたりしてかなり楽しい時間を過ごせました。

RaspberryPiのCPU温度を確認したい

vcgencmdを使って確認します。

www.raspberrypi.org

$ dnf install cmake gcc gcc-c++ make

アップグレード済み:
  cpp-8.4.1-1.el8.aarch64       gcc-8.4.1-1.el8.aarch64       gcc-c++-8.4.1-1.el8.aarch64       libgcc-8.4.1-1.el8.aarch64       libgomp-8.4.1-1.el8.aarch64       libstdc++-8.4.1-1.el8.aarch64       libstdc++-devel-8.4.1-1.el8.aarch64

インストール済み:
  cmake-3.18.2-11.el8_4.aarch64     cmake-data-3.18.2-11.el8_4.noarch     cmake-filesystem-3.18.2-11.el8_4.aarch64     cmake-rpm-macros-3.18.2-11.el8_4.noarch     libuv-1:1.40.0-1.el8.aarch64     vim-filesystem-2:8.0.1763-15.el8.noarch
$ ./buildme --debug
~/work/userland/build/raspberry/debug ~/work/userland
cmake: symbol lookup error: cmake: undefined symbol: archive_write_add_filter_zstd
make: *** ターゲットが指定されておらず, makefile も見つかりません.  中止.
make: *** ターゲット 'install' を make するルールがありません.  中止.

ググるとcmakeで使用するlibarchiveのバージョンが古いとかでした。

github.com

bug reportも見つけました。 bugzilla.redhat.com

https://centos.pkgs.org/8-stream/centos-baseos-x86_64/libarchive-3.3.3-1.el8.x86_64.rpm.html

## https://github.com/ComplianceAsCode/content/issues/7016
$ dnf install libarchive

## 実行
$ ./buildme --aarch64

$ vi /etc/ld.so.conf.d/raspberrypi.conf
## 追記
/opt/vc/bin
$ ldconfig

## PATHを通す
$ vi ~/.bashrc
PATH="/opt/vc/bin:$PATH"
$ source ~/.bashrc

## CPU温度を確認
$ vcgencmd measure_temp
temp=54.0'C

こんなことをしなくても

node_exporterのmetrixで簡単にGrafanaで可視化できます。

metrixはnode_thermal_zone_tempです。

f:id:mutaonet:20210724173318p:plain

mutaonet.hatenablog.com

Grafana Prometheusな環境構築

grafanaをラズパイにinstall

環境

Rasberry Pi4 ModelB

CentOS 8

構築

https://grafana.com/grafana/download?platform=arm

$ wget https://dl.grafana.com/oss/release/grafana-8.0.5-1.aarch64.rpm
$ sudo yum install grafana-8.0.5-1.aarch64.rpm
$ systemctl enable grafana-server
Synchronizing state of grafana-server.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing: /usr/lib/systemd/systemd-sysv-install enable grafana-server
Created symlink /etc/systemd/system/multi-user.target.wants/grafana-server.service → /usr/lib/systemd/system/grafana-server.service.
$ firewall-cmd --zone=public --add-port=3000/tcp --permanent
$ systemctl restart firewalld.service
$ systemctl start grafana-server

デフォルトのログインは root : root でログインできる。

f:id:mutaonet:20210714201109p:plain

node_expoter

https://prometheus.io/download/#node_exporter

 ## documentにあるものだとエラーがでたのでgithubから直接wget
 $ wget https://github.com/prometheus/node_exporter/releases/download/v1.1.2/node_exporter-1.1.2.linux-arm64.tar.gz
 $ tar -xvzf node_exporter-1.1.2.linux-amd64.tar.gz
 
 ## ブラウザ経由でみたい場合firewallを設定する
 $ firewall-cmd --zone=public --add-port=9100/tcp --permanent
 
 $ systemctl restart firewalld.service
 $ ./node_exporter-1.1.2.linux-arm64/node_exporter
level=info ts=2021-07-11T09:35:59.700Z caller=node_exporter.go:178 msg="Starting node_exporter" version="(version=1.1.2, branch=HEAD, revision=b597c1244d7bef49e6f3359c87a56dd7707f6719)"
level=info ts=2021-07-11T09:35:59.700Z caller=node_exporter.go:179 msg="Build context" build_context="(go=go1.15.8, user=root@f07de8ca602a, date=20210305-09:32:30)"
level=warn ts=2021-07-11T09:35:59.700Z caller=node_exporter.go:181 msg="Node Exporter is running as root user. This exporter is designed to run as unpriviledged user, root is not required."
level=info ts=2021-07-11T09:35:59.701Z caller=filesystem_common.go:74 collector=filesystem msg="Parsed flag --collector.filesystem.ignored-mount-points" flag=^/(dev|proc|sys|var/lib/docker/.+)($|/)
level=info ts=2021-07-11T09:35:59.701Z caller=filesystem_common.go:76 collector=filesystem msg="Parsed flag --collector.filesystem.ignored-fs-types" flag=^(autofs|binfmt_misc|bpf|cgroup2?|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|iso9660|mqueue|nsfs|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|selinuxfs|squashfs|sysfs|tracefs)$
 $ curl http://localhost:9100/metrics
 $ mv node_exporter-1.1.2.linux-amd64/node_exporter /usr/local/bin
 
 ## servideファイルを作成する。
 $ vi /etc/systemd/system/node_exporter.service
 [Unit]
Description=Prometheus Node Exporter
Wants=network-online.target
After=network-online.target

[Service]
#User=node_exporter ## お好みのuserを指定
#Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter

[Install]
WantedBy=multi-user.target

Prometheus

https://github.com/prometheus/prometheus/releases/tag/v2.28.1

$ wget https://github.com/prometheus/prometheus/releases/download/v2.28.1/prometheus-2.28.1.linux-arm64.tar.gz
$ tar xvzf prometheus-2.28.1.linux-arm64.tar.gz
$ cd prometheus-2.28.1.linux-arm64
$ ./prometheus --config.file=prometheus.yml
## node_exporterを監視設定に含める
$ vi prometheus.yml
## 追記
  - job_name: 'node_exporter'
    static_configs:
    - targets: ['localhost:9100']
## 配置
$ mv prometheus-2.28.1.linux-arm64/prometheus /usr/local/bin;
$ mv prometheus-2.28.1.linux-arm64/promtool /usr/local/bin;

$ mv prometheus-2.28.1.linux-arm64/prometheus.yml /etc/prometheus/;

$ mv prometheus-2.28.1.linux-arm64/consoles /etc/prometheus/;
$ mv prometheus-2.28.1.linux-arm64/console_libraries /etc/prometheus/;

## Service化
$ vi /etc/systemd/system/prometheus.service
[Unit]
Description=Prometheus
Documentation=https://prometheus.io/docs/introduction/overview/
Wants=network-online.target
After=network-online.target

[Service]
#User=prometheus ## お好みで設定。ここで指定したユーザに/etc/prometheusあたりの権限を付与する。
#Group=prometheus
Type=simple
ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/usr/local/bin/prometheus \
    --config.file=/etc/prometheus/prometheus.yml \
    --storage.tsdb.path=/var/lib/prometheus/ \
    --web.console.templates=/etc/prometheus/consoles \
    --web.console.libraries=/etc/prometheus/console_libraries \
    --web.listen-address=0.0.0.0:9090

SyslogIdentifier=prometheus
Restart=always

[Install]
WantedBy=multi-user.target

f:id:mutaonet:20210714201251p:plain

node_exporterのmetricsをGrafanaで可視化

Prometheusを選択。

f:id:mutaonet:20210714201345p:plain

左メニューからDashboardを作成。

Metrix browserから可視化したいものを選択するだけ。

f:id:mutaonet:20210714201502p:plain

drone-ci構築

drone

Github上のmainブランチへのmergeや、PR作成をhookして.drone.ymlに記載したpipelineを実行する。 build deployなんかができる。詳しくは公式documentを参照。

readme.drone.io

localで構築してみる。

これも公式documentを見るだけでできる。

docker-compose.ymlを作成すれば楽になる。

readme.drone.io

Github OAtuth Appを作成するにはcallback用のパブリックなドメイン(IP)が必要なのでngrokを利用する。

ngrok.com

---
version: '3'

services:
  drone-server:
    image: drone/drone:2
    ports:
      - 8000:80
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - .:/data
    restart: always
    environment:
      - DRONE_GITHUB_SERVER=https://github.com
      - DRONE_GITHUB_CLIENT_ID=XXX
      - DRONE_GITHUB_CLIENT_SECRET=XXX
      - DRONE_RPC_SECRET=XXX # openssl rand -hex 16 で取得したsecret key
      - DRONE_SERVER_HOST=XXX.ngrok.io # ngrokで取得したドメイン
      - DRONE_SERVER_PROTO=https
      - DRONE_TLS_AUTOCERT=true

  drone-agent:
    image: drone/drone:2
    command: agent
    restart: always
    depends_on:
      - drone-server
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - DRONE_RPC_SERVER=http://drone-server
      - DRONE_RPC_SECRET=XXX  # openssl rand -hex 16 で取得したsecret key
      - DRONE_RUNNER_CAPACITY=2
$ docker-compose up

ngrokで取得したURLをブラウザで表示すると以下のようなダッシュボードが見える。

f:id:mutaonet:20210711163907p:plain

適当な.drone.ymlをリポジトリに作成してbuildしてみることで完了。

今回はhello worldするだけの.drone.ymlを作成しました。

f:id:mutaonet:20210711164123p:plain

今後のためのメモ

コンテナ起動後にagent側がclusheし続けること。

問題なくbuildもできるけど、正常な状態ではないので調査したい。

drone-agent_1   | {"level":"fatal","msg":"main: source code management system not configured","time":"2021-07-11T07:40:39Z"}
drone-study_drone-agent_1 exited with code 1
drone-study_drone-agent_1 exited with code 1

ngrokでToo Many Connections

drone2系で起きやすい。1系よりも多くのconnectionを貼るのかもしれない。

安定した環境で入門してみるなら1系の方がいいかもしれない。UIは異なる。

f:id:mutaonet:20210711164337p:plain

ngrok再起動でdocker-compose.ymlを修正しなければならない

DRONE_SERVER_HOST の値を変更する必要がある。以外と手間なのでちゃんとした環境を作りたい。

decleareでエラー

decleareでエラー

bashを使って簡単なscriptを書いたときにエラーが出たので軽くメモ

「decleareでエラー」の語感が好きだったという理由です。

#!/bin/bash
declare -A arr=(
    ["aaa"]="100"
    ["bbb"]="200"
    ["ccc"]="300"
)

for value in ${!arr[@]}; do
   echo ${value} ${arr[${value}]}
done
## 実行
$ ./test.sh
./test.sh: line 2: declare: -A: invalid option
declare: usage: declare [-afFirtx] [-p] [name[=value] ...]
0 300

原因はbashのバージョンが低いから

https://stackoverflow.com/questions/6047648/associative-arrays-error-declare-a-invalid-option

/bin/bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin20)
Copyright (C) 2007 Free Software Foundation, Inc.

brewbashをinstallします。4系からdeclareは使用可能です。

$ brew install bash
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
==> New Formulae
amfora                         ciphey                         envoy@1.17                     git-xargs                      kubeconform                    pythran                        spectra                        wasmtime
argocd-vault-plugin            demumble                       fcp                            jrsonnet                       lexbor                         ronn                           sqsmover                       wxmac@3.0
bosh-cli                       detect-secrets                 frum                           kalker                         multi-git-status               s4cmd                          svgbob
==> Updated Formulae
Updated 1515 formulae.
==> Renamed Formulae
weboob -> woob
==> Deleted Formulae
libinfinity

==> Downloading https://ghcr.io/v2/homebrew/core/bash/manifests/5.1.8
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/bash/blobs/sha256:62569d2e8452dd3cb61168ffc2581193989503f0e419c3cf1c32984d165ce139
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:62569d2e8452dd3cb61168ffc2581193989503f0e419c3cf1c32984d165ce139?se=2021-07-07T03%3A40%3A00Z&sig=JwNonIiglsc99nsyES8%2BocmdDokosd8yyg5tVPC4RpU%3D&sp=r&spr=https&
######################################################################## 100.0%
==> Pouring bash--5.1.8.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/bash/5.1.8: 157 files, 10.9MB

## バージョン確認
$ /usr/local/bin/bash --version
GNU bash, バージョン 5.1.8(1)-release (x86_64-apple-darwin20.3.0)
Copyright (C) 2020 Free Software Foundation, Inc.
ライセンス GPLv3+: GNU GPL バージョン 3 またはそれ以降 <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

shebanをbrewで入れたbashのpathに変更します。

#!/usr/local/bin/bash

## 実行
$ ./test.sh          
bbb 200
ccc 300
aaa 100

Macbash書かないので今更遭遇したエラーでした。書くとしてもサーバで書く。

まぁ書くとしてもzshですよね。