zshのプロンプト の色を256色で指定する

はじめに

ネットで調べて上位にヒットした方法で色変更できなかったので、macOSで変更する方法をまとめておく
あと備忘録のため、他に入れた便利設定も残しておく

目次

  • 動作テスト環境
  • プロンプトの色変更方法
  • その他補完機能など

動作テスト環境

  • macOS Catalina Version 10.15 Beta

プロンプトの色変更方法

正しい設定

f:id:yuki9431:20191012221229p:plain /etc/zshのPS1を以下のように変更すると上の画像みたいにできる

#PS1="%n@%m %1~ %# "
PS1='%F{196}%n%f:%F{159}%c%f%# '

設定値を軽く説明
%F{256色}hoge%f このように囲むことでhogeの色を指定できる
何色が何番に対応するかは、リンク先のワンライナーで表示できるので参考に
zsh で全 256 色を試しに表示みたい

%nはユーザ名、%cカレントディレクトリを意味する
他にも時間表示やhostnameを表示できる
他のパラメータはマニュアル参照してくさい
The Z Shell Manual

PS1変更してプロファイル再読み込みして確認するのは効率悪いので、私は以下のコマンドで設定を確認した

print -P '%F{196}%n%f:%F{159}%c%f%# ' # 表示確認
macbook_pro:~%  # 表示確認

誤った設定

最初以下のように設定していて、改行位置がおかしなことになった
Linuxだと上手くいくのかね? Linuxは未検証ですが、私のmacOSではこの設定は使えなかった

PS1=$'\e[38;5;196m%n\e[0m:\e[38;5;159m%c\e[0m%# '

その他補完機能など

下記の2行を/etc/zshに追記すると補完機能を強化できる
"ls -" tabキーでオプションを順に選択し、ヘルプも表示できる
万年bash使いだったので、これは便利すぎて涙出た
f:id:yuki9431:20191012221440p:plain

autoload -U compinit
compinit



tab押下時に選択中の項目を塗りつぶす f:id:yuki9431:20191012221354p:plain

zstyle ':completion:*' menu select



コマンド入力ミスの際の類似コマンドの提案

setopt correct



重複コマンドをhistoryに残さない

setopt HIST_IGNORE_DUPS

おわりに

alias等の設定はbashから流用してるので、よければ併せて参考にどうぞ
- macOSの設定ファイルをカスタムして、あなたのCLIライフを幸せに

参考サイト

[Go言語]Linebot最短作成手順

はじめに

Line APIを利用して、自動で天気情報を送信するbotを作成したので
準備から公開までの手順をまとめる。

目次

  • 事前準備
  • LINE Developers プロバイダー登録
  • Messaging APIのチャネル作成
  • Linebotサンプルコードを作成

動作環境

事前準備

LINE Developers プロバイダー登録

  1. Line Developersにアクセスする
  2. Log in 押下
  3. Create New Provider 押下
  4. Provider name : Café com Leite (好きな名前)
  5. Create 押下

Messaging APIのチャネル作成

f:id:yuki9431:20190720170058p:plain

  1. Messaging API チャネル作成する 押下
  2. Messaging APIの情報入力

    • アプリ名: CentOS bot (好きな名前)
    • アプリ説明: Learning Line API
    • 大業種、小業種:個人用なので適当に
    • メールアドレス:hoge@hoge.net
  3. 規約に同意して、作成押下

Linebotサンプルコードを作成

  1. Linebotを載せるサーバ(CentOS)にログインして事前準備

    ```$

     # Goのソース保管ディレクトルに移動
     cd $GOPATH/src
    
     # Linebot用のディレクトリ作成
     mkdir linebot/ && cd linebot/;pwd
    
     # サンプルコード作成 (gitでダウンロードするならスキップ)
     vi linebot.go
    
  2. Line公式のサンプルコードをダウンロード (github)

  3. サンプルコードを少し編集する
    ```go:linebot.go

     package main
    
     import (
         "log"
         "net/http"
         "os"
    
         "github.com/line/line-bot-sdk-go/linebot"
         "github.com/line/line-bot-sdk-go/linebot/httphandler"
     )
    
     func main() {
    
         // CHANNEL_SECRETとCHANNEL_TOKENはLine Developersから取得できる
         handler, err := httphandler.New(
             os.Getenv("CHANNEL_SECRET"),
             os.Getenv("CHANNEL_TOKEN"),
         )
         if err != nil {
             log.Fatal(err)
         }
    
         // Setup HTTP Server for receiving requests from LINE platform
         handler.HandleEvents(func(events []*linebot.Event, r *http.Request) {
             bot, err := handler.NewClient()
             if err != nil {
                 log.Print(err)
                 return
             }
             for _, event := range events {
                 if event.Type == linebot.EventTypeMessage {
                     switch message := event.Message.(type) {
                     case *linebot.TextMessage:
                         if _, err = bot.ReplyMessage(event.ReplyToken, linebot.NewTextMessage(message.Text)).Do(); err != nil {
                             log.Print(err)
                         }
                     }
                 }
             }
         })
         http.Handle("/callback", handler)
    
         //if err := http.ListenAndServe(":"+os.Getenv("PORT"), nil); err != nil {
         //  log.Fatal(err)
         //}
    
         // HTTPではLine APIを利用できないため、HTTPSに変更する 
         // CERT_FILEとKEY_FILEはSSL証明書を発行した後に書き換える
         if err := http.ListenAndServeTLS(":443", "CERT_FILE", "KEY_FILE", nil); err != nil {
             logger.Fatal("ListenAndServe: ", err)
         }
     }
    

ルータとファイアウォールの設定

ファイアウォールが有効な場合は、443ポートの通信を許可する。ファイアウォールの設定は無効にして実施したため、ここでは詳細を割愛する。 また、自宅のサーバで公開する場合は443ポートを開けて、対象サーバにポートフォワーディングするように設定する必要がある。設定方法はルータの機器によって異なるが、自宅のルータ(ヤマハ製)では、下記の通り設定している。

    pp select 1
        ip pp secure filter in 200003 ... 300001
        ip pp nat descriptor 1000

    ip filter 300001 pass * <サーバのローカルIPアドレス> tcp * www,https
    nat descriptor type 1000 masquerade
    nat descriptor masquerade static 1000 105 <サーバのローカルIPアドレス> tcp www,https

SSL証明書取得

SSL証明書は無料のLet's Encryptを使用する。
公式チュートリアルでプラットフォームごとの説明があり、非常わかりやすい。
チュートリアルの通りコマンドを叩けば証明書を発行できる。

証明書の場所とAPI Keyをサンプルコードに追記

  1. Channel ScreatとChannel Tokenの確認方法
    1. Line Developersにアクセスする
    2. プロバイダーリストから対象を選ぶ
    3. チャネル基本設定で確認できる(図を参照) f:id:yuki9431:20190720170149p:plainf:id:yuki9431:20190720170153p:plain
  2. CHANNEL_SECRETとCHANNEL_TOKENを書き換え

    ```go:linebot.go

     //handler, err := httphandler.New(
     //    os.Getenv("CHANNEL_SECRET"),
     //    os.Getenv("CHANNEL_TOKEN"),
     //)
    
     handler, err := httphandler.New(
         "CHANNEL_SECRET",
         "CHANNEL_TOKEN",
     )
    
  3. サーバ証明書の場所を追記する

    ```go:linebot.go

     //if err := http.ListenAndServeTLS(":443", "CERT_FILE", "KEY_FILE", nil); err != nil {
     //    logger.Fatal("ListenAndServe: ", err)
     //}
    
     if err := http.ListenAndServeTLS(
         ":443",
         "/etc/letsencrypt/live/DOMAIN_NAME/fullchain.pem",
         "/etc/letsencrypt/live/DOMAIN_NAME/privkey.pem", nil); err != nil {
         logger.Fatal("ListenAndServe: ", err)
     }
    

稼働確認

  1. サンプルコードをコンパイル&実行する

    ```$

     # カレントディレクトリの確認(linebot配下にいること)
     pwd
    
     # ソースファイルをコンパイルする
     go build
    
     # バックグラウンドでLinebotを実行する
     sudo ./linebot &
    
  2. Line Developersで、サーバのグローバルIPアドレスドメインをWebhookに設定する。
    例:"https://myLinebot.com/callback"

  3. 接続確認を押下して、「成功しました。」と表示されたらOK

  4. プロバイダーページにあるQRコードを手持ちのスマホで読み込んで登録する

  5. メッセージを送信して。鸚鵡返しが来たら成功

おわりに

Linebotを公開するまでに一番苦労するのはネットワーク周りの設定だと思う。
Line APISSL通信しか許可されないからサーバ証明書ドメイン取得が必要だし、少し敷居が高いと感じた。
また、私の場合は同時期にヤマハのRTX1200を自宅に入れたばかりだったため、ポートフォワーディングの設定ができるまで時間がかかった。
ネットワーク周りの設定ができてしまえば、あとはAPIを叩くだけので大した作業はない。
openweatherのAPIと組み合わせて、毎日天気配信をするbotを作成したが、無料アカウントだけでいろいろ試せて非常に楽しかった。(https://github.com/yuki9431/myLinebot)

macOSの設定ファイルをカスタムして、あなたのCLIライフを幸せに

はじめに

普段ターミナルを使用していて気なるところがいくつかあったので、自分好みに変えた。
後先考えずに設定ファイルを増やしたり、変更したりしたので忘れる前にメモ。

目次

  • コマンドのショートカット
  • lsコマンドの出力結果の色変更
  • /etc/bashrcの設定
  • ファイルを任意のアプリで開くコマンドを作成
  • Homebrewインストールとmas-cliのインストール
  • tabキー押下時の警告音と画面点滅をオフにする
  • hostsファイルによく使う接続先の登録

コマンドのショートカット

# general command 
alias ls='ls -G'
alias ll='ls -lG'
alias la='ls -laG'
alias rm='rm -i'
alias cp='cp -i'
alias df='df -h'
alias vi='vim'

# docker command
alias d='docker'
alias dps='docker ps -a'

"/etc/bash_alias"を作成して、ショートカットを設定する。
"ll"と"rm"はの設定は必須だと思う。"ls -G"はlinuxの"ls --color"と同じ意味。

lsコマンドの出力結果の色変更

LSCOLORS=gxfxcxdxbxegedabagacad

"/etc/bash_profile"を作成する。環境変数を設定したい時はここに書く
(例: "export PATH=$PATH:/hoge/hoge")
私は現時点では通したいパスがないので、lsコマンドの色だけ変更してる。
f:id:yuki9431:20190423220049p:plain

/etc/bashrcの設定

[ -r "/etc/bash_alias" ] && . "/etc/bash_alias"
[ -r "/etc/bash_profile" ] && . "/etc/bash_profile"

/etc/bashrcの末尾に2行追記する。これでターミナル起動時に読み込まれる。
あと". /etc/bashrc"で再読み込みできる。

ファイルを任意のアプリで開くコマンドを作成

#!/bin/bash
# vscode <filename>...
#

open ${@:1} -a "Visual Studio Code"

"/usr/local/bin/"配下に自作コマンドを作成します。
(例:"/usr/local/bin/vscode")
macOSではCLIからファイルを開くために、openコマンドが用意されています。
-aオプションを使用すると開きたいをアプリを指定できる。 ("ls /Applications"でアプリ一覧を見られる)
"${@:1}"は1番目以降の引数全てを意味する。(一度に複数ファイルを指定可能にする)

Homebrewインストールとmas-cliのインストール

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install mas

パケットマネージャをインストールする。
Homebrewとmas-climac用のパケットマネージャ。
ターミナルだけでパッケージのインストールができて便利。
特にmas-cliはAppStoreのアプリをまとめてインストールする時に重宝する。

tabキー押下時の警告音と画面点滅をオフにする

ターミナルの設定画面からBellのチェックを外すだけ
f:id:yuki9431:20190423220229p:plain

hostsファイルによく使う接続先の登録

192.168.11.1    router
192.168.11.81   raspberryPi
192.168.11.102  windows10
192.168.11.103  debian

/etc/hostsに上記みたい追記すると、"ssh 192.168.11.103"を"ssh debian"でいけるようになる。
端末が少ないなら、各端末ローカルのhostsに書けばいいと思うが、私の場合は自宅DNSサーバを設置して、そこで一元管理している。

おわりに

仕事でも遊びでも、自分が使いやすいように環境を整えるのは大事だと思う。

自作スクリプトでDDNSのIPアドレスを自動更新する

はじめに

DDNS NowでIPアドレスの自動更新をする方法を紹介します。
DiCEを使用せずに、cronにスクリプトを登録して更新します。
DDNS Now - 無料ダイナミックDNSサービス

スクリプト作成

DDNS Nowの更新方法ページ読んでみると、HTTPリクエストでIPアドレス更新が可能みたいです。

下記のHTTP GETでAレコードの更新が可能です。
https://f5.si/update.php?domain=ユーザ名&password=パスワード&ip=IPアドレス
※「&ip=」を指定しない場合はアクセス元のIPアドレスを自動的に設定できます。
※「パスワード」は平文のパスワードのほかにAPIトークンも使用できます。
https://ddns.kuku.lu/setupinfo.php

上記のURLをスクリプトで叩いてDDNSの更新を行います。

まずは以下のコマンドで稼動確認を行います。
パスワードは平文ではなくAPIトークンで実行することをおすすめします。
APIトークンは詳細ページの一番下にあるのでコピペしてください。

curl -X GET https://f5.si/update.php?domain=ユーザ名\&password=APIトークン
注意点:&をエスケープ処理すること(bashの&はバックグランド処理を意味するため)

以下のように表示されたら成功です。

OK:SUCCESS (good)

エラーコードが表示される場合は、更新方法ページの一番下にエラーコードの内容が書いてありますので、それを参考にURLを修正してください。(私の場合は&をエスケープしなかったためパスワードを送信できていなかった)

稼動確認ができたら、/usr/local/bin/callApiDDNSを作成します

#!/bin/bash 
# IPアドレスを更新する
# /usr/local/bin/callApiDDNS

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
LOGFILE=/var/log/callApiDdns.log

echo -n "/usr/local/bin/callApiDDNS start at `date '+%Y/%m/%d %R'` " >> $LOGFILE
echo -n "Result: " >> $LOGFILE
curl -X GET https://f5.si/update.php?domain=ユーザ名\&password=APIトークン >> $LOGFILE
echo "" >> $LOGFILE
 
exit 0

作成できたら実行権限を付与します。

sudo chmod 755 /usr/local/bin/callApiDDNS

ここでもう一度稼動確認を行います。上手く行けば/var/log/callApiDdns.logにログが吐かれます。

sudo /usr/local/bin/callApiDDNS

ログファイルにOK:SUCCESS (good)と出力されたらOKです。

cronで定期実行

上記のスクリプトを自動で起動するように設定します。
起動時間は任意で変更してください。

sudo vi /etc/cron.d/callApiDDNS
# 毎日01:00に処理を実行する
# m h dom mon dow user  command
0 1    * * *    root    /usr/local/bin/callApiDDNS

編集後は権限を変更して、cronの再起動

sudo chmod 644 /etc/cron.d/callApiDDNS
sudo chown root:root /etc/cron.d/callApiDDNS
sudo service cron restart
sudo service cron status # 再起動確認

ログローテーションの設定

このままでは実行ログが肥大化していくので、logrotateで自動的に削除するようにします。

sudo vi /etc/logrotate.d/callApiDDNS
/var/log/callApiDDNS.log
{
    rotate 4
    weekly
    missingok
    notifempty
}

上記では4週間ログを保持する設定にしてます。それ以上古いものは自動的に削除されます。
最後にテスト実行でエラーが発生しないことを確認できたらOKです。

logrotate -dv /etc/logrotate.d/callApiDDNS

おわりに

今回は簡易なスクリプトにしましたが、エラーコードが返ったときはメール通知する処理を入れた方が丁寧ですね。時間があればメール送信処理を入れてみます。

以上

Raspberry PiにOpenVpnを導入

はじめに

自宅でRaspberry Piを使用してVPN環境を構築できたので、備忘録も兼ねて書いておきます。

使用した物

目次

  • OpenVPN導入
  • ルータの設定変更
  • クライアントの設定

OpenVpn導入

TODO

IPアドレス固定化

IPを固定するには/etc/dhcpcd.confを編集します。

vi /etc/dhcpcd.conf

自分の環境に合わせて、dhcpcd.confを以下のように書きます。

interface eth0  # 対象のNIC(無線ならwlan0)
static ip_address=192.168.11.181/24 # Raspberry Piに割り当てるIPアドレス
static routers=192.168.11.1 # 自宅のルータのIPアドレス
static domain_name_servers=192.168.11.1 # 基本的にはルータのIPアドレスでいい(GoogleのDNSなら8.8.8.8とか)

IPアドレスを設定後は反映させるためにシステム再起動 or ネットワーク再起動をしてください。

sudo service network restart

稼動確認
ifconfigを実施して、IPアドレスが設定されてたらOKです。

ifconfig

OpenVPNインストール & 証明証の発行

OpenVPNをインストールして、証明書と認証鍵を作成します。
PiVPNでしたら、自動でOpenVPNのインストールと証明書認証用の設定をやってくれるので、今回はPiVPNを使用します。 (OpenVPNをインストールして、自前で証明書を発行するやり方もあるがこっちのが簡単)

以下のコマンドを実行すると、PiVPNのインストール画面が表示され
いくつか質問に解答するだけで簡単にOpenVpnを導入できる。

curl -L https://install.pivpn.io | bash

PiVPN公式
Qiita (英語読みたくない人はこちらを参考に)

稼動確認
再起動後、下記のコマンドを実施して、openvpnが稼動していたらとりあず成功

ps -ef | grep vpn

ルータの設定を変更

TODO

  • ポート開放

PiVPNインストール時に設定したポートを開放します。
やり方はルータによって違いますので、google先生に「ルータ型名 ポート開放」と聞いてください。
参考までに私が使用しているBuffaloのルータの設定方法を載せておきます。

手順

  1. ブラウザからルータの設定画面にアクセスする。
  2. [詳細設定]をクリック

    f:id:yuki9431:20190304194829p:plain
    Buffaloルータの設定画面

  3. 左のメニューから[セキュリティー]、[ポート変換]を順にクリック

  4. ポート変換の新規追加の項目を埋める

クライアントの設定

TODO
- ovpnプロファイルの作成
- クライントからVPNサーバ(Raspberry Pi)に接続

ovpnプロファイルの作成

下記コマンドを実施すると、クライント用のプロファイルを作成できます。 ホームディレクトリにovpnファイルができるので、使用したいマシンに転送する。

pivpn add

クライントからVPNサーバ(Raspberry Pi)に接続

ovpnプロファイルをMacスマホに転送後、下記のVPNクライントソフトで接続できるか確認する。
ログファイルは/var/log/openvpn.logに吐かれるので、接続を確認する。

Mac
https://tunnelblick.net

iPhone
https://itunes.apple.com/jp/app/openvpn-connect/id590379981?mt=8

おわりに

私は最初IPv6プラス(IPv4 over IPv6)の環境で稼動させていましたが、時折繋がらないことがありました。(ポート開放を制限されているため)
そのため、IPv4環境に切り替えて稼動させています。 IPv4に切り替えてから、2週間様子を見ていますが今のところ順調です。
また、DDNSの設定を行って様子を見ています。安定稼動が確認できたら載せます。

Windowsマシンで改修したシェルがLinuxサーバで正常に動作しない

事象

Windowsマシンで改修したbashシェルが、Linux環境で上手く動作しない。 

原因

FTPでファイルの送受信をする際の転送モードが適切ではなかった。  

経緯

使用していたFTPソフトの設定の送信モードが自動になっていた。Linuxから元ファイルをダウンロードする際に、ASCIIモードになり、アップロードする際はバイナリモードで送信していた。上記の条件が重なるとLinux側では改行コードではなく文字として認識される。