Hexoで画像を表示する

_config.ymlをpost_asset_folder: trueにする。

hexo new {記事title}の時に source/_postsディレクトリ以下に{記事tile}のディレクトリができるので、
そのディレクトリ内に画像を配置。

1
{% asset_img 画像名 記事名 %}

のタグで表示できます。

画像名や記事名にスペースがふくまれる場合、ダブルクォーテーションで囲ってください。

1
{% asset_img "画像名" "記事名" %}

参考url

https://hexo.io/docs/asset-folders#Tag-Plugins-For-Relative-Path-Referencing

KotlinでSpring Bootでhello worldを出してみる

KotlinのSpring Bootでhello worldを出してみました。

前提条件

  • JDKがインストール済み
  • Intellij IDEAもインストール済み

Spring Bootのフレームワークをダウンロード

Spring Initializrのから設定してダウンロード

設定の参考url

https://qiita.com/kawasaki_dev/items/1a188878eb6928880256#%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E9%9B%9B%E5%BD%A2%E3%82%92%E4%BD%9C%E6%88%90

GradleをインストールしてSpring Bootを起動してみる

Intellij IDEAからダウンロードしたSpring BootのフレームワークをOpenする。

そうすると右下にGradleをインストールしますかのようなポップアップが現れるので、そこからインストールをしてもらう。

GradleがインストールされるとProjectパネルに.gradelとbuildのディレクトリが作成され、main関数の横にrunボタンが表示されるのでrunボタンから起動してWEBアプリケーションを実行します。

Spring BootはWebサーバーが内包されている

PHPですとnginxやapacheなどのWebサーバを用意する必要がありますが、Spring Bootのフレームワーク自体にWebサーバが内包されているのでmain関数の横にrunボタンを押すだけでwebアプリケーションを起動できます、便利ですね。
ちなみに、AWSのLambdaのようなものをサーバレスといいますが、このような「WEBサーバ」の用意が不要なこともサーバレスというようです。

hello worldを表示するコード

https://github.com/unamu1229/spring-boot-demo/pull/2/files
のファイルを追加します。
再度main関数をrunすると http://localhost:8080/ にhello worldと表示されました。

参考url

Spring Initializr

https://qiita.com/kawasaki_dev/items/1a188878eb6928880256#%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E9%9B%9B%E5%BD%A2%E3%82%92%E4%BD%9C%E6%88%90

サーバレス

https://qiita.com/kannkyo/items/c3d25553fc505150bfdf#31-%E3%82%B5%E3%83%BC%E3%83%90%E3%83%AC%E3%82%B9%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3

Controller

https://spring.pleiades.io/guides/tutorials/spring-boot-kotlin/

https://blog.qbist.co.jp/?p=2654

インターフェイス名はクライアント側に由来する名前にする

インターフェイスの名前を命名する時に、サーバー側の名前ではなくクライアント側の名前をつける必要があるそうです。
このソースは、アジャイルソフトウェア開発の奥義(ロバート・C・マーチン)9.3 鍵は「抽象」にありの項目(P130)に書かれていました。
理由は、抽象クラスはそれを実際に実装するクラスとの関係よりも、それを利用するクラスとの関係の方がずっと密接だからだそうです。

Laravelのapp()->make()はアンチパターンなの?

Laravelのapp()->make()はアンチパターンなのか調べてみました。

結論

フレームワークに依存すると問題のあるドメイン層以外ではapp()->make()を利用してもいい。

調査内容

アプリケーションサービスのメソッド内でapp()->make()を利用していたら、
疎結合を意識してコンストラクタインジェクションを利用するようにコードレビューをもらったことがあったのですが、app()->make()は疎結合だし、コンストラクタからタイプヒンティングでプロパティに持たせるほうがインスタンスの作成時に必ず依存することで循環参照になりやすく結合度は高そうと思ったのでいろいろ調べて見ました。

パターンの種類でいうと
app()->make()はServiceLocaorで、
コンストラクタインジェクションはDIになります。

双方のバターンとも疎結合を基本としている。
という記事や、
そもそもDIは依存性の解決であって、依存が無くなるわけではない。
という記事があったりして正反対な意見があるようですが、ServiceLocaorをDIにすることで、サービスロケータ自体には依存しないようになるようです。

そのため、ServiceLocaorがアンチパターンのような記事をいくつか見かけたのですが、マーティンファウラー先生によるとそれは違うようです。
先生によるとDIよりService Locatorが利用できるのであれば、それを利用するのはもっともだとおっしゃっています。

1
Service Locator と Dependency Injection とのどちらを採用するかの判断は、 ロケータへの依存性が問題になるかどうかにかかっている。

とありましたので、Laravelのフレームワークを利用する上で、フレームワークに依存すると問題のあるドメイン層以外では Service Locatorを採用したほうがよさそうです。

また、同様の意見が「上田勲. プリンシプル オブ プログラミング 3年目までに身につけたい 一生役立つ101の原理原則」にも書かれていました。

1
2
結合先モジュールの質にも着目しましょう。密な結合自体は問題ですが、本質的には、不安定な要素と密に結合するのが問題になります。安定的なライブラリに依存するのは特に問題ではありません。盲目的にデータ結合を目指すというより、相手によって付き合いの深さを判断しましょう。
`

「データ結合」とは、この本の中でもっとも疎結合であるという形です。
フレームワークとして提供されるサービスロケータの質は安定的しているといえるので、盲目的に疎結合を目指してDIを利用するということは良くないようです。

参考url

マーティンファウラー

https://kakutani.com/trans/fowler/injection.html#ServiceLocatorVsDependencyInjection

マーティンファウラーとは反対の意見

http://blog.a-way-out.net/blog/2015/08/31/your-dependency-injection-is-wrong-as-I-expected/

日毎のlogrotateをテストで動かしたい

日毎のlogrotateをテストで動かしたい

AmazonLinuxで日毎の設定のlogrotateの動作確認をしたいと思い。
対象のファイルの日付をtouchで昨日にして、
/usr/sbin/logrotate /etc/logrotate.conf を実行してもログファイルが作成されませんでした。

調べてみると
/var/lib/logrotate/logrotate.status
というファイルに前回のログローテートを行った時刻を記載しているとのこと。

/var/lib/logrotate/logrotate.status に先程logrotateコマンドをした日時が記録されていたので、
その日時を昨日に変更して、再度 /usr/sbin/logrotate /etc/logrotate.conf を実行すると

無事ログファイルがローテートされました。

tips

調べている際に、logrotateは/etc/cron.dailyで実行されていて。
cron.dailyの実行は/etc/anacrontabで設定されているということを知りました。

参考サイト

https://www.khstasaba.com/?p=958
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/6/html/deployment_guide/ch-automating_system_tasks#s2-configuring-anacron-jobs

systemd Failed to execute command: Permission denied

CentOS8にてsystemdのtest.serviceを作成してみてsystemd start testを行ってみると実行に失敗、
/var/log/messagesに下記のエラーが表示されていました。

1
2
3
Mar 20 13:21:45 unamu systemd[1]: Started testscript.
Mar 20 13:21:45 unamu systemd[83619]: test.service: Failed to execute command: Permission denied
Mar 20 13:21:45 unamu systemd[83619]: test.service: Failed at step EXEC spawning /tmp/test: Permission denied

Permission deniedの表示からファイルのパーミッションを確認しましたが、問題無し。
SELinuxが邪魔をしていたようです。
有効になっているか確認

1
2
$ getenforce
Enforcing

Permissiveモードにします。

1
$ setenforce 0

その後、systemd start testで無事実行されました。

参考url

https://fujiyasu.hatenablog.com/entry/2016/08/05/094804

ファイアウォールでpingの疎通確認を拒否する

CentOS8のfirewall-cmdでpingの疎通確認を拒否を試してみました。
pingはicmpのプロトコルです。

firewallの設定内容を確認します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@localhost unamu]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: enp0s3
sources:
services: cockpit dhcpv6-client http ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

icmp-block-inversionがyesの時にicmp-blocksに記載されたICMP Typeを受け入れ、
noの時はicmp-blocksに記載されたICMP Typeを拒否します。
icmp-blocksに何も設定されていないので、icmp-block-inversionをyesにすることですべてのICMP Typeを拒否することで
pingを拒否できそうです。

icmp-block-inversionをyesにする。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@localhost unamu]# firewall-cmd --add-icmp-block-inversion
success
[root@localhost unamu]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: yes
interfaces: enp0s3
sources:
services: cockpit dhcpv6-client http ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

icmp-block-inversionが yes になったので、pingを実行して拒否されるか確認します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
~/D/g/D/laradock ❯❯❯ ping 192.168.11.17                                            (git)-[master]
PING 192.168.11.17 (192.168.11.17): 56 data bytes
92 bytes from 192.168.11.17: Communication prohibited by filter
Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
4 5 00 5400 59d4 0 0000 40 01 896f 192.168.11.4 192.168.11.17

Request timeout for icmp_seq 0
92 bytes from 192.168.11.17: Communication prohibited by filter
Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
4 5 00 5400 9edf 0 0000 40 01 4464 192.168.11.4 192.168.11.17

Request timeout for icmp_seq 1
92 bytes from 192.168.11.17: Communication prohibited by filter
Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
4 5 00 5400 40eb 0 0000 40 01 a258 192.168.11.4 192.168.11.17

^C
--- 192.168.11.17 ping statistics ---
3 packets transmitted, 0 packets received, 100.0% packet loss

100.0% packet loss となっているので拒否できているようです。

icmp-block-inversionをnoに戻しておきます。

1
2
[root@localhost unamu]# firewall-cmd --remove-icmp-block-inversion
success

応答自体を返さない場合はtargetをDROPにすることで可能です、
targetの設定を反映するにはreloadが必要なようです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[root@localhost unamu]# firewall-cmd --set-target=DROP --permanent
success
[root@localhost unamu]# firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: enp0s3
sources:
services: cockpit dhcpv6-client http ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
[root@localhost unamu]# firewall-cmd --reload
success
[root@localhost unamu]# firewall-cmd --list-all
public (active)
target: DROP
icmp-block-inversion: no
interfaces: enp0s3
sources:
services: cockpit dhcpv6-client http ssh
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:

pingで応答が無いか確認

1
2
3
4
5
6
7
8
9
~/D/g/D/laradock ❯❯❯ ping 192.168.11.17                                            (git)-[master]
PING 192.168.11.17 (192.168.11.17): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
Request timeout for icmp_seq 2
Request timeout for icmp_seq 3
^C
--- 192.168.11.17 ping statistics ---
5 packets transmitted, 0 packets received, 100.0% packet loss

AWSのサービスにpingを実行した時と同じ反応です、
これが応答が無い場合のリアクションなんですね。

元に戻しておきます。

1
2
3
4
[root@localhost unamu]# firewall-cmd --set-target=default --permanent
success
[root@localhost unamu]# firewall-cmd --reload
success

参考サイト

https://milestone-of-se.nesuke.com/sv-basic/linux-basic/firewall-cmd/
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/security_guide/sec-managing_icmp_requests
https://milestone-of-se.nesuke.com/sv-basic/linux-basic/drop-ping-on-linux/

Goの使い始めにハマったこと

GOPATH 関係

コードポイント 関係

ElasticSearchでqueryの結果が下記の\u6771\u4eac0ように日本語がUTF16のコードポイントとして表示されていた。
本当はprefの項目は東京0と表示されて欲しかった。

1
2
3
4
5
body, _ := ioutil.ReadAll(resp.Body)
mt.Println(string(body))

# コンソール出力
{"took":27,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":1,"relation":"eq"},"max_score":1.0,"hits":[{"_index":"search_job","_type":"_doc","_id":"0","_score":1.0,"_source":{"pref":"\u6771\u4eac0","employment":"full-time","line":{"name":"\u5c71\u624b\u7dda","station":["\u6771\u4eac"]}}}]}}

日本語がUTF16のコードポイントとして表示されており、
tranceformパッケージでurf16のバイトのDecodeを試したが文字化けして失敗。
(失敗例)

1
2
3
4
5
6
7
8
9
body, _ := ioutil.ReadAll(resp.Body)
hoge, _, _ := transform.Bytes(
unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM).NewDecoder(),
body,
)
fmt.Println(string(hoge))

# コンソール出力
≻潴歯㨢ⰵ琢浩摥潟瑵㨢慦獬ⱥ弢桳牡獤㨢≻潴慴≬ㄺ∬畳捣獥晳汵㨢ⰱ猢敲慬楴湯㨢攢≱ⱽ洢硡獟潣敲㨢⸱ⰰ栢瑩≳嬺≻楟摮硥㨢猢慥捲彨潪≢∬瑟≦∺畜㜶ㄷ畜攴捡∰∬浥汰祯敭瑮㨢昢汵⵬楴敭Ⱒ氢湩≥笺渢浡≥∺畜挵ㄷ畜㈶戴畜搷慤Ⱒ猢慴楴湯㨢≛畜㜶ㄷ畜攴捡崢絽嵽絽

structにqueryの結果を入れて表示すると、期待通り東京0と表示されました。
Unmarshalの中でdecodeがされているようです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
type GetResponse struct {
Took int `json:"took"`
TimedOut bool `json:"timed_out"`
Shards struct {
Total int `json:"total"`
Successful int `json:"successful"`
Skipped int `json:"skipped"`
Failed int `json:"failed"`
} `json:"_shards"`
Hits struct {
Total struct {
Value int `json:"value"`
Relation string `json:"relation"`
} `json:"total"`
MaxScore float64 `json:"max_score"`
Hits []struct {
Index string `json:"_index"`
Type string `json:"_type"`
ID string `json:"_id"`
Score float64 `json:"_score"`
Source struct {
Pref string `json:"pref"`
Employment string `json:"employment"`
Line struct {
Name string `json:"name"`
Station []string `json:"station"`
} `json:"line"`
} `json:"_source"`
} `json:"hits"`
} `json:"hits"`
}

func main() {
body, _ := ioutil.ReadAll(resp.Body)
var getResponse GetResponse
unmarshalErr := json.Unmarshal(body, &getResponse)
if unmarshalErr != nil {
fmt.Println(unmarshalErr)
}

for _, hit := range getResponse.Hits.Hits {
fmt.Println("pref", hit.Source.Pref)
}
}

# コンソール出力
pref 東京0

json全体ではなく、コードポイントの箇所のみであれば、Unquoteで文字に変換できました。

1
2
3
4
5
t := "\\u6771\\u4eac0"
converted, _ := strconv.Unquote(`"` + t + `"`)
fmt.Println(converted)
# コンソール出力
東京0