それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

python で日本語のUnicode のコードポイントから平仮名を連番テーブルを作る

python でA-Zみたいに 「ひらがな」をコードポイントで扱う。

f:id:takuya_1st:20190414152203p:plain

tl;dr

>>> [ chr( i+ 0x3042) for i in range(0,85)]
['あ', 'ぃ', 'い', 'ぅ', 'う', 'ぇ', 'え', 'ぉ', 'お', 'か', 'が', 'き', 'ぎ', 'く', 'ぐ', 'け', 'げ', 'こ', 'ご', 'さ', 'ざ', 'し', 'じ', 'す', 'ず', 'せ', 'ぜ', 'そ', 'ぞ', 'た', 'だ', 'ち', 'ぢ', 'っ', 'つ', 'づ', 'て', 'で', 'と', 'ど', 'な', 'に', 'ぬ', 'ね', 'の', 'は', 'ば', 'ぱ', 'ひ', 'び', 'ぴ', 'ふ', 'ぶ', 'ぷ', 'へ', 'べ', 'ぺ', 'ほ', 'ぼ', 'ぽ', 'ま', 'み', 'む', 'め', 'も', 'ゃ', 'や', 'ゅ', 'ゆ', 'ょ', 'よ', 'ら', 'り', 'る', 'れ', 'ろ', 'ゎ', 'わ', 'ゐ', 'ゑ', 'を', 'ん', 'ゔ', 'ゕ', 'ゖ']

解説

chr ( 0x3042 )

これは、以下と同じ

'\u3042'

\u でユニコードにコードポイントであることを示している。

'\u3042'を示したときに、Pythonで内部エンコーディングにデコードされ文字列として格納されている。

文字符号化方式UTF-8/UTF-16エンコードすると、次のようなバイト列になる。

>>> '\u3042'.encode('utf-8')
b'\xe3\x81\x82'
>>> '\u3042'.encode('utf-16')
b'\xff\xfeB0'

ちなみに、内部エンコーディングは次のように確認できる(いまはUTF-8固定かな?たしか)

import sys; sys.getdefaultencoding()

得られたバイト列を、文字列にする

>>> b'\xe3\x81\x82'.decode()
'あ'

ちなみに b'\xxxx' はバイト列であることを示す b です。

UTF-16のバイト列をそのままデコードしてもエラーになります。

>>> b'\xff\xfeB0'.decode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte

内部エンコーディングUTF-8(デフォルト)なので、UTF-16UTF-8としてデコードしようとしてエラーですね。

>>> b'\xff\xfeB0'.decode('utf16')
'あ'

これで、バイト列がUTF-16の符号化として扱われて、デコードされ、Unicodeのコードポイントを得ることが出来て、内部エンコーディング(この場合UTF-8)にデコードされ出力された。

ユニコードのコードポイントを連番で扱う。

あ=0x3042 であることを利用して連番「ひらがな」を作ってみる。

>>> [chr(0x3042+i) for i in range(0,10)]
['あ', 'ぃ', 'い', 'ぅ', 'う', 'ぇ', 'え', 'ぉ', 'お', 'か']

逆に、「あいうえお」をすべてユニコードのコードポイントにしてみる

>>> [ (ord(i)) for i in  "あいうえお"]
[12354, 12356, 12358, 12360, 12362]

見やすいように16進数 Hexにする

>>> [ hex(ord(i)) for i in  "あいうえお"]
['0x3042', '0x3044', '0x3046', '0x3048', '0x304a']

まとめ

chr でユニコードのコードポイント(数字)から、文字へ

>>> chr( 0x3042 )
'あ'
>>> chr( 0x3042 + 1  )
'ぃ'

ord で、文字を数字(int)へ。hex で16進数表記へ

>>> ord('あ')
12354
>>> hex(ord('あ'))
'0x3042'

補足

ユニコードUnicode)のコードポイントは、文字符号の変換表(数字→文字)であり、utf-8utf-16 はその変換した数字をバイナリとしてどうやって保存するかになる。

ユニコードでは、あ=0x3042 である。これはUTF-8でもUTF-16 でも変わらない。ただし、この0x304 をどうやって0/1に落とし込むかで表現方法は変わる。

$(pyenv init -) が遅いので遅延ロードにした

ターミナルの起動が遅い。

最近、妙にターミナルの起動が遅くて苦痛だなと思って調べたら pyenv 関連だった。

rbenv もそうだったし、pyenv もやはり遅い。 rbenv に関してはrbenv init では諦めて、symlink を使って解決しているが pyenv は別の方法を模索した。

pyenv 関連の起動遅いねん

f:id:takuya_1st:20190414143941p:plain f:id:takuya_1st:20190414144043p:plain f:id:takuya_1st:20190414143856p:plain

ああ、わりと時間かかりすぎ。

## init 系を測定してみる
time { 
  ## rb
  eval "$(rbenv init -)"
  ## py
  eval "$(pyenv init -)"
  eval "$(pip completion --bash)"
  eval "$(pipenv --completion)"
}

シェル起動の処理で4秒超えは、ストレス溜まりそう。

f:id:takuya_1st:20190414151002p:plain

ターミナルの起動を早くしたい。

python は使わないこともあるし、ターミナル自体はもっと早く起動してサクサクと使いたい。

lazyload をする方法が紹介されている

ログインシェルの起動を高速化する lazyenv を作った - Qiita

方針としては

  1. pyenv と同名の function pyenv(){} をbashrcに登録する
  2. pyenv 関数内で、自分自身を消す
  3. 消すときに同時にpyenv をちゃんとロードする
  4. 自分自身のかわりにロードしたpyenv を起動する。

これらの関数をpyenv の初期化に変わって実行すると、bashrc 内部で init が行われないので、bashrcの読み込みが、遅くなることはない。

シェルスクリプトで表すとこんな感じ。

pyenv () {
    unset -f pyenv
    pyenv_load_function
    pyenv "$@"
}

上記の関数は、関数名とロード関数名が同じであれば、抽象化できるので、作ろうと思ったら、すでに作ってる人がいた。

使い方

私は、遅延ロードさせる関数を .bashrc.d/ に配置した。

.bashrc

bashrc.d をロードする。

if [[ -d ~/.bashrc.d/ ]]; then
  for i in ~/.bashrc.d/* ; do source $i; done
fi

以下のファイル名にして、layzyenv を先に読み込まれるように設定。

  • .bashrc.d/00-lazyenv.bash
  • .bashrc.d/pyenv-init.bash

.bashrc.d/00-lazyenv.bash

これは、takezoh/lazyenv から取得した。

.bashrc.d/pyenv-init.bash

## 2019-04-13 takuya
## python 関連の設定をまとめる
## lazyload を使って pip を遅延させる
# これをすることでコマンドを実行するまで補完ができなくなるので
# 初回起動まで、補完が出来なかったりする
# なので、一見すると補完が効かないように見えることがあるので注意
## pyenv init -
## pip completion
## pipenv --completion

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
export PYTHONSTARTUP=~/.pythonrc

_pyenv_init() {
  # python 関連の起動遅いから、ここにまとめる

  # pyenv を使う
  if  ( type "$0" > /dev/null 2>&1  ||  [[ -d  ~/.pyenv  ]] ) && [[ $TERM != screen* ]]; then
    ### pyenv
    eval "$(pyenv init -)"
    eval "$(pip completion --bash)"
    eval "$(pipenv --completion)"
    # cmd_is_exists pyenv-virtualenv && eval "$(pyenv virtualenv-init -)"
  fi
}
eval "$(lazyenv.load _pyenv_init pyenv python pip pipenv )"

screen / tmux の起動時は環境変数を引き継ぐので重複処理はしないようにしてたり。

他の似たようなコマンドはどうしたか

nvm / node

これらに関しては、bashrcで読み込む必要もないし、プロジェクト単位で使うことが前提でなので、bashrc から外した。 その後 nvm はあまり使わないことに気づいたのでnvm 自体を外した。

rbenv /ruby

これらに関しては、私が個人的に結構ruby使うのと、brewruby を使ってることもあり、rbenv 自体を外すことは諦めた。それぞれ固定バージョンへのsymlinkを作成してPATHの優先度で対応した。 rbenv init は使わずに済ませた。

phpenv / php

これらに関しては、プロジェクト単位にbashrc を作ることで対応している。

その他の解決方法。

pyenv 自体は、バージョンとコマンド名を解決するものなので、bash 用に専用の pyenv-virtualenv を作り、symlinkしてバージョンを固定。 シェルではロードして利用し、プロジェクトや環境ではプロジェクト環境ごとに pyenv を毎回ロードして使ってもいいかもしれない。

処理後の時間

1秒未満なら、まぁ許容範囲かな。500ms 切りたいとこではあるが。brew の completion 系がたくさんあるのでそれを外すのは難しいし。諦めた。 f:id:takuya_1st:20190414151325p:plain

2019/05/17 追記

pyenv init を見ていて気づいた。

pyenv init を実行してPATH を見ようと実行して気づいたのですが。

pyenv init 自体は、pyenv の別名関数を定義していて、pyenv は遅延ロード的な動作になっている。

他の処理を取り除いた bash や root の bash で pyenv init - するとすごく早い。

もしかしたらpyenv init が遅い原因は、pyenv ではなく、brew など他のパッケージにあるのかもしれない。

# pyenv init -
export PATH="/var/root/.pyenv/shims:${PATH}"
export PYENV_SHELL=sh
command pyenv rehash 2>/dev/null
pyenv() {
  local command
  command="${1:-}"
  if [ "$#" -gt 0 ]; then
    shift
  fi

  case "$command" in
  activate|deactivate|rehash|shell)
    eval "$(pyenv "sh-$command" "$@")";;
  *)
    command pyenv "$command" "$@";;
  esac
}

参考資料

GitHub - takezoh/lazyenv: lazyenv provides the delayed calling function associated with the specified commands.

ログインシェルの起動を高速化する lazyenv を作った - Qiita

Lazy load nvm for faster shell start - Broken By Me

Certbot を自動的に更新するタイマーを設定する。

certbotapache/nginx を殺される。

通常のCertbotだと、DNSのAレコードとHTTP(s)を使って、ドメインの確認を行う。

しかし、web サーバーを不用意にシャットダウンされるのは面倒でした。あとポート転送とかやってたりするとめんどくさいんだよなぁ。

DNS の認証をTXTレコードで行う。

これは以前やりました  → certbotの更新でCloudflareプラグインを使ってDNSの認証を楽にする - それマグで!

自動的に更新する

WEBサーバーをシャットダウン・再起動を行わずに、DNSのTXTレコードでCertbotによる証明書発行ができるたら、最後は自動化です。

systemd のタイマー機能を使う。

今回は、Cronではなくsystemd のタイマー機能を使って自動実行をしようと思います。

編集するファイル

  • 実行するスクリプトファイル /usr/local/sbin/certbot-renewal.sh
  • サービス /etc/systemd/system/certbot-renewal.service
  • タイマー /etc/systemd/system/certbot-renewal.timer
  • /lib/systemd/system/certbot.timer 既存のsystemd certbot の自動実行ジョブ

実行するジョブとして登録するファイルを準備します。

ジョブとして実行するファイルを準備しました。

複数の証明書があるので、スクリプトファイルにまとめています。

/usr/local/sbin/certbot-renewal.sh

#!/usr/bin/env bash

certbot=/home/takuya/certbot/certbot-test/bin/certbot

## cloudflare の場合
CERT_NAME=example.com-wildcard
$certbot  renew --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflareapi.cfg \
  --cert-name $CERT_NAME


## mydns の場合
CERT_NAME=example.com-mydns
mydns=/usr/local/lib/mydns/DirectEdit-master
cmd="$certbot renew --manual --preferred-challenges=dns \
  --cert-name $CERT_NAME\
  --manual-auth-hook $mydns/txtregist.php\
  --manual-cleanup-hook $mydns/txtdelete.php\
  --manual-public-ip-logging-ok"

# echo $cmd
$cmd

systemd にタイマーサービスとして登録します。

新しくファイルを準備します。

/etc/systemd/system/certbot-renewal.service

takuya@:~$ cat  /etc/systemd/system/certbot-renewal.service
[Unit]
Description=Certbot Renewal
Type=oneshot

[Service]
ExecStart=/usr/local/sbin/certbot-renewal.sh

systemd にタイマーを準備します

新しくファイルを準備します。

/etc/systemd/system/certbot-renewal.timer

[Unit]
Description=Certbot を定期的に更新する。

[Timer]
OnBootSec=3000
OnUnitActiveSec=1w

[Install]
WantedBy=multi-user.target

もし、apt などでタイマーがすでに入っていたら止めておきます。

わたしの場合、apt でいれた古いcertbot の設定があったので止めました。

sudo systemctl disable certbot.service
sudo systemctl disable certbot.timer

apt でいれた実際のファイルは次のようになっていました。

service側

takuya@sakura:~$ cat /lib/systemd/system/certbot.service
[Unit]
Description=Certbot
Documentation=file:///usr/share/doc/python-certbot-doc/html/index.html
Documentation=https://letsencrypt.readthedocs.io/en/latest/
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot -q renew
PrivateTmp=true

timer 側

takuya@sakura:~$ cat /lib/systemd/system/certbot.timer
[Unit]
Description=Run certbot twice daily

[Timer]
OnCalendar=*-*-* 00,12:00:00
RandomizedDelaySec=43200
Persistent=true

[Install]
WantedBy=timers.target

あとは登録して実行します。

手動で動かすとき。最初に1度実行して確認しておきます。

sudo systemctl start certbot-renewal.timer

タイマーを有効にする。

 sudo systemctl enable certbot-renewal.timer

これで、しばらく証明書の期限切れに悩まされなくていいですね。

まとめ

letsencrypt は 手軽に証明書が作れるけど、手軽さ故に枚数が増えすぎて管理が煩雑だった。

これらをおこなったことで、管理は楽になったし、枕を高くして寝る事ができそうです。

関連資料

Certbot 関連であれこれやった記事たちです。

参考資料

https://stevenwestmoreland.com/2017/11/renewing-certbot-certificates-using-a-systemd-timer.html

プロジェクト単位のnode_module の実行コマンドの格納場所 .bin

プロジェクトでインストールした node_module の実行コマンドはどこ?

npm -g i とかでいちいちグローバルなんて使ってられないし、プロジェクトの実行環境内で完結させたい。DockerとかデプロイCIとか絡んでくると特にその思いが顕著になる。

./node_modules/.bin

公式に資料が書いてある。

Executables§ When in global mode, executables are linked into {prefix}/bin on Unix, or directly into {prefix} on Windows.

When in local mode, executables are linked into ./node_modules/.bin so that they can be made available to scripts run through npm. (For example, so that a test runner will be in the path when you run npm test.)

サンプル

たまたま手元にあったLaravelで npm i した結果で確認したら、次のように用意されている。

コマンドはここから拾えば動きますね。やったね。

takuya@bookmarklets$ ls -l  node_modules/.bin/
total 0
lrwxr-xr-x 1 takuya staff 18 2019-04-02 16:52 acorn -> ../acorn/bin/acorn
lrwxr-xr-x 1 takuya staff 26 2019-04-02 16:52 ansi-html -> ../ansi-html/bin/ansi-html
lrwxr-xr-x 1 takuya staff 19 2019-04-02 16:52 atob -> ../atob/bin/atob.js
lrwxr-xr-x 1 takuya staff 32 2019-04-02 16:52 autoprefixer -> ../autoprefixer/bin/autoprefixer
lrwxr-xr-x 1 takuya staff 22 2019-04-02 16:52 browserslist -> ../browserslist/cli.js
lrwxr-xr-x 1 takuya staff 34 2019-04-02 16:52 cross-env -> ../cross-env/dist/bin/cross-env.js
lrwxr-xr-x 1 takuya staff 40 2019-04-02 16:52 cross-env-shell -> ../cross-env/dist/bin/cross-env-shell.js
lrwxr-xr-x 1 takuya staff 20 2019-04-02 16:52 cssesc -> ../cssesc/bin/cssesc
lrwxr-xr-x 1 takuya staff 15 2019-04-02 16:52 errno -> ../errno/cli.js
lrwxr-xr-x 1 takuya staff 25 2019-04-02 16:52 esparse -> ../esprima/bin/esparse.js
lrwxr-xr-x 1 takuya staff 28 2019-04-02 16:52 esvalidate -> ../esprima/bin/esvalidate.js
lrwxr-xr-x 1 takuya staff 12 2019-04-02 16:52 he -> ../he/bin/he
lrwxr-xr-x 1 takuya staff 23 2019-04-02 16:52 html-minifier -> ../html-minifier/cli.js
lrwxr-xr-x 1 takuya staff 31 2019-04-02 16:52 import-local-fixture -> ../import-local/fixtures/cli.js
lrwxr-xr-x 1 takuya staff 25 2019-04-02 16:52 js-yaml -> ../js-yaml/bin/js-yaml.js
lrwxr-xr-x 1 takuya staff 18 2019-04-02 16:52 jsesc -> ../jsesc/bin/jsesc
lrwxr-xr-x 1 takuya staff 19 2019-04-02 16:52 json5 -> ../json5/lib/cli.js
lrwxr-xr-x 1 takuya staff 22 2019-04-02 16:52 loose-envify -> ../loose-envify/cli.js
lrwxr-xr-x 1 takuya staff 32 2019-04-02 16:52 miller-rabin -> ../miller-rabin/bin/miller-rabin
lrwxr-xr-x 1 takuya staff 14 2019-04-02 16:52 mime -> ../mime/cli.js
lrwxr-xr-x 1 takuya staff 20 2019-04-02 16:52 mkdirp -> ../mkdirp/bin/cmd.js
lrwxr-xr-x 1 takuya staff 23 2019-04-02 16:52 multicast-dns -> ../multicast-dns/cli.js
lrwxr-xr-x 1 takuya staff 36 2019-04-02 16:52 parser -> ../@babel/parser/bin/babel-parser.js
lrwxr-xr-x 1 takuya staff 27 2019-04-02 16:52 prettier -> ../prettier/bin-prettier.js
lrwxr-xr-x 1 takuya staff 30 2019-04-02 16:52 regexp-tree -> ../regexp-tree/bin/regexp-tree
lrwxr-xr-x 1 takuya staff 25 2019-04-02 16:52 regjsparser -> ../regjsparser/bin/parser
lrwxr-xr-x 1 takuya staff 16 2019-04-02 16:52 rimraf -> ../rimraf/bin.js
lrwxr-xr-x 1 takuya staff 15 2019-04-02 16:52 sass -> ../sass/sass.js
lrwxr-xr-x 1 takuya staff 16 2019-04-02 16:52 sha.js -> ../sha.js/bin.js
lrwxr-xr-x 1 takuya staff 16 2019-04-02 16:52 svgo -> ../svgo/bin/svgo
lrwxr-xr-x 1 takuya staff 22 2019-04-02 16:52 terser -> ../terser/bin/uglifyjs
lrwxr-xr-x 1 takuya staff 25 2019-04-02 16:52 uglifyjs -> ../uglify-js/bin/uglifyjs
lrwxr-xr-x 1 takuya staff 25 2019-04-02 16:52 webpack -> ../webpack/bin/webpack.js
lrwxr-xr-x 1 takuya staff 25 2019-04-02 16:52 webpack-cli -> ../webpack-cli/bin/cli.js
lrwxr-xr-x 1 takuya staff 47 2019-04-02 16:52 webpack-dev-server -> ../webpack-dev-server/bin/webpack-dev-server.js
lrwxr-xr-x 1 takuya staff 18 2019-04-02 16:52 which -> ../which/bin/which

参考資料

https://docs.npmjs.com/files/folders#executables

ubuntu /debian のLTSにphp7.1/php7.2/php8.0/php8.1 などを複数バージョン導入する

Ubuntu 16 LTSのPHPが古い

WindowsのWSLでインストールされる Ubuntu 16 LTS のパッケージがLTSらしく、どれもちょっと古くて困るので、php7.1 php7.2 をapt インストールして使いたい。

LTS だとphpが古い

php5.6 のサポートは終わりました。

php7.0 のサポートも終わりました。

php7.1系ももうすぐ終わりそうです。(終わりました。

wordpressに導入するためには、現行のubuntu/DebianのLTSサポートだとちょっと困る。

php のサポートライン

f:id:takuya_1st:20211129124747p:plain

ubuntu LTS や debian 9 / debian LTS

debian はstable は古いが安定してるというか、長期運用が可能といえど追いついてこないのは本当に困るよね。

配布レポジトリを追加する

debian

eval " $( cat /etc/os-release  )"
sudo wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
sudo  sh -c "echo 'deb https://packages.sury.org/php/ $VERSION_CODENAME main' > /etc/apt/sources.list.d/php.list"
sudo  apt install apt-transport-https ca-certificates
sudi apt update

ubuntu

add-apt-repository ppa:ondrej/php

インストール

パッケージはお好みで。

sudo apt install php7.1-apcu\
 php7.1-bcmath\
 php7.1-cli\
 php7.1-curl\
 php7.1-fpm\
 php7.1-gd\
 php7.1-intl\
 php7.1-imagick\
 php7.1-mcrypt\
 php7.1-mbstring\
 php7.1-mysql\
 php7.1-pgsql\
 php7.1-sqlite3\
 php7.1-xml\
 php7.1-zip\
 php7.1-phpdbg

php8.1 のインストール

sudo apt install \
  php8.1-apcu \
  php8.1-bcmath \
  php8.1-curl \
  php8.1-cli \
  php8.1-common \
  php8.1-dev \
  php8.1-fpm \
  php8.1-gd \
  php8.1-intl \
  php8.1-imagick \
  php8.1-mbstring \
  php8.1-mcrypt \
  php8.1-mysql \
  php8.1-opcache \
  php8.1-sqlite3 \
  php8.1-xml \
  php8.1-xsl \
  php8.1 \
;

デフォルトのphpを設定する。

いきなり全部あげてしまうと影響もあるし、デフォルトのphpコマンドのバージョンを固定してしまってもいいだろう。

sudo update-alternatives --set php /usr/bin/php8.0

任意のバージョンを使う。

$ php7.0 -i 
$ php7.4 -i 
$ php8.0 -i 
$ php8.1 -i 

phpのモジュールを有効・無効を切り替える

有効化

phpenmod -v 7.0 imap
phpenmod -v 8.0 imap

無効化

phpdismod -v 7.0 imap
phpdismod -v 8.0 imap

任意のPECL/PEARバージョンを入れる。

PEAR/PECL のモジュールは、バージョン共通のパッケージを使う。

apt install php-pear

ビルドして、PECLのパッケージを有効化する。

たとえば、pam のパッケージをビルドして使う場合。

sudo apt install php8.1-dev
wget https://pecl.php.net/get/pam-2.2.3.tgz
tar zxvf pam-2.2.3.tgz
cd pam-2.2.3
phpize8.1
./configure 
make 
sudo make install 
phpenmod -v 8.1 pam
systemctl restart php8.1-fpm apache2

PECLphpはバージョンが上がるとビルドし直しなので、なにかいい方法がないかと思う。 自前でビルドパッケージシステムを作り、aptパッケージとしてapt-lineしか無いかもしれない

設定など

mod_phpphp-fpm を使うわけだが

mod_php の場合、設定すれば行けるのですが、競合とかめんどくさいので apache(prefork)+mod_phpapache(worker)+php-fpm にしたほうが無難かと思われる。もちろんnginx でもいいんだけど、thread や worker を使うならapacheでも対して変わらない。

2021-11-15

stretch / buster / bullseye を直接書いてたので、再利用しやすいように変更

2021-11-29

php8.1が出たので更新。

参考資料

System installation on Debian 9 (Stretch) — Akeneo PIM documentation

https://pierre-schmitz.com/using-opcache-to-speed-up-your-cli-scripts/

https://tecadmin.net/install-php-debian-9-stretch/

DebianのBackportsを使う

debian のバックポートを使う。

パッケージがしっかりメンテされているので安心できる stable だけど、どうしても新しいものが欲しい時がある。

そういうときは、deiban のbackports よりも各ソフトウェアの公式のレポジトリを使えばいい。( node とか vivaldi とか gitlab とか chromeとか)

それでも足りないときに backportsが必要になるので追加する。

最初にほしいパッケージがバックポートにあるかカクニンする。

そもそも、ほしいパッケージがバックポートにあるのかどうか調べておく。これをやらないと徒労に終わる。

ここで検索するか、https://backports.debian.org/Packages/

ここで、一覧を眺めるか。 https://packages.debian.org/stretch-backports/

/etc/apt/sources.list

deb http://deb.debian.org/debian stretch-backports main

apt の source ラインに、1行追記するだけ。

その後、アップデート

sudo apt update 

ほしいパッケージをいれる。

バックポートからインストールするときには、バックポートから入れることを明示する。

sudo apt-get -t stretch-backports install "package"

backports にはあんまりないよ

パッケージがそもそも数多くない。たぶん皆さんが求めるのは sid から導入だったり unstable/testing の最新版だったりしませんかね。

繰り返しになりますが、apt で入れるならソフトウェアの公開元が提供している レポジトリを使ったほうがいい。

それでも、unstable/testing がいいんだってときは。 たぶん、この辺が参考になります。 http://www.j96.org/~yuya/d/20090725.html

参考資料

SpeedTest(スピードテスト)をコマンドからやりたい

皆さんも、おなじみスピードテスト

f:id:takuya_1st:20190328173714p:plain

コマンドからやりたい

ssh 経由でリモートの接続の速度を知りたいですよね。うん。

コマンドインタフェースがあるんです。

https://www.howtoforge.com/tutorial/check-internet-speed-with-speedtest-cli-on-ubuntu/

インストール

pip install speedtest-cli

python パッケージが用意されてるので pip るだけで準備完了。

実際にやってみた

takuya@:~$ speedtest-cli
Retrieving speedtest.net configuration...
Testing from Softbank BB (126.xxx.59.xxx)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by JAIST(ino-lab) (Nomi) [220.91 km]: 22.356 ms
Testing download speed................................................................................
Download: 179.96 Mbit/s
Testing upload speed......................................................................................................
Upload: 197.91 Mbit/s

シェアしたい。

オプションでシェアをつけるとPNGファイルが用意される。はーメッチャ便利。

speedtest-cli --share

実際の例

takuya@:~$ speedtest-cli --share
Retrieving speedtest.net configuration...
Testing from Softbank BB (126.xxx.59.xxx)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by JAIST(ino-lab) (Nomi) [220.91 km]: 17.672 ms
Testing download speed................................................................................
Download: 160.62 Mbit/s
Testing upload speed......................................................................................................
Upload: 215.63 Mbit/s
Share results: http://www.speedtest.net/result/81456xxxxxxxxxxxxxxxxxxx.png

画像はこれ

自動生成された画像はこれ

f:id:takuya_1st:20190328174138p:plain

他にも

サーバー選んだり、ダウン速度だけ調べたり、JSONで結果撮ってきたり。

は~便利これ。

参考資料

MacのWiFiやルーティング設定をターミナルのコマンド networksetup でやる

MacOSWiFi設定をnetworksetup コマンドで行う。

過去にも何度もエントリにしたり、まとめてるんだけど、全然覚えられないし、逆引きとして自分のブログがヒットしないし、ブログ内検索でもマッチしないので、書き直します。 networksetup コマンドはわかりにくいと思う。本当にわかりにくい。

イベントのお手伝いでネットワークの構築に言ったときに設定をアレコレするのに、環境設定から手作業で何度もやり直すのがめんどくさかったし、コマンドと履歴で呼び出せるようにしたい。

無線LANに静的にIPを割り当てる

networksetup -setmanual  Wi-Fi 192.168.2.220 255.255.0.0

有線LAN(wired)に静的なDNS IPアドレスを割り振る

networksetup -setdnsservers 'AX88179 USB 3.0 to Gigabit Ethernet' 1.1.1.1

有線LAN・無線LANをコマンドで処理するときの指定名を調べる。

networksetupで指定するインターフェース名はどこので調べるのか。

最初の例の名前をどうやって取得するのか

takuya@~$ networksetup -listallnetworkservices
An asterisk (*) denotes that a network service is disabled.
PPPoE
Wi-Fi
USB 10/100/1000 LAN
AX88179 USB 3.0 to Gigabit Ethernet
iPad USB
iPhone USB 2
Bluetooth PAN
Thunderboltブリッジ
Thunderbolt ブリッジ

ハードウェアの名前と一致を調べる。

en0 などの古き良きデバイス名とMacでの名前を調べる。

takuya@~$ networksetup -listallhardwareports

Hardware Port: Wi-Fi
Device: en0
Ethernet Address: f0:18:98:11:3e:90
(略

VLAN Configurations
===================

指定したSSIDに接続する

networksetup -setairportnetwork en0 nsc_staff

WiFi の接続を切断し再接続する。

networksetup -setnetworkserviceenabled Wi-Fi off
networksetup -setnetworkserviceenabled Wi-Fi on

切断するとこういう感じ

f:id:takuya_1st:20190328171556p:plain

WiFi の接続を切断し、別のSSIDに接続する

networksetup -setnetworkserviceenabled Wi-Fi off
networksetup -setnetworkserviceenabled Wi-Fi on
networksetup -setairportnetwork en0 nsc_staff

デフォルト・ルートを書き換える

ip route del default
ip route add default via 172.16.1.253

WiFi 電源OFFにして再起動する。

networksetup -setairportpower en0 off
networksetup -setairportpower en0 on

電源OFFと接続切断は混同しやすいので特に注意が必要。iOS的な動きするのが -setnetworkserviceenabled です。 -setairportpower `は電源OFF

電源OFFするとこういう感じ。macOSのメニューからオフを選ぶのと同様の動作になる。

f:id:takuya_1st:20190328171624p:plain

関連記事

ip コマンドは -o オプションを使うと便利すぎてやばい

ip コマンド は -o オプションをつけるとメッチャ見やすい

ip コマンドの ip a の結果はごちゃって見辛くないですか?私は非常に辛い。 とくにIPv6 が混じってきて、1つのインターフェースに複数のIPが入ってくると辛い

シェルスクリプトで、grep してるけど、めっちゃめんどくさい。

オプション -o をつけると便利

1行に付き1つのIPアドレスが表示されるのでわかりやすい思う。

takuya@:~$ ip -o  a
1: lo    inet 127.0.0.1/8 scope host lo\       valid_lft forever preferred_lft forever
1: lo    inet6 ::1/128 scope host \       valid_lft forever preferred_lft forever
2: enp3s0    inet 192.168.11.103/24 brd 192.168.11.255 scope global dynamic noprefixroute enp3s0\       valid_lft 39969sec preferred_lft 39969sec
2: enp3s0    inet6 fe80::6ae7:5e96:e212:xxxx/64 scope link noprefixroute \       valid_lft forever preferred_lft forever
3: vlan2    inet 192.168.2.102/24 brd 192.168.2.255 scope global dynamic noprefixroute vlan2\       valid_lft 18372sec preferred_lft 18372sec
3: vlan2    inet6 2001:xxxx:8383:a300:b1a2:9557:xxxx:adxxxxa4/64 scope global temporary dynamic \       valid_lft 13828sec preferred_lft 12028sec
3: vlan2    inet6 2001:xxxx:8383:a300:8012:e7db:xxxx:xxxx/64 scope global dynamic mngtmpaddr noprefixroute \       valid_lft 13828sec preferred_lft 12028sec
3: vlan2    inet6 fe80::91e1:2583:xxxx:edaf/64 scope link noprefixroute \       valid_lft forever preferred_lft forever

ip a の場合

一般的に使われる ip a の場合、次のように、インデントを使って表示される

  • インターフェース1
  • インターフェース2

オプションをつける

今回紹介した ip -o a の場合、次のように1行1レコードになる

  • インターフェース1 IPv4 アドレス
  • インターフェース1 IPv4 アドレス
  • インターフェース2 IPv4 アドレス
  • インターフェース2 IPv6 アドレス
  • インターフェース2 IPv6 アドレス

コマンドで処理をしたり、grep したり sed したりIP取得したりするときに、1行ごとの表示のほうが見やすくないですか?私は見やすいです

wc でIPの数を数えたり、grep で目的のIPレンジを探したり。インターフェースが増えてくるとこのほうが使いやすかった。

オプションについて

-o オプションは、LF(改行)を '\' バックスラッシュに置換してプリントしてくれるものです。もとに戻すなら置換をすればいいとわかります。

-o, -oneline output each record on a single line, replacing line feeds with the '\' character. This is convenient when you want to count records with wc(1) or to grep(1) the output.

参考資料

man ip

Certbotの証明書をドメインごとではなく、ワイルドカードで1枚証明書にまとめる。

certbot の証明書が増えすぎたので辛い

certbot で証明書をバンバン作ってたら管理がめんどくさくなってきた。

証明書の管理を楽にしたい。

LetsEncryptの証明書は、ワイルドカードに対応しているので、ワイルドカードな証明書を作ることもできるし

また、ワイルドカードだけでなく、複数のドメインを入れることができる。

  1. ワイルドカードを使う
  2. 複数ドメインを1つの証明書で賄う

これらの選択肢があります。

ワイルドカードの証明書の利用

ワイルドカード証明書を使うことで、ある程度の証明書をまとめることが出来た。

これについては、過去記事があります。→ certbot がLetsEncryptのワイルドカード証明書に対応してたので作ってみた - それマグで!

でも、まだ足りない。サブドメインワイルドカードや別ドメイン(別名)などもあると管理が煩雑だった。

複数ドメインを1枚の証明書にまとめる。

certbot の証明書は、「名前」(初期値はドメイン)単位で管理されているが、その証明書に含まれるドメインはいくつも指定が可能です。

説明
メインのドメイン example.com
ワイルドカード *.example.com
サブドメインのイルドカード *.takuya.example.com
ドメインワイルドカード *.example.jp

これらの複数のドメインワイルドカードを1枚に押し込める事が可能でした。

証明書をまとめるメリット

apache / nginx などの設定が非常に楽ちんになる。

証明書の更新作業が非常に楽ちんになる。

なので、ドメインを追加するときは新規で証明書作るより、既存の証明書(名前)にドメインを追加して再取得するほうがいい。

ワイルドカードで複数にサブドメインをまるっと突っ込む例。

mydomain=example.com \
sudo ./certbot-test/bin/certbot  \
  certonly \
  --cert-name $mydomain-all-in-one \
  --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflareapi.cfg \
  --server https://acme-v02.api.letsencrypt.org/directory \
   -d "$mydomain" \
   -d "*.$mydomain" \
   -d "*.a.$mydomain" 

このコマンドのポイントは

--cert-name で「覚えやすい名前」をつけているところ。(よく使われるの)ドメインそのままを名前にせず、自分で名付けています。これによって複数ドメインが入った証明書であることをわかりやすくしている

-d ドメイン で 複数ドメインワイルドカードも含めて)を指定しているところ。

オプションをこれら使うことで、証明書1つでマルチに対応できる

すでに存在する証明書をまとめる

これは、削除→新規作成と更新→追加の2つの選択肢がある。

  1. すでにある証明書を削除(delete/revoke)して、新規作成時にドメイン追加する。(覚えることが少ない
  2. すでにある証明書を更新して、ドメイン追加する。

削除→新規 の例

certbot revoke ...#略
certbot certonly  # 略

削除(revoke)と新規作成は、個別に記事があるので参照する。

追加 を使う

削除→追加以外にも追加オプションがあるので、これも知っておくと役に立ちそう

追加するときは、既存の証明書の名前を指定し、既存のドメインをすべて指定する。

設定例

mydomain=example.com \
sudo ./certbot-test/bin/certbot certonly \
   --cert-name $mydomain-allinone \
   -d git.example.com
  -d add.example.com

f:id:takuya_1st:20190328161857p:plain

TODO ↑の写真とコマンドは間違ってるので後で修正。

すると、次の様に、ドメインに追加するメニューと確認が出てくる。

本家解説

--expand documentation によると次のように解説されている。

--expand tells Certbot to update an existing certificate with a new certificate that contains all of the old domains and one or more additional new domains. With the --expand option, use the -d option to specify all existing domains and one or more new domains.

既存のドメインの証明書を新しい証明書に更新するが、一つ以上の追加(または削除)したいドメインがあるときに -d でドメインを列挙して指定する。

まとめ

証明書にドメイン追加とワイルドカードを使うことで、複数のサブドメインを1枚の証明書にまとめることができ、管理がとても楽ちんになる。

また、サブドメインでもなく、全然別のドメインを入れることができるので、別のドメインをまとめることで管理が簡素化する。 (ただし、同一証明書を利用しているときは、CDNやプロキシでさばくと便利なのですが、複数のドメインを証明書とプロキシでまとめるとその分平分で通信も見られやすいので注意が必要)

参考資料

https://certbot.eff.org/docs/using.html

certbot でステージング(テスト環境)用に証明書を作る

certbot で同一ドメインの証明書を複数作る

ステージングや、certbot のコマンドであれこれ実験していると、証明書の発行上限に達してしまいます。

そこで、 ステージング用の証明書を使うと良さそうなので試してみた。ステージングやテスト用にドメインを作って管理するのも面倒な話ですし。

ステージングの使用

testing:
  The following flags are meant for testing and integration purposes only.

  --test-cert, --staging
                        Use the staging server to obtain or revoke test
                        (invalid) certificates; equivalent to --server https
                        ://acme-staging-v02.api.letsencrypt.org/directory
                        (default: False)

ステージングを使うと、閾値による制限にかからなくなるので、コマンドや.gitlab-ci.yml や .circle-ci.yaml に組み込むとき実験で使える。重宝する

使い方

いつもの、certbot のコマンドにオプションを付けるだけ。

  --staging \   を追加しています。

certbot で証明書作るサンプル

mydomain=example.com \
sudo ./certbot-test/bin/certbot  \
  certonly \
  --staging \ 
  --cert-name ${mydomain}-staging \
  --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflareapi.cfg \
   -d "*.${mydomain}" \
   -d ${mydomain}

わたしは、ドメイン所持のチェックにcloudflare プラグインを使うのでオプションが入っていますね。

実際にアクセスしてみる

証明書のの検証には失敗する。自己証明書よりは簡便でマシかな程度のステージング証明書になる。 f:id:takuya_1st:20190327162607p:plain

削除したり 更新したり

削除したり、更新したり、いろんなcertbot のコマンドを試せたり、また検証サーバーやテスト用に作れるので便利かもしれない。

追記:revoke

--staging / --test-cert で作った証明書は、当然ですが、そのままでは通常運用出来ない代物なので、 revoke する必要がなく、revoke コマンドは通りません。

不要になったら delete します。

その他の方法

dry-run の利用

dry-run でも似たような効果は得られる。

--dry-run             Perform a test run of the client, obtaining test
                        (invalid) certificates but not saving them to disk.
                        This can currently only be used with the 'certonly'
                        and 'renew' subcommands. Note: Although --dry-run
                        tries to avoid making any persistent changes on a
                        system, it is not completely side-effect free: if used
                        with webserver authenticator plugins like apache and
                        nginx, it makes and then reverts temporary config
                        changes in order to obtain test certificates, and
                        reloads webservers to deploy and then roll back those
                        changes. It also calls --pre-hook and --post-hook
                        commands if they are defined because they may be
                        necessary to accurately simulate renewal. --deploy-
                        hook commands are not called. (default: False)

参考資料

https://certbot.eff.org/docs/using.html?highlight=staging

Certbot で証明書を削除する。

Certbot で証明書を消す

選択した証明書を消すには、対話式CLIを使うのが楽

sudo certbot delete 

f:id:takuya_1st:20190327153208p:plain

証明書の名前(ドメイン)がわかっているとき。

証明書の名前を指定して、オプションで明示することで削除ができる。

sudo certbot delete --cert-name example.com

---cert-name は自分で自由に決められる名前ですが、だいたいみんなドメインを使います。 わたしは使ってませんが。。。

その他の方法

直接ファイルを消すという手もあるにはある。

rm -rf /etc/letsencrypt/live/${DOMAIN}
rm /etc/letsencrypt/renewal/${DOMAIN}.conf

revoke して無効化することもある。

delete ではなくrevoke して一旦無効化することもいい。certbot は revoke すると その後 delete するらしいです。

Once a certificate is revoked (or for other certificate management tasks), all of a certificate’s relevant files can be removed from the system with the delete subcommand:

コレを読む限り、delete するより、revoke のほうが良さそうですね。

参考資料

https://certbot.eff.org/docs/using.html?highlight=revoke

mac のnetworksetup コマンドでVLAN作成

Mac のVLAN作成をCLIでコマンドからやる。

コマンドライン(CLI)で、VLANネットワークの設定をやる

networksetup コマンドでVLANインターフェースを作る。

コマンドとしてVLANを扱うのは次の通り。

networksetup -createVLAN <VLAN name> <parent device name> <tag>
networksetup -deleteVLAN <VLAN name> <parent device name> <tag>
networksetup -listVLANs
networksetup -listdevicesthatsupportVLAN

VLANが作れるデバイスには制限がある。

VLAN作成可能なネットワーク・インターフェースには制限がある。 実NICを接続する必要があった。

最初に、VLAN作成可能なデバイスを調べる。

takuya@~$ networksetup -listdevicesthatsupportVLAN

en21 (AX88179 USB 3.0 to Gigabit Ethernet)

VLAN を作る

networksetup -createVLAN test en21 200

作成できる。結果は何も表示されない。

エラー時はエラーが表示される。

たとえば、作成ができないデバイスWi-Fi)に対してVLAN ID を作成しようとすると

takuya@~$ networksetup -createVLAN test en0 2000
Could not find VLAN capable hardware port or device named en0.
** Error: The parameters were not valid.

このようにエラーが出る。

 作成結果を確認する。

createVLANコマンドでは結果が表示されないので、一覧コマンドで作成結果を確認する。

networksetup -listVLANs

コマンドでカクニンすることができる。

実例

takuya@~$ networksetup -listVLANs

VLAN User Defined Name: test
Parent Device: en21
Device ("Hardware" Port): vlan0
Tag: 200

ここで、vlan0 として作られたことがわかる。

実際にvlan0 があることを調べる。mac なので ifconfig ですね。

takuya@~$ ifconfig  vlan0
vlan0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    options=3<RXCSUM,TXCSUM>
    ether 00:00:68:ab:47:71
    nd6 options=201<PERFORMNUD,DAD>
    vlan: 200 parent interface: en21
    media: autoselect (<unknown type>)
    status: inactive
takuya@~$

Mac でVLANのタグを読めるインターフェイスを作成する

mac でもVLANを使いたい。

MacOS のLANインターフェースでVLANを扱う必要があった。ぱぱっと設定したときにどうやったかメモを残しておきます。

VLAN は環境設定から。

環境設定のネットワークをひらく。 左下の歯車のアイコンを押す。(ここがポイント) f:id:takuya_1st:20190322135718p:plain

仮想インターフェイスを作成を選ぶ。

メニューの中から、仮想インターフェイス管理を選ぶ。

f:id:takuya_1st:20190322135723p:plain

VLAN作成を選ぶ

仮想インターフェイスの一覧が表示されるので、左下の追加(+)ボタンを押す。
新規VLANを選びます、

f:id:takuya_1st:20190322135727p:plain

VLANを作成します。

VLAN ID と インターフェース、インターフェース名を入力します。

f:id:takuya_1st:20190322135732p:plain

疎通を確認します。

あとは、VLANネットワークとの疎通を確認します。

一般のご家庭で手軽にVLANして遊ぶには

VLANって逸般の誤家庭にはあるけど、一般のご家庭には無いんですよね。

ところが、次のような2500円程度の機材を使うことで、手軽にVLANを張って遊べます。便利。

ip コマンドでルーティングテーブルの逆引き(?)どのルートを通るか調べる

ip route show してもすっとわからない。

このIPはどのルーティグで転送されるの??

ip route show してもわからない、僕ら素人のためのコマンド

ip route get

宛先IPアドレスを指定すると。そのIPアドレスはどのルーティングテーブルにマッチするのかを調べることができる。

使用例

takuya@Desktop$ ip route get 192.168.2.1
192.168.2.1 via 192.168.11.1 dev en7  src 192.168.11.141

ipv6 で役に立つ。

IPv6 だと一目で即時にルーティングが見えづらい。アドレスが長いので、一呼吸を置いてから脳内で整理してたけど。 このコマンドを使えばそういうの面倒な脳内処理が不要になる。

ルールが複雑なときや、ルーティング順番がうまくマッチしないときに、どのrouteがマッチするのか調べることができるから便利。

使用例

takuya@:~$ ip route  get 2001:xxxx:38a8:3700:e80:63ff:xxxx:xxse
2001:xxxx:38a8:3700:e80:63ff:xxxx:xx3b from :: via fe80::225:36ff:fe75:a542 dev vlan2 
proto ra src 2001:axxx:8383:a300:b1a2:9557:xxxx:xxa4 metric 400 pref medium

もっとはやく教えてくれよ。