それマグで!

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

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

LVM のvg/lv の名前の変更

LVM のvg/lv の名前の変更したい

takuya@u04:~$ lsblk
NAME                      MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
vda                       252:0    0   20G  0 disk
├─vda1                    252:1    0    1M  0 part
├─vda2                    252:2    0    1G  0 part /boot
└─vda3                    252:3    0   19G  0 part
  └─ubuntu--vg-ubuntu--lv 253:0    0    9G  0 lvm  /

vg の名前の変更

オンラインで名前を変えられる。

sudo vgrename ubuntu-vg main
#  Volume group "ubuntu-vg" successfully renamed to "main"

lv の名前の変更

sudo lvrename main/ubuntu-lv main/root
# Renamed "ubuntu-lv" to "root" in volume group "main"

結果の確認

takuya@u04:~$ lsblk
vda           252:0    0   20G  0 disk
├─vda1        252:1    0    1M  0 part
├─vda2        252:2    0    1G  0 part /boot
└─vda3        252:3    0   19G  0 part
  └─main-root 253:0    0    9G  0 lvm  /

lvm の ボリュームグループ vg と ロジカルボリューム lv の名前をオンライン(しかもマウント済み)で変更できることがわかった。

ubuntu-vg みたいに、ハイフン付きで名前をつけてしまうとubuntu--vg とハイフンがハイフンでエスケープされて2重化されるので本当に不便だったけど、インストール後にサクッと名前の変更ができるとわかった。

インストール時にLV/VGの名前を変えてインストールしていたが、インストール後に名前を変更できるとわかったので、手順が一つ減らせて最高だった。

注意点

vgrename / lvrename はあまりに手軽だが、注意点がある。 /etc/fstabである。

名前が変わると、マウント先が変わるので、root ファイルシステムについてこれをやると全く起動しなくなるので注意が必要

WindowsのRDPの接続設定を保存して、xrdpに接続しやすくする

RDPでログイン情報を保存したい。

RDPで接続するときに、ユーザー名とパスワードを保存することが出来る。Xrdpでは駄目なのかなと思ってたけど、確認したら保存できたのでメモに残す。

なぜわざわざ記事にしたのか。

画面のデザインが○ソで、何処にどう保存したらいいか全く理解できなかった。

takuya/my_password 何処に保存したらいいかわかりますか?

この画面をみて、どこにパスワードを入れたら、takuya/my_passになると思いますか?

この画面が保存するのは、実はAD-ドメイン\takuya / my_passwordなんですよ。

ユーザ名にドメインが入るのですよ。そんなのわかるかよ。

と散々に腹がたったので、記事にしました。

xrdp の場合:ユーザーログインが必要になる。

XRDPの場合は、Windowsのログオン画面の代わりにXRDPのログイン・ダイアログが表示される。

認証に失敗したりすると、次の画面になる。

保存の概要

保存するためには、いくつか手順をふまなくてはいけない。 以前のように接続設定ファイルに保存したりができない。

Windowsセキュリティを使ってユーザーのログイン認証情報をWindowsのユーザー専用ストレージに保存する。これがちょっとわかりにくい。

接続設定は、解像度やデバイス設定を保存して、Windowsセキュリティでログイン認証情報を保存する。

この違いを覚えておく。

保存をするために、チェックを入れる。

パスワード保存を有効(許可する)にチェックをいれたら、保存されるようになるが、そのままでは保存されない。チェックを入れた状態で「接続する」

チェックした状態で接続する。

windows セキュリティが起動する。

Windowsセキュリティが起動する。ここで保存する情報を入力する。

ユーザの選択が出てくるが、ユーザ名は、RDPらしく「ADドメイン名(コンピュータ名)」と「ユーザ名」の組み合わせになっている。

ここでは、「別のユーザ」を選ぶ。

XRDPの場合、ここでADドメイン名(コンピュータ名)を指定すると、サーバーに「ドメイン名(コンピュータ名)¥ユーザ名」がおくられて、Linuxユーザとのマッピングがうまくいかないので、「別のユーザを指定」を選ぶ。

初期状態では次の表示になり、紛らわしい。

MoreChoices(赤囲み・青字)を選ぶ。

ダイアログは、ユーザ名が表示されているが、実体は黄色線野先にある、「ADドメイン名¥ユーザ名」になっているので、このままではログイン先のパスワードに一致しないことがある。ドメイン名を変える(なしにする)には、赤囲みのMore Choicesを選ぶ必要がある。

もともと、パスワード保存を選んでこのダイアログが出ているのに、さらに、「Remember Me」を<さらにチェック>するのが、特にわかりにくい。本当にWindowsさんは面倒なのですよね。

ユーザ名とパスワードを入れる。

このときに、ユーザ名とパスワードを入力し、チェックをボックスを入れる。のだが、この画面で入れると面倒が起きる。

パスワードの入力順に注意。

Windowsセキュリティ側から、RDPアプリに、パスワードを提供するという設計になっているようだが、Windowsセキュリティ画面で、このパスワードを編集したり閲覧する機能は用意されていない。*1

保存したパスワードを消す

保存したパスワード・ユーザを削除・編集したい場合は、なんとRemote接続画面から消す。

ホスト名に1つのID/PWが保存される。、同一ホスト名に別のユーザ名で保存するのはできないようだった。ほんとうにWindowsの画面設計はわかりにくい。

まとめ

RDPでドメイン名を除去するのはRDP受信側(サーバー側)の仕様ではある。しかし、ユーザ名を指定する画面と実際に保存するWindowsセキュリティの画面に表記揺れがあり、本当に分かりづらい。

年末年始で時間ができたので手当たり次第試すことができて理解できたけど、普段はまったくわからずユーザ名を使わずサーバー側のログイン画面を使ってログインしていた。しかも3年位謎だった。謎が解けたので記事にした。

*1:Windowsセキュリティに保存したパスワードを編集閲覧できない、パスワードをパスワードで保護する機能もないし、保存する選んで、パスワード入力画面に来ているのに、RememberMeが出てくるってのは、しかも、上から順に入力すると間違いになりログインできない。上から順に選択肢入力すると間違いになる設計。ほんとうにWindowsは設計が無茶苦茶です。WindowsのUIは支離滅裂で破綻しています。

時間範囲(開始終了)の比較を考える。

時間範囲の重なりを考える。

予定表の追加の確認や、イベントの開催時間の確認、予約システムの確認や、会議室の予約など、時間範囲をリソースとして扱うことは多い。

そのリソースの時分割をどうやって判定するのかちょっと考えていた。

時間範囲の比較パターン 13個

それらのパターンに名前がないので、名前は、ウェブやgithubみながら、私が適当に考えた。名前くらいは自分で考えてみると面白い。*1

11パターン

先のパターンのうち、12,13は 、他パターン(8,9、3,6)に含まれるので、次の11種類に減らせる。

同時(=)は被ると判断するとー>7パターンへ

同時スタートや、終了直後にスタート、同時に終了は、同一時刻に間髪入れずに開始終了するので、同時は重複していると判断したほうが楽。同時は重複していると考えることが可能。つまり、パターン8・9は、パターン2・3と同じと判断できそうだ。

<=、>=、==を省いたら、7パターンまで減らせる。

さらにいえば、もし予約Aを取るとき、A終了=B開始が重複するのなら、A終了を-1 ミリ秒すれば被らない。なので A ( 14:00.00 ~14:59.99 )B( 15:00.00~15:29.99 )としてしまえばいい。時間が被ってないとわかる。表示するときに、四捨五入でINTに丸めれば A(14:00 ~15:00)B(15:00~15:30)になるわけだ。

時間の重複があるかないか

時間の重複があるかないか、それだけを考えるのでれば、更に減せる。

時間が被り予約が取れないリソースを確保できないみたいな判断だけなら、パターン1・5を満たすものだけ考えればいい。

つまり単純に考えればA終了<B開始 または、B終了<A開始 を満たせばいいとわかる。 ここまで考えれば、プログラミングで実現するまでもなく、SQLの検索条件に出来る。専用ライブラリ導入を考えずに、WHERE句だけでもいける。なので、時間範囲(予定表)を全件を無駄に取得して全部の組み合わせを比較するなんて言う、富豪プロミラングを避けられる。

なぜこんな事を考えてたのか。

とある、予定表のシステムのが「ものすごく遅い」ので使い物にならないのでJavascriptのFetchリクエストをみていたら、予定表を全件と一致を個別判定にリクエスト行ってたんですよね。呆然でした。富豪プロミラングもいいけどモヤっとする。

試しに実装してみた。

条件さえ整理してしまえば、プログラミングで、7 種類を判定、時間の重なりがあるかの判定はサクッと作れるのではないかと思った。なのでサクッと作ってみた。

github.com

条件を整理して、ANDを使えばそれぞれを識別できそうだった。

ご意見お待ちしております。

この記事は私がエクセルとにらめっこしながら3時間程度考えた結果です。

時間の範囲比較は、もっとこう考えればいいよ。ここ間違えてるよ。とか、もっと知りたいです。教えて下さい!!

参考資料

*1:コピペ・サイト事業者が、「いかがですか」をつくるとき、この名前の組み合わせは私の記事をパクッたとわかる。こんな素人記事をパクらずに、githubの素晴らしい人達の実装からパクった方が良いよ。

nvmeの温度を取得する方法ー3種類

nvme の温度を調べる

nvme が発熱でサーマル・スロットリング(温度保護)が走ってるっぽいので、温度のログを保存することにした。

その時に、そのもそもnvmeの温度を調べるにはどうするか考えた。

nvme の温度(temp/temparature) を調べる方法

コマンド apt 必要 root必要
cat /sys - -
sensors -
smartctl
nvme

ルート権限なし /sys ファイルシステム

/sys から取得すれば、ルート権限なしで取得できる。

cat  /sys/class/nvme/nvme0/device/hwmon/hwmon1/temp1_input

sensorsコマンド

これはインストールが必要、実行時にはroot権限はいらない。

sudo apt install lm-sensors
sudo sensors-detect

温度取得

sensors

smatctl

SMARTで直接にデバイスへ取りに行く。

インストールが必要、実行時に デバイスへのRoot権限が必要

sudo apt install smartctl

温度取得

sudo smartctl -a /dev/nvme0 | grep -i Temp

nvme-cli コマンド

smart等のデータを含めて、nvmeを管理するコマンド、温度取得も可能

sudo apt install nvme-cli 

温度取得

sudo nvme smart-log  /dev/nvme0

ルート権限が必要なコマンドを一般ユーザに許可する

SetSUID すれば、一般ユーザでも実行可能にすることが出来る。諸刃の剣。smratctl くらいなら問題な無いと思う。

SIDをつかって、一般ユーザでもsmartctl出来るようにする

sudo chmod u+s /usr/sbin/smartctl

smartctl で情報見る程度でsudo求められるのもなんか違うと思うし。

もしくは、温度を見る専用のコマンドを作って、そのコマンドををSetSIDする。 コマンドを作っておいて、このコマンドだけは一般ユーザでもrootとして動かせるようにしてもいいと思いますが、forkしてexecvするとかC言語で書くとか面倒なのですよね。

結論

ルート権限がないなら、/sys から見る

sudo できるなら smartctl で見る。

これらが確実なようです。

7z をコマンド・ラインで使っzip/tar/7z を作る作り方

7z コマンドでアーカイブを作る

出力先ファイル名とフォルダを指定して作れる。

7z アーカイブ

7z   a     out.7z    input/

tar アーカイブ

7z   a     out.tar    input/

zip アーカイブ

7z   a     out.tar    input/

7z コマンドだけでできます。有能ですね。

ファイルの追加

7z a は追加 コマンドなのでファイルを追加もできますね

7z   a     out.zip   input.txt input2.txt

複数のファイルを列挙してもいいですね。

インストール

7z コマンド自体は、debian/ubuntu なら apt で導入ができます。

sudo apt install p7zip-full --install-suggests

Windowsなら chocolatey が便利でしょう

choco search 7z

p7zip はコマンドは、GNUコマンドと引数が違って、違和感がありますが。使う分には使いやすいコマンドだと思います。

Windows が起動するUSBメモリを作る

準備するもの

起動メディアにしたい、USBメモリを準備。
Rufusをインストール、Windowsを書き込むために必要。
Windows のISOファイルを準備 。

WindowsのISOファイルがない場合は、Windows Media Creation Tool 使いISOファイルを作成する

Rufusを使う

RufusWindowsのISOファイルを指定すると、Windows to Go にするか?と訊かれる。
WindowsToGo はUSBメモリで起動するWindowsのことであり、
これを選ぶことで、Windowsが起動するUSBメモリになる。

書き込み前に、Windowsの種別や、初期ユーザーを設定が訊かれる。
それらを設定して、USBドライブを作成する。

あとは書き込みを待つ。

WindowsのISOファイルの準備

Windows Media Creation Tool を使う

Windows のISOを作る

USB フラッシュまたはISOを選んで

ISOを選ぶ。

ISOを選ぶと保存するファイル名を決めて、書き込みを待つ

暫く待つと、Windows.iso が生成されている。

WindowsのUSBドライブの活用

Windowsで動作検証を行いたいときや、ちょっとディスクをチェックしたいときに使える

とくに、nvmeのディスクで重宝する。

nvmeのSSDは、pcie で接続しないと、メーカー提供の各種ツールが使えない(セキュア・イレース、ファームウェア・アップグレード、S.M.A.R.T情報取得など)

そのため、USB 変換でnvme を使うと動作しないのである。直接nvmeを差し込んで調査しようとしても、起動ディスクになっているため初期化などの操作はできない。かといって別のnvmeから起動しようにも、nvmeのスロットは1つしか無いのである。そうなるとUSB-HDDやUSB-SSDからWindowsを起動するかしか無いのである。

持ち運び用に

Windows to Go は便利である。リモートようにPCを配布しなくてもご家庭のWindowsにセキュリティをガチガチに強化しなくても、ご家庭のWindowsPCを使って、お仕事用のWindowsを起動できるし持ち運び出来るわけである。

また、抜き差しで管理できるために、とても手軽に使えるのである。

Bitlockerと合わせて使うと確実であると考えられるが、Bitlockerが使えるかどうかはまだ検証してない。

デメリット

1台毎にWindowsのライセンスが必要になります。

おすすめのUSBメモリ

USBメモリは高速な方がいいと思う、nvme 2242 を使って超小型のUSBメモリを作れるキットがある。

暗号化機能付き

暗号化機能付きもいいと思います。

同じお金を掛けるなら、Windows HomeをWindows Proにして、Bitlockerを使ったほうがいいかもしれませんが

過去記事

takuya-1st.hatenablog.jp

Multipass でUbuntuをインストールしWindowsのフォルダをマウントできる。

Multipass でUbuntuをインストールしてあこれこれする

multipass でWindowsのフォルダをマウントできる。

multipass記事を読んでたら、こんな記述があった。 https://hnakamur.github.io/blog/2019/10/17/multipass-on-windows-and-macos/

ホストのディレクトリのマウント 仮想マシンのホストであるWindowsディレクトリを仮想マシンにマウントするのは以下のようにします。ディレクトリ名は適宜変更してください。マウント先のディレクトリは自動的に作成されました。

multipass mount C:/Users/hnakamur/foo primary:foo

やってみた。

multipass.exe mount 'C:/Users/takuya/Desktop' 'primary:win-desktop'

特権が必要

エラーが出た。マウントはパーミッションが必要。

takuya@wsl:Desktop$ multipass.exe list
Name                    State             IPv4             Image
primary                 Running           172.23.119.104   Ubuntu 20.04 LTS
takuya@wsl:Desktop$ multipass.exe mount 'C:/Users/takuya/Desktop' 'primary:win-desktop'
mount failed: Mounts are disabled on this installation of Multipass.

See https://multipass.run/docs/set-command#local.privileged-mounts for information
on how to enable them.

管理者権限のPowershellで権限を付与

PS > multipass set local.privileged-mounts=true
PS > multipass get local.privileged-mounts
true
PS >

実行例

再起動

PS > multipass restart primary

コマンドからmultipassとWindowsのマウントを試してみる。

マウントするとできた

マウントはWSLのシェルからもできた。

multipass.exe mount 'C:/Users/takuya/Desktop' 'primary:win-desktop'

マウントはSSHFS

確認すると、SSHFSでマウントされてますね。速度はあれだけど、使えりゃいいのでSSHFSでマウントで十分ですね。

chroot でネットワーク接続ができない。

chroot 環境を作ったらネットワーク接続できない

sudo chroot /mnt

chroot したので普通と同じようにネットワークを扱えるかと思いきやできない。

dns エラーを切り分ける

ping 1.1.1.1 # 通る
ping g.co # 取らない。

DNSですね。

systemd-resolved がいた

/etc/resolv.confが、systemd管理になってるのが原因 。

まじか。systemdは余計なお世話が多いですね。

echo nameserver 1.1.1.1 >> /etc/resolv.conf

これで解決ですね。

やっぱり設定ファイルだけで動作するって頑丈ですね。

参考資料

https://bbs.archlinux.org/viewtopic.php?id=95865

年齢を計算する

年齢計算とは、単純だけどちょっと難しいものです。

色々と考えられるけど、判断していいのか困ったのであれこれ考えた。

日数から、年が何回出てるか(365の商)を見る

剰余は無視すればい。

(Date.parse('2022-12-01') - Date.parse('1989-12-02')).to_i/365

閏年

閏年(LEAP)の問題が発生するので、1年を365日と1/4日にしてみる。

(Date.parse('2022-12-01') - Date.parse('1989-12-02')).to_i/365.25

まぁこれでも十分な精度が得られる。

それでいいの?

人間の年齢ならね。人間の年齢は0−99まで計算できればいので有効桁数が2桁である。 1年を365日で計算していると、0.25/365だけ誤差が出てくる。有効桁数を考えれば無視できるかな。 365.25で、小数点以下を切り捨てるので、有効桁数を考慮しても十分な精度である。

ただし、人間の年齢で、かつ「日付」を使うならね。

この考え方を応用すると、

((Date.parse('2022-12-02') - Date.parse('1989-12-02'))/365.25)=32.99931553730322

上記のように、32歳と11ヶ月30日だとしても、だ。32.9999 になっても切り捨てるので問題ない。

日数(365日)による計算がいやなら

もう少しマシな方法を考えよう。

こちらは、いったん数え年(序数)で出しておいて

x_th_year = Date.parse('2022-12-02').year-Date.parse('1989-12-02').year #=>33

満年齢に達していないときは、減らせばいい。

x_th_year - 1 if (Date.parse('2022-12-01').prev_year(33) - Date.parse('1989-12-02'))   #=> 32

if文が、めんどくさい。

if が持ってるフラグ部分をなんとかしたい 、年齢は(2022-1989)-(1 or 0 )であるとわかるので、-1の部分を入れればいいとわかる。

数え年は次のように計算して

( Date.parse('2022-12-01').strftime('%Y').to_i - Date.parse('1989-12-02').strftime('%Y').to_i ) #=> 33

これが、0.01 でも減ればいい。

なので、数字を次のようにみると

Date.parse('2022-12-01').strftime('%Y,%m%d') #=> 2022,1202
Date.parse('1989-12-02').strftime('%Y,%m%d') #=> 1989,1201

数え年に、誕生日のプラスマイナスを加減してあげて、INTをとれば十分な精度だと解る。

1年は365日なので、4桁くらい用意しておけば十分である。

33*1000 - (1202-1201) #=> 32999

4桁足したので、4桁を減らしてINT取ればいい。

(33*1000 - (1202-1201))/1000 #=> 32.999
((33*1000 - (1202-1201))/1000).to_i #=> 32

これで十分である。

この計算をまとめると次のようになる。

(2022*1000+1201 - 1989*1000+1202) / 1000 

この計算を整理すると、単純に文字列を「8桁の数字」として計算しているだけである。

1202は4桁なので、5桁で割って、小数点に落としてしまえば、INTとして計算ができる。

(20221201 - 19891202) / 10000

したがって、年齢計算を簡単にやるには、次で十分である。

(Date.today.strftime('%Y%m%d').to_i- Date.parse('1989-12-01').strftime('%Y%m%d').to_i ) /10000

これは、有名なアルゴリズムであるね。

10000で割るというものの別解

べつにさ、0.001だけでも減ってしまえば、丸めていいんだから。INTで計算してからINTに丸める必要はない。

小数点を使って計算すればいいじゃん

2022.1201 - 1989.1202

なので、こうなる。

today =  Date.today.strftime('%Y.%m%d').to_f #=> 2022.1201
birthday = Date.parse('1989-12-01').strftime('%Y.%m%d').to_f #=> 1989.1202
( today - birthday ).to_i

一行で書くと

( Date.today.strftime('%Y.%m%d').to_f - Date.parse('1989-12-01').strftime('%Y.%m%d').to_f ).to_i

int 丸める処理の直前で、桁を上げる必要すらないことがわかる。

昔の計算機は貧弱だったのでFloatの計算を避たのだろう。

現代っ子にとっては、小数点を使ったほうがわかりやすいだろう。

年齢計算ニ関スル法律

ちなみに年齢計算ニ関スル法律というものがあり、年齢計算のアルゴリズムは法律で定められている。

だた、法律の年齢計算のアルゴリズムを厳密にやると大変なので、どこかで近似してざっくり計算しても十分なことが多い。

だって、欲しいものは整数値(INT)だもの。

今回の計算は日付と日数を単純に計算したものです。

Date型を使わなくても十分だったり。

年齢計算とは、単純な桁繰り上げ問題ということでした。

Date型は内部でINT秒を変換してる判断してると、こういうざっくりした計算や時刻比較が思いつかないので困るよね。

たとえば、日付の比較だって単純な数字の比較できる。2022.1201 > 2022.1130 なのですから。

他にも日付の検索を単純に考えることも出来る。

たとえば、文字列で検索とか、数値で検索とかできちゃうよね。

select * from table where birthday LIKE '1988-11-%' # 文字列で1989-11-05 のように入れてた場合
select * from table where birthday > 1988.1100  # 数値で、1989.1105のように入れてた場合。

日付とか年齢ってDate型で扱うのが正義だけど、Date型がいつでも最短経路だとは限らない。

(現代のコンピュータはUTC/JSTなど時差を考慮するから、Date型が必須なんだけどね。)

LaravelでsocialiteでOauth(サイトログイン)連携を作る/Gitlabログインを例に

LaravelでGitlabログイン連携を作る

laravel でSocialiteプラグインを使う。ユーザー登録の代わりにユーザをほかサイトのIDでログインさせるOAuthです。

今回は、「gitlab」ユーザでログイン機能を作る。とくにOmnibus版でセルフ・ホスティングサイトを使う。

全体の流れ。

  • laravel プロジェクト作成
  • プラグインをインストール
  • db 初期化
  • gitlab にAppを登録
  • laravel でソースを追加
  • 新規ユーザ追加処理を追加
  • ログインボタンを設置

とても、かんたんですね。php最新版が動作すれば、10分程で、ユーザーログイン機能とOAUTH機能を作れます。お手軽です。

laravel プロジェクト作成

composer create-project laravel/laravel sample-app
cd sample-app
composer install 

パッケージをインストール

composer require laravel/socialite

socialiteでgitlab を使えるように、パッケージインストール

composer require socialiteproviders/gitlab

DBを準備

sed -i 's/DB_/#DB_/' .env
sed -i  '11iDB_CONNECTION=sqlite'  .env
touch database/database.sqlite
php artisan migrate:fresh --seed
cp .env .env.local

breeezeを使う

composer require laravel/breeze --dev
php artisan breeze:install 

APP_URL を artisan serve向けに書き換え

sed 's|=http://localhost|=http://127.0.0.1:8000|' -i .env

コールバックURLが重要になるの。APP_URLを使うのでartisan serve で使えるように書き換え。

gitlab soclialteを作っていく

config/services.php ファイル

<?php   
return [
   // 中略
   'gitlab' => [
      'client_id' => env( 'GITLAB_CLIENT_ID' ),
      'client_secret' => env( 'GITLAB_CLIENT_SECRET' ),
      'redirect' => env('APP_URL').'/auth/gitlab/callback',
      'host'=>env('GITLAB_HOST'),
    ],

上記の config/services.php をコマンド・ラインからコピペで行うコード

sed -i -e "/^];/i \\
   'gitlab' => [\n\
      'client_id' => env( 'GITLAB_CLIENT_ID' ),\n\
      'client_secret' => env( 'GITLAB_CLIENT_SECRET' ),\n\
      'redirect' => env('APP_URL').'/auth/gitlab/callback',\n\
      'host'=>env('GITLAB_HOST'),\n\
    ],\n\
"  config/services.php

Gitlabのサイトで、APP_IDとAPP_SECRETを用意する。

callback url

http://127.0.0.1:8000/auth/gitlab/callback

チェック

read_user

GIT_LABの場合APP_SECRETを作るのは、「ユーザー自分自身」で作ってもいいし、「アプリ全体」で作ってもいい。

.env

APP_URL=http://127.0.0.1:8000
GITLAB_CLIENT_SECRET=244a53xxxxxxxxxxx
GITLAB_CLIENT_ID=5c35dcxxxxxxxxxxxx
GITLAB_HOST=https://gitlab.example.tld/

routes/web.php

oauth専用のroute を定義します。別ファイルに定義するのでinclude定義を書きます。

<?php
// append
require __DIR__.'/socialite-gitlab.php';

上記の処理をコピペで行う

sed '$a require __DIR__."/socialite-gitlab.php";' -i routes/web.php
touch routes/socialite-gitlab.php

routes/socialite-gitlab.php

ログインの動作を作ります。Controllerに作ってもいいけど、可搬性・行数の少なさ・理解のしやすさ、これらを踏まえて、route定義だけに留めました。

<?php
use Illuminate\Support\Facades\Route;
use Laravel\Socialite\Facades\Socialite;
use App\Models\User;
use Illuminate\Support\Facades\Auth;

Route::get('auth/gitlab', function () {
  $driver = Socialite::driver('gitlab');
  return $driver->redirect();
})->name('oauth:gitlab.redirect');
//
Route::get('auth/gitlab/callback', function () {
  //
  $oa_user = Socialite::driver('gitlab')->user();
  $userdata = (object)$oa_user->user;
  // 管理者フラグ
  if ( !$userdata->is_admin ) {
    // laravel アプリの利用者を gitlab admin に限定する。
    abort( 403, 'not admin' );
  }
  // ユーザを作成
  $user = User::updateOrCreate(
    ['email' => $userdata->email],
    [
      'email_verified' => $userdata->confirmed_at,
      'name'           => $userdata->username,
      'password'       => 'dummy_oauth_'.md5(random_bytes(20)),
    ]
  );
  Auth::login( $user );
  return redirect('/dashboard');
});

本当に、この10行程度でログインが作れるわけです。

ログインフォームをつくくる

<form method="POST" action="{{ route('login') }}">
    @csrf
    <div class="flex items-center justify-end mt-4">
        <a class="btn" href="{{ route('oauth:gitlab.redirect') }}"
           style="background: #FFA500; color: #ffffff; padding: 10px; width: 100%; text-align: center; display: block; border-radius:3px;">
            Login with GitLab
        </a>
    </div>
    ...
</form>

起動

ここまで作ったら起動してログインします。

php artisan serve

laravel とプラグインを使えばかんたん

とくに、gitlabやmattermostのように社内で使っているユーザ管理の仕組みが整っていたら、Laravelを使うと認証連携を手軽に作れて本当に便利ですよ。

ちょっとした問い合わせフォーム、データ集計フォーム。業務用の使い捨てアプリならサクッと作れます。

sed で行挿入をシンプルに行う。

sedなら出来る。

sed で検索文字列の直前に行を作って入れられる。 今回使ったsedgnu sedです。

マッチの直前に行を追加

サンプル

echo hello | sed '/hello/i world'

hello の直前にsay を入れました。

sed で行挿入をシンプルにやる。

sed を使って、設定ファイルを書き換えるコマンドを作っていると。

マッチ箇所の「直前」に行を入れたい。ということがよくある。

たとえば、次のようにコメントアウトをしつつ、設定を書きたい。など

leftauth=secret
#leftauth=pubkey

行挿入の例

これらは、sedで動く行挿入の例デス。

sed '1i FoooBar'
sed '1a FoooBar'
sed '/Fooo/a Baaar'
sed '/Fooo/i Baaar'

複数行を挿入する例

'\n'を使えばいい

echo names| sed -e '/names/a = ["nao"\n"aki",\n"rin"\n]'

複数行をコピペで入れるには、バックスラッシュでエスケープする

echo names| sed -e '/names/a = ["nao"\
"aki",\
"rin"\
]'

-eを使わずに置換するときは両方使う。

sed -i  "/table->id();/a  \\
      \$table->string( 'title' );\n\
      \$table->string( 'ISBN' );\n\
      \$table->string( 'author' );\n\
      \$table->string( 'located' );\
"  database/migrations/*create_book*table.php

sed の '/i/' を知るための進化の系譜。

此処から先は、 i ってなんだ?と思った人向けです。

sedは stream editor と言われます。わたしは、special な edコマンド だと思っています。

edコマンドとは、editorコマンドのことです。

edが進化した vi / sed

ものすごく、「ざっくり」いうと、edコマンドはポケモン的進化をたどっています。

  • ed は進化して exになりました。
  • exがスクリーン機能でvi になり、viは進化してvim になりました。
  • vim は さらに nvim になりした。

その一方で

  • ed は進化して sedになりました。
  • sedは進化して gnu sedになりました。

その間に、難しくなりすぎた vi を敬遠する人がいて

  • nano は vi / ed /ex コマンドがわからない人向けに作られました。

vim のEXコマンド(edモード)とsed

vim のEXコマンドモード(edコマンドモード)と同じ、というかedから派生した(とわたしは信じています。)

sedもedの進化系と考えれば、vim で覚えたEXコマンドのノウハウもsedで使えたりするのです。

「範囲✖命令」がvim の特徴

vimを思い出しましょう。 vim のed コマンドモードでは、「範囲xコマンド」になってる

:%s/hello/world/
:1,3/hello/world/
:'<,'>s/hello/world/

これは、 次のように解釈する。

EXコマンド 範囲 操作 操作内容
%s/hello/world/ % s /hello/world/
1,3/hello/world/ 1-3 s /hello/world/
<,>/hello/world/ 1-3 s /hello/world/

% は、「全部の行」、1,3 は「1-3行目」を意味する。<,>は選択範囲

s は置換 、/hello/world/は「置換前・置換後」である。

s(置換) の他になにかあるのか?

s/i/a/d のコマンド

vim といえば、ia,dを押したことがあるはずだ。あれらが「操作」である。

削除d の例

削除は、次のように行指定で出来る

1,3d
222d

sed で d,i,s,a

sed は この ed エディタの系譜になるので、vim のEx(Ed)モードと大体似ている。sed の s はストリームのSで1行ごと処理をする。

冒頭の例を分解する。

hello という文字列の直前に挿入

echo hello | sed '/hello/i say'

この例は、次のように解釈できる。/hello/ を探して Insert "say"

sed で 後続行に追加 : /hello/a

vimia の違いは知ってますよね。

ここまでわかると、i (insert)のかわりにa (append)を使ってみる。

aはAppendだから続く行に追加出来ると予想できますよね。

echo hello | sed '/hello/a world'

これは、 hello をさがして Apppend "world" と解釈できる。

コマンド例

echo hello | sed '/hello/a world'

実行結果

hello
world

ね。Vimと同じでしょ。

sedgrep も同じ祖先

grep の名の由来は、ラインエディタedのコマンド g/re/p である。その意味するところは「global regular expression print(ファイル全体から/正規表現に一致する行を/表示する)」で略号になっている[1]。

姉妹コマンドとして、正規表現ではなくリテラル(即値文字列)のみを扱う高速な fgrep[2]、拡張正規表現が使える egrep[3] がある。POSIX では fgrep、egrep を旧形式としていて、それぞれ grep -F、grep -E を使うことを標準としている。Linux Standard Baseでも指定コマンドになっている[4]。 wikipedia|grep

へぇ grep って ed 由来の名称なんですね。

つまり、こういうことか!

sed 'g/re/p'

そういえば、fgrep は思考停止出来ていいですよね。

以上が私の理解。

私の理解は、「進化」をたどって理解するという、回りくどいやり方で理解してますが、単純に例だけを覚えてもいいと思う。

sedをつかってマッチした行を削除とか、追加とか

vimは必須知識

vim は難しいとか、 vi は要らないとかいわずに、nanoを使わずにed/vi/vim(ex)/sedを使ってみましょうよ。

きっといいことがありますよ。

sedを使って設定書き換えるのも楽ちんになります。

bash で source か実行かを区別する。python/ruby の main 的なこと

bash スクリプトで main を作りたい。

スクリプトファイルは、sourceで読み込まれることがある。 実行されたときだけ、sourceで読み込まれたときだけ実行したい。という希望もまた存在する。

python の場合

python の場合は、main を使って次のようにかける。

if __name__ == '__main__':
    sys.exit(main(sys.argv))

bash の場合

bash の場合は、次のように書くことでsourceを判別できる。

if [ "$0" = "$BASH_SOURCE" ]; then
    echo "Error: Script must be sourced"
    exit 1
fi

BASH_SOURCE という変数をつかってbash sourceを判定できる。

bash って本当に便利ですね。POSIX互換?bash 互換で十分では。

sh の場合

sh の場合、完璧ではないが、ある程度の防衛策がある。

if [[ "$(basename -- "$0")" == "script.sh" ]]; then
    >&2 echo "Don't run $0, source it"
    exit 1
fi

POSIX互換でもできるけど、僕はbashでいいかな。

安心

これで、bash スクリプトを関数定義ごとに分割して書くことができる。安心である。

参考資料

Bash: detect execute vs source in a script? - Super User

Googleドキュメントでクォートの変換をやめさせる。シングル・ダブルクォーテーションの自動置換を停止

Google ドキュメントは、クォートがきれいにされる、迷惑な話だ

Googleドキュメント全般において、ダブルクォーテーション・シングルクォテーションは、入力時に文字が変換される。

" / ' を入力した例。

該当する設定=スマートクォート

スマートクォートがONになっていると上記のように、"a" →“a“  に引用符に変換される。

設定は、Googleスライドの場合次の場所にある。

ツール→設定→全般→スマートクォート

置換されることは「ある意味で正しい」

引用符には、いくつかあって文章ではを使うのが正しいので、Googleドキュメントの挙動はある意味正しい。

クォテーションの正しいありかた。

ただしソースコードのコピペなどでは、" をつかう。

上段がソースコードで使われるダブルクォーテーション。

下段が文章で使わるダブルクォーテーション。

クォテーションを自動修正させない。(方法1:全般設定)

スマートクォートをオフにすると、Googleドキュメントでは自動修正を防いで文章的にで正しいクォテーションをソースコードで使うソースコードで正しいクォテーションにする。

クォテーションを自動修正させない(方法2:都度入力)

日本語のIMEを使っていれば、入力時に指定して明示的に入力することでGoogleドキュメントでは正しく入力できる。

Google IMEの例。

意図通り入力できる。

この設定が必要な箇所

Google ドキュメント・スライドで文章を書いているとき、この違いを意識しておく必要がある。

Wireguard で v6を通す

Wireguard で v6を通す

Wireguard でv6 通信も通したい。

設定の流れ。

基本的には、v4 アドレスを足すのと同じ手順。

今回は、ルーター側がLinux(openwrt)なので、ルーター側のNAT/FW設定はiproute2/ip6tablesコマンドです。

ルーター

ルーター側wg0に、v6ローカルアドレスを追加、接続先のv6 アドレスを追加

#v6 アドレス追加
[Interface]
Address = 172.16.4.1/24, fd00::801:1/64

#v6 アドレス追加
[Peer]
AllowedIPs = 172.16.4.1, fd00::801:3

PC側(クライアント側)

# v6 アドレス追加
[Interface]
Address = 172.16.4.3/24, fd00::801:3/64

# v6 アドレス追加
[Peer]
AllowedIPs = 0.0.0.0/0, ::/0

単純に ローカルなv6アドドレス (サイトローカル/ユニークローカル)を仕込んでいく。

これで、通信できるようになる。

ルーター側にNATを仕込み、v6 NATで出ていく。

ルーター側では、v6 NATを仕込んであげる。

LAN_IF=wg1
WAN_IF=eth1

ip6tables -I FORWARD -i $LAN_IF -o $WAN_IF -j ACCEPT
ip6tables -I FORWARD -i $WAN_IF -o $LAN_IF  -j ACCEPT -m conntrack --ctstate RELATED,ESTABLISHED
ip6tables -t nat -I POSTROUTING -o $WAN_IF -d ::/0 -j MASQUERADE

経路の追加

v6の経路を確認。

ip -6 route show

経路がない場合は、経路を追加してあげる(通信相手を考えて経路追加)

WAN_IF=eth1
GW=$( [[ $(ip neigh show dev $WAN_IF ) =~ (fe80[0-9a-f:]+) ]] ; echo ${BASH_REMATCH} )
echo $GW
ip -6 route add from ::/0 to 2001:a7ff:ff63:1::a via $GW dev eth1
ip -6 route add from ::/0 to 2001:a7ff:ff47:101::1 via $GW dev eth1

疎通確認

フレッツ・クラブのIPアドレスを使って通信を確認しよう。

www.flets-west.jp 2001:a7ff:ff47:101::1
assv.asc.flets-west.jp 2001:a7ff:ff63:1::a

この2つが通れば通信ができるようになる。

wireguard でipv6 通信

wireguard でもv4 と同じ箇所にv6 アドレスを追記すればいいとわかった。

単純な方法で、なんとか、v6 NAT で通信ができるようになる。同じにかけるという点が大きい。

v6 nat について

むかしは、ipv6 ではNATは不要になるとか、なんとか言ってる人もいたし、それを突き詰めてv6 ではNATできないとかいうトンデモな設問を見たこともあるが。

v6 でも VPNのようなL3接続はNATでないと接続がめんどくさい(v4と同じ手法でかけない)。なので、やっぱりNATはあったほうがいい。

MySQLの全文検索を日本語対応にする/Mattermostの日本語検索ができない問題に対応

現れた問題点

Mattermostの日本語検索ができない

MattermostはMYSQL全文検索を使っている

MYSQL全文検索について設定する

N-gram(2-gram) で検索されない

ASANAみたいな単語は、AS-SA-AN-NA に分割されてN-gram(bi-gram)になって、MYSQLAS / AN がストップワードなので、検索されなくなります。

そこで、ngramを小さくした上で、ストップワードをオフにします。 そもそも、日本語では、英単語を単なる熟語として採用しているだけであり、検索キーワードそのものです。ストップワードする意味がありません。

/etc/mysql/mysql.conf.d/mysqld.cnf

## 2022-11-14 takuya
## https://dev.mysql.com/doc/refman/5.6/ja/fulltext-fine-tuning.html
[mysqld]
innodb_ft_min_token_size=2
ft_min_word_len=2
innodb_ft_enable_stopword=OFF

ubuntu でのファイルの場所

ubuntu では mariadb / mysql の互換性を考えていっぱいファイルが有るのですが。mysqld.conf に設置するのが基本らしい

takuya@Gitlab:~$ sudo tree /etc/mysql
/etc/mysql
├── conf.d
│   ├── mysql.cnf
│   └── mysqldump.cnf
├── debian-start
├── debian.cnf
├── my.cnf -> /etc/alternatives/my.cnf
├── my.cnf.fallback
├── mysql.cnf
└── mysql.conf.d
    ├── mysql.cnf
    └── mysqld.cnf

2 directories, 9 files

再起動で mysqld.conf を反映

sudo systemctl restart mysql

再起動後の設定反映の確認

$ sudo mysql;
mysql > SHOW VARIABLES LIKE 'innodb_ft_enable_stopword';
+---------------------------+-------+
| Variable_name             | Value |
+---------------------------+-------+
| innodb_ft_enable_stopword | OFF   |
+---------------------------+-------+
1 row in set (0.05 sec)

設定をインデックスに反映する。

インデックスを再構築するのだが、innno_db においては、OPTIMIZE table すればいい

インデックスの再構築

$ sudo mysql;
mysql > use mattermost_production_db;
mysql > OPTIMIZE TABLE Posts;

インデックスの再構築は少し時間が必要なので注意。