OmniAICreator/Qiita-1.07M huggingface dataset:
error enhanced-resolve@4.0.0:の対処

# はじめに
今回は`yarn add webpack`でエラーが発生しましたので，それの対処法を記述したいと思います．
(yarn ver 1.7.0)

# webpack追加で発生したエラー
以下が実際に発生したエラー出力です．

```bash
$ yarn add webpack
yarn add v1.7.0
[1/4] Resolving packages...
[2/4] Fetching packages...
error enhanced-resolve@4.0.0: The engine "node" is incompatible with this module. Expected version ">=6.11.5".
error Found incompatible module
info Visit https://yarnpkg.com/en/docs/cli/add for documentation about this command.
```

同じようなエラーが無いか検索すると，やはり同じような症状が発生した事例を発見．
>https://github.com/webpack/webpack/issues/6579

なんかバージョンがだめっぽい．

バージョンを変えるのがベストとコメントしているので，それに従うことに．

# バージョン指定方法
`yarn add package`に対してバージョンを指定するには以下のように@のあとにバージョンを記述すればいい．

```bash
$ yarn add package@2.12.2
```

# エラー対処方法
本題のwebpackのバージョンを指定してエラーを回避してみる．
今回バージョンは3.3.0とした

```bash
$ yarn add webpack@3.3.0
yarn add v1.7.0
[1/4] Resolving packages...
[2/4] Fetching packages...
info fsevents@1.2.4: The platform "linux" is incompatible with this module.
info "fsevents@1.2.4" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 194 new dependencies.
info Direct dependencies
```

エラーが出力されず，成功していることがわかる．

また，`yarn add webpack-dev-server`についても同じエラーが起きたが，同様の対処法で回避できる．

# まとめ
`yarn add webpack`のエラーの対処法について記述した．
他のパッケージ追加時のエラーについてもバージョン指定で
回避できるかもしれないので，迷った際はぜひバージョン指定をしてほしい．
async/await 構文で私が勘違いしていたこと～第1話～

この記事は「`async/await` 構文を使い始めの時期に私が勘違いしていたこと」を元に、「もしかして私も勘違いしているかもしれない…？」と自信がない方へ向けての「`async/await` を間違えて使わない」ための記事です。C# / .NET を前提にしています。

[Taskを極めろ！async/await完全攻略](https://qiita.com/acple@github/items/8f63aacb13de9954c5da)と併せて読んでいただくことで、より理解が深まると思います。

この記事では次のような方を対象としています。

* `async` をつけたメソッドは非同期で実行されると思っている
* `async` をつけたメソッドはバックグラウンドスレッド（？）で実行されると思っている
* `await` を書いた箇所は非同期（？）になると思っている（←非同期 is 何？って訊かれるとモニョる）
* `この非同期メソッドには 'await' 演算子がないため、同期的に実行されます。'await' 演算子を使用して非ブロッキング API 呼び出しを待機するか、'await Task.Run(...)' を使用してバックグラウンドのスレッドに対して CPU 主体の処理を実行することを検討してください。` という警告が何を言ってるかよくわからない
* なんかうまく非同期になっていないっぽい…？よし、とりあえず `Task.Run` を書いてみよう

これらのモヤモヤをひも解いていこうと思います。

# `async` をつけたメソッドは非同期とは限らない

メソッドに `async` ってつけたことがありますか？
この記事を読んでいる方は、きっと1回くらいはつけたことがある方だと思います。

下記の2つメソッドを、それぞれ `DoSomething();` `DoSomethingAsync();` と呼び出したときの違いはなんでしょう？

```csharp
public void DoSomething()
{
    DoHeavyTask(); // ← 10秒かかる重い処理
}
```

```csharp
public async Task DoSomethingAsync()
{
    DoHeavyTask(); // ← 10秒かかる重い処理
}
```

「下のメソッドは非同期メソッドなのでバックグラウンドで実行される…？」と思いましたか？
残念！2つのメソッドは実質同じ(*1)です。

実質同じとは、つまり以下のように呼び出した場合、10秒かかるのは `DoSomethingAsync` 呼び出しである、ということです。

```csharp
var stopwatch = Stopwatch.StartNew();

Console.WriteLine("before DoSomethingAsync: {0:N0}ms", stopwatch.ElapsedMilliseconds);

// ここではバックグラウンド？で DoSomethingAsync を開始だけしたつもり（非同期のつもり）
var task = DoSomethingAsync();

Console.WriteLine("after DoSomethingAsync: {0:N0}ms", stopwatch.ElapsedMilliseconds);

// ここで await することで完了を待っているつもり
await task;

Console.WriteLine("after await: {0:N0}ms", stopwatch.ElapsedMilliseconds);
```

```
before DoSomethingAsync: 0ms
after DoSomethingAsync: 10,002ms
after await: 10,003ms
```

2行目、予想に反したのではないでしょうか？
私にも2行目が `0ms` とか `1ms` とかになると思っていた時期がありました……

おいおい、`async` って言ってるのに「非同期」じゃないじゃないか……

それもそのはずです。`async` 修飾子の意味はただ一つ。

**`await` を使うメソッドには `async` をつけなければならないというルールだからつける**（＝ `async` をつけると `await` キーワードが使えるようになる）。

これだけです。`async` 自体は `await` を使うためのマーカーにすぎません。`async` をつけてもつけなくても、それだけなら何も変わらない [^1] のです。

[^1]: 実際には `async` でマークされたメソッドはビルド時に特殊な形に展開されます。また、その関係で例外発生時の挙動が変わります。ただし「非同期になるか？同期のままか？」の観点で言えば `async` をつけただけでは何も変わらないと考えて OK です

冒頭に書かれていた `この非同期メソッドには 'await' 演算子がないため、同期的に実行されます。～(中略)～を検討してください。` という警告。これは「`await` が使われていない `async` メソッドがあるとき」に出る警告です。

先の説明の通り、`await` を使わない `async` とつけたメソッドには**(async をつける)意味がない**ため、「何か勘違いしとらんか？非同期になっとらんやでそれ」という意味で警告が出るのです。

ここまでで「いやいや、戻り値の型が `void` から `Task` に変わっとるがな！一緒じゃなくね？」と思った方はいい気づき [^2] です。

[^2]: この変化が「実際には `async` でマークされたメソッドはビルド時に特殊な形に展開されます。また、その関係で例外発生時の挙動が変わります。」と関連します。

これについては後ほど触れるとして、`async` をつけて使いたい `await` というのはなんなのか？
次回はそこに焦点を当てたいと思います。

## 今回のまとめ

* `async` は `await` を使うためのマーカーにすぎず、それ自体は何もしてくれない
* ただし、戻り値の型は `void` から `Task` に変わるようだ（これについては後々説明があるようだ）
* `async` はマーカーにすぎないので `await` こそが大事らしい。`await` って何？が次回のテーマのようだ
Let's Encryptのワイルドカード証明書の発行(CensOS7)

# はじめに
本内容はLet's Encrypt ワイルドカードのSSl証明書の発行手順を**自分用のメモ**として書いております。
これにより、何らかの問題が発生しても一切責任は取りません。

# 必要なものを用意しようぜ
その前に今回の環境

```
(SSL発行):CentOS Linux release 7.4.1708
(Webサーバー): CentOS Linux release 7.3.1611
Apache: Apache/2.4.6
(クライアント): Windows7
ドメイン: Cloudflare
```

サーバーはConoHaのvpsです。
以前間違った知識をドヤ顔ぶっこいて書いたConoHaです。
あのときは申し訳ございませんでした。

さてさて、今回の環境は以上のとおりですが、諸事情で発行したVPSとWebサーバーが別なのでFileZillaを使って転送したりしました。

必要なものをインストールします。

```
yum install git
git clone https://github.com/certbot/certbot.git
```

yumからcertbotがインストール可能らしいですが、自分的にはgitからクローンしました。
インストールしたんですが、バージョンが古いためかワイルドカードの発行ができませんでした。
特に、ワイルドカード証明書発行時にエラーが出る場合はバージョンを確認してみてください。

# コマンドうつぞい
SSHでコマンド送信するわけですが、ConoHa等のvpsのコンソールからでも実行が可能だと思います。

```
./certbot-auto certonly \
  --manual \
  --domain <ドメイン> --domain *.<ドメイン> \
  --email <メールアドレス> \
  --agree-tos \
  --manual-public-ip-logging-ok \
  --preferred-challenges dns-01 \
  --server https://acme-v02.api.letsencrypt.org/directory
```

上をテンプレにして書き換えるといいと思います。
注意する点はdomainをワイルドカードと普通のドメインの2つを指定していることです。
実際やってみたわけですが、ワイルドカードだけだとブラウザ側ではSSLのエラーが出ます。

# ドメインのTXTの設定いるじゃん
表示されているレコードを設定する必要があります。
![](https://cdn.yama2211.biz/public/qiita/qiita1.PNG)
こんな感じなの(通常は白線は出ませんが、編集で隠してあります)が出るはずです。
これをドメインのレコードに登録します。
浸透に最大で24時間かかるようですが、Cloudflareの場合結構早いようです。

![](https://cdn.yama2211.biz/public/qiita/qiita2.PNG)
私だけかわかりませんが、二回認証が必要っぽいです。

![](https://cdn.yama2211.biz/public/qiita/qiita3.PNG)
発行成功するとこんな感じ。
失敗したらエラーが出ます。
大体は、TXTの浸透ができてないだけっぽいです。

# 発行した証明書をwebに適応させるぞい
スクショ3枚めの白線で隠してあるファイルパス2つが証明書(上)とプレイベート証明書(下)です。
あとは、httpd.confをいじるだけです。

```
    SSLCertificateFile /etc/letsencrypt/live/<ドメイン>/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/<ドメイン>/privkey.pem
```

若しくは

```
    SSLCertificateFile /etc/letsencrypt/archive/<ドメイン>/fullchain(数字[*1]).pem
    SSLCertificateKeyFile /etc/letsencrypt/archive/<ドメイン>/privkey(数字[*1]).pem
```

[*1]：発行数による。はじめて発行した場合1,それ以上の場合2や3など。

それでApacheをリロードさせれば設定完了です。

# 終わりに
多分できると思います。

# サンクス
- AWS CloudFront(画像CDN配信用)
- [Let's Encrypt 総合ポータル](https://letsencrypt.jp/)
- どこかのqiita記事 (テンプレをお借りしましたがどこの記事か忘れました。見つけたらリンク更新します。)
- その他ワイルドカード証明書発行に当たり幾つかのサイト内容を参考にしました。
サンクスに書かせていただいたサイト様サービス関係者様、ページの下の方からではございますが、お礼申し上げます。

# 私のリンク
Twitter: [@yamagami2211](https://twitter.com/yamagami2211)
Webサイト: https://yama2211.biz/
ROS＋MATLABでレーザーの値を取得して，描画してみた

# はじめに
ROSとMATLABが共演できるのにもかかわらず，意外と知られていないのと参考になるプログラムが少ないので書いてみます
しかもROSを普通のPCに入れるのは大変です　RaspiであればすぐできるのでRaspi+PCでやってみます

# 目的
ROSとMatlabの併用

# 詳細
ROSとMATLABを同時に扱えると例えばROSの入ったRaspiでLaserの値を取得，それをMATLAB上で取得して，ロボットのモータの指令値を生成（Matlabの制御ライブラリツールを使える→ここ重要）して，RaspiのGPIOを介して，Raspiからモータを動かすなんてこともできる

# 用意するもの
・Raspi(Ubuntu mate 16.04)
・PC(Matlabの入ったPC(2017a以上推奨））
・UST-10(Hokuyo電機）

![IMG-5295.JPG](https://qiita-image-store.s3.amazonaws.com/0/261584/c1865448-e48b-8e19-68c2-8a9794397173.jpeg)


こんな感じで配線


# コード
①Raspiでroscreを立ち上げます

```
roscore
```

②RaspiでLRSを使えるライブラリを起こします
インストール方法は探せばあるのでぐぐってください
（ROSのいいところはこういう風にライブラリを使えることにありますね）

③Matlabのコードはこんな感じ
Main file

```matlab
main.m
%% 初期化作業
clear
close all
% ROS初期化
% raspiのIPを入力（変更する場合）
% ROSCOREのIPをいれてください
rosinit('http://'ここにIP':11311')

%% 各ノード立ち上げ

% Subscriber
% Topic : /Scan
% Topic Type : MatlabはSubscribeする場合はTopic名のみで受信可能
% Callback_func : laser_func
% Topicを受信し次第@laser_funcを実行

matlab_sub_node = rossubscriber('/scan', @laser_func);%レーザの値を取得してくるSubscriber

%% またはreceiveでも値を得ることが可能

%% 片付け
rosshutdown
```

laser_func関数では

```matlab:laser_func.m
%% Laser_func
function laser_func(obj, message, src);

%% global変数(Publishノード）
global matlab_pub_node

%% massageを受信
distance = ((message.Ranges);%距離データ（）
distance_num = length(distance);%データの数
Max_angle = message.AngleMax;%最大角度
min_angle = message.AngleMin;%最小角度
angle_step = message.AngleIncrement;%ステップ角度
angle = min_angle: angle_step :Max_angle;%角度行列

%Laserのスペック
max_det_dis = 25;

%外れ値処理（値がとれずに35となった場合）
for n = 1:1:distance_num
    if distance(n) > max_det_dis && n > 1%端以外の外れ値は1つ前の角度の距離と同様
        distance(n) = distance(n-1);        
    elseif n == 1 && distance(n) > max_det_dis%端は0に
        distance(n) = 0;
    end
end

%% ここから下に処理を書いてください %%%%%%%%%%%%%%
%distanceは距離データ行列
%angleは角度行列



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% 描画
refresh%リセット
 
for n_all = 1:1:distance_num
    X_all_Data(n_all) = distance(n_all) * cos(angle(n_all));
    Y_all_Data(n_all) = distance(n_all) * sin(angle(n_all));
end

plot(X_all_Data, Y_all_Data, 'LineWidth', 3, 'Color', [0 0 1]);
hold on
%描画範囲
XLIM = max(X_all_Data);

YLIM = max(Y_all_Data);
xlim([-XLIM XLIM]);
ylim([-YLIM YLIM]);
hold off

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
```

MatlabのROSライブラリはreceiveを用いてもTopicの値を取得できますがあまりROSっぽくないので，callback関数を用いてます
実行してみると，
描画してくれました！！
次回はこれを使ってものを検出するアルゴリズムをやってみます！
なおプログラムはgithubに上がってます

https://github.com/Shunichi09/Qiita/tree/master/Laser/laser

Twitterも確認お願いします
https://twitter.com/ShunichiSekigu1
Ruby + FIGletで誇張しすぎたFizzBuzz

## **やりたいこと**
- Rubyで**`FizzBuzz`**を書きたい
- **`FIGlet`**が楽しそうなので使ってみたい

## **FizzBuzz とは**
言語入門者が学習のために行う問題です。
>1 から順に数を数えていく。但し、その数が 3 で割り切れるならば数字の代わりに Fizz と、5 で割り切れるなら Buzz と言うゲーム。3 でも 5 でも割り切れる場合は、FizzBuzz の順に言う。

[はてなキーワード](http://d.hatena.ne.jp/keyword/FizzBuzz)より

## **FIGlet とは**
コマンドラインで実行可能なAAを表現できるプログラムです。
http://www.figlet.org/
>FIGletとは、小さなASCII文字を寄せ集めてより大きな文字にし、これらから成る様々な書体を用いてテキストバナーを生成するコンピュータプログラムである

[wikipedia](https://ja.wikipedia.org/wiki/FIGlet)より

## **準備**
- FIGletをインストールします。

```
$ yum install figlet
```

- macの場合はHomebrewで

```
$ brew install figlet
```

## **ソース**
```ruby:fizzbuzz.rb
for i in 1..30

  if i % 15 == 0
    system("figlet FizzBuzz!")
  elsif i % 3 == 0
    system("figlet Fizz!")
  elsif i % 5 == 0
    system("figlet Buzz!")
  else
    puts i
  end

end
```
- figletでは`figlet hogehoge`とすることで英字をAA化することが出来ます。

## **実行結果**
![fizzbuzz.gif](https://qiita-image-store.s3.amazonaws.com/0/239966/5329710c-5ebf-2dfa-56a0-f8ade894f8c4.gif)

## **Special Thanks**
- [ฅ(・ω・ฅ) { ⏳ Ruby と figlet コマンドでカウントダウン ⏳ }](https://qiita.com/tbpgr/items/410afe52af5bcb414854)

## **あとがき**
内容のタイトル負け感がすごい・・:innocent:
Mac上でnpmで開発してたらLambdaで実行できなかった話

Mac上で開発していて、npmのnode_moduleごとパッケージングしてLambdaにアップロードしたらMac OS用のライブラリ使っているみたいでLambdaで実行できなかった話。

# 環境
- Mac: Darwin Kernel Version 17.5.0
- node: v6.10.3

# dependencies
firebaseいれたら起きたからたぶん`firebase`のせい。

```
"dependencies": {
    "async": "^2.6.0",
    "aws-sdk": "^2.3.2",
    "date-utils": "^1.2.21",
    "firebase": "^5.0.4"
}
```

# エラー内容
クラウドウォッチに以下ログがでる。

```
Unable to import module 'index': Error
Expected directory: node-v48-linux-x64-glibc
Found: [node-v48-darwin-x64-unknown]
This problem can often be fixed by running "npm rebuild" on the current system
Original error: Cannot find module '/var/task/node_modules/grpc/src/node/extension_binary/node-v48-linux-x64-glibc/grpc_node.node'
at Object.<anonymous> (/var/task/node_modules/grpc/src/grpc_extension.js:53:17)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.require (module.js:497:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (/var/task/node_modules/grpc/src/client_interceptors.js:145:12)
at Module._compile (module.js:570:32)
```

`darwin`じゃなくて `linux` をくれと言ってるのではないかとUbuntu上で `npm rebuild`してアップロードしなおしてみたら実行できた。

# 回避方法は？
聞きたい。そもそもMac上で開発しないで、Linuxカーネル上で開発するのがベストプラクティスなの？？
Node.jsでつくるNode.js - Step2：単純化

# はじめに

「RubyでつくるRuby ゼロから学びなおすプログラミング言語入門」([ラムダノート](https://www.lambdanote.com/products/ruby-ruby), [Amazon](https://www.amazon.co.jp/dp/4908686017)) と [PythonでつくるPython](http://akimacho.hatenablog.com/entry/2018/05/22/220109)に影響を受けて、Node.jsでミニNode.js作りにチャンレンジ中です。

[前回](https://qiita.com/massie_g/items/3f604413ca5ea4552b45)はソースをパースするところまでやりました。今回はAST(構文木)をシンプルに整形するところと、ミニNode.jsのカバー範囲を考えてみます。

* [もくじ](https://qiita.com/massie_g/items/3ee11c105b4458686bc1)

# ASTの単純化

[前回のStep1](https://qiita.com/massie_g/items/3f604413ca5ea4552b45)ではesprimaでASTを作りました。想像以上に複雑で、単に'1'を変換しただけでこんな大げさな構造になっています。

```
Script {
  type: 'Program',
  body:
   [ ExpressionStatement {
       type: 'ExpressionStatement',
       expression: Literal { type: 'Literal', value: 1, raw: '1' } } ],
  sourceType: 'script' }
```

この構造をそのまま使うのは正直面倒です。「RubyでつくるRuby」や「PythonでつくるPython」のコードを見ると、simplify()という処理でどうやら単純化しているようです。
それを真似してみることにします。

'1'を与えた場合に欲しいのは次のような結果です。

```
["lit", 1]
```

まずはこれだけを目指して、simplify()を作ります。

```js
function simplify(ast) {
  const exp = ast.body[0].expression;
  if (exp.type === 'Literal') {
    return ['lit', exp.value];
  }

  return null;
}
```

'1' をパース、simplify()した結果はこうなりました。

```
[ 'lit', 1 ]
```

このsimplify()を、今後拡張していく予定です。

# 仕様の単純化

今回のミニNode.jsでは、言語仕様もバッサリ単純化します。基本は「RubyでつくるRuby」を真似て、こんな感じで考えています。

* リテラル（定数）が扱える。最低限は整数、文字列、可能なら実数も
* 変数が扱える。宣言は let のみ
* 条件分岐は if のみ
* 繰り返しは while のみ
* ユーザ定義関数が作れて、呼べる
* 最低限の組み込み関数を用意する
* FizzBuzzが実装できる
* 最後はブートストラップで自分自身を実行できる（のか？？）

進行に従って仕様は変えるかもしれませんが、ひとまずこれで進めてみます。

# 次回

* [Step 3: +演算子を評価する](https://qiita.com/massie_g/items/ad6ae33ec1e46b67ad57)

# 今回のソースコード

Step2までの全体のコードはこちらです。

```js
const esprima = require("esprima");

function parseSrc(src) {
  const ast = esprima.parseScript(src);
  return ast;
}

function printObj(obj) {
  console.dir(obj, {depth: 10});
}


function simplify(ast) {
  const exp = ast.body[0].expression;
  if (exp.type === 'Literal') {
    return ['lit', exp.value];
  }

  return null;
}

// --------

const ast1 = parseSrc('1');
printObj(ast1);

const tree1 = simplify(ast1);
printObj(tree1);
```
PostfixでSMTP AUTHの利用を許可するIPアドレスを指定する方法

#はじめに

某大学でメールサーバを運用してます。

CentOS7.x/postfixで運用しているメールサーバに以下のようなSMTP AUTHに対する辞書攻撃のログが多数残っていました。

```
May 31 19:34:22 mail postfix/smtpd[6594]: warning: unknown[x.x.x.x]: SASL PLAIN authentication failed:
Jun  1 01:28:55 mail postfix/smtpd[9517]: warning: unknown[x.x.x.x]: SASL LOGIN authentication failed: XXXXX
```

うざいのでSMTP AUTHを使えるIPアドレスを限定したいと思いました。

SMTP AUTHからの正規アクセスがあるのは、某大学の学内ネットワーク限定です。学外からは辞書攻撃です。

まぁこんな環境ならsubmission(TCP/587)とか使えと思われるかもしれませんが、歴史的にsmtp(TCP/25)のままの方が多くて。。。また学内を無条件でリレー許可してSMTP AUTHやめればという意見もありかもしれませんが、ウイルスなどの感染によるメールのバラマキも考えられます。)

なんか良い方法がないかと思って探したらDovecotの設定が使えるようです。

> https://wiki2.dovecot.org/PasswordDatabase/PAM
> PAM - Pluggable Authentication Modules
> -> Restrict IP-Addresses allowed to connect via PAM

この設定はSMTP AUTH認証をDovecotに代行させている場合のみ使えます。具体的には/etc/postfix/main.cfに以下のような記述をしてSMTP AUTHを実現している場合のみです。

```/etc/postfix/main.cf
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
```

上記の環境に該当する場合は、次の方法でSMTP AUTHが利用可能なIPアドレスを制限できます。

Dovecotに以下のような記述をします。学内のIPアドレスを a.b.0.0/16 とします。pamを使っているとします。

```/etc/dovecot/conf.d/auth-system.conf.ext
passdb {
  driver = pam
  # [session=yes] [setcred=yes] [failure_show_msg=yes] [max_requests=<n>]
  # [cache_key=<key>] [<service name>]
  #args = dovecot
  override_fields = allow_nets=127.0.0.0/8,::1/128,fe80::/64,a.b.0.0/16 
  # 上記を加筆
}
```

上記の設定でSMTP AUTHがIPアドレスa.b.0.0/16 からのみ認証に成功するようになります。それ以外のIPアドレスからはSMTP AUTHが常に認証に失敗します。（注意:職場はIPv6が使えないためIPv6は動作未確認。）

具体的に認証に成功するかしないかはtelnetコマンドでSMTP AUTHの動作確認をしてみてください。

> http://d.hatena.ne.jp/toshi_hirasawa/20111124/1322134634
> smtp-auth　メモ　(telnetでEHLO)

なお、多くの環境ではSMTP AUTHはSSLで通信しているときのみ可能です。その場合はtelnetを以下のように替えてください。

> openssl s_client -connect メールサーバのサーバ名:25 -starttls smtp -ign_eof

## smtpd_sasl_exceptions_networks

上記のtelnetコマンドを使ったSMTP AUTHの動作確認ですが、EHLOコマンドを叩くとどのIPアドレスからでもSMTP AUTHが利用可能である旨の表示がされます。AUTH PLAIN.. のところです。これはDovecotでSMTP AUTHを禁止したIPアドレスからでもSMTP AUTHが利用可能であると表示されます。

```
$ telnet hoghehoge 25

EHLO クライアント名

250-メールサーバ名
250- (省略)
250-AUTH PLAIN LOGIN
250-AUTH=PLAIN LOGIN
250- (省略)
250 DSN
```

このAUTH PLAIN .. の表示を抑制したいと考えました。

マニュアルを探すとpostfixに smtpd_sasl_exceptions_networks というのがありました。この命令はSMTL AUTHの利用可であるという表示を抑制する命令です。 (注意：表示が抑制されるだけです。SMTP AUTHは受け付けます。ただし認証の可否はDovecotの設定によります。)

> http://www.postfix.org/postconf.5.html#smtpd_sasl_exceptions_networks

本当ならSMTP AUTHを許可するIPを指定する命令があったらうれしかったのですが。

ですがマニュアルを読むと 「!」 で否定がかけるようです(^_^)

なら、SMTP AUTを許可するIPアドレスを！で否定し、最後にすべてのIPアドレスからのSMTP AUTHの表示を抑制したら期待した挙動になるのではないか？

試してみた。

学内のIPアドレスを a.b.c.d/16 とします。学内のIPアドレスを!で否定します。最後にすべてのIPアドレスを示す 0.0.0.0/0 を記載します。またIPv6関連の同様の記述を行います。（注意:職場はIPv6が使えないためIPv6は動作未確認。）


```/etc/postfix/main.cf
smtpd_sasl_exceptions_networks = !127.0.0.0/8, ![::1]/128, ![fe80::]/64, !a.b.0.0/16, [::]/0, 0.0.0.0/0
```

これで試したところ、なんかうまくいってるっぽいです。 

##辞書攻撃は賢くなかった
EHLO命令でSMTP AUTHの利用可能である旨を表示させない設定をした翌日、メールのログを確認したらSMTP AUTHの辞書攻撃がやっぱり記録されていました。。。

これは！辞書攻撃はEHLO命令の出力など確認せず無条件にやってやがる！！

EHLOで表示抑制しても意味なかった。

##最後に
ここで述べている方法は設定失敗すると正規利用者のメールの送信ができなくなるため、かならず動作確認お願いします。他のところではうまく動作しないかもしれませんので。

以上です。
JavaでRSA暗号を使って暗号化する

RSA暗号での暗号化のJavaでの実装例です。秘密鍵で暗号化 → 公開鍵で復号、公開鍵で暗号化 → 秘密鍵で復号の2パターンを実装しています。

```java
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;

import javax.crypto.Cipher;

public class Main {
	public static void main(String[] args) throws Exception {
		// 公開鍵・秘密鍵を生成する。
		KeyPairGenerator kg = KeyPairGenerator.getInstance("RSA");
		kg.initialize(1024);
		KeyPair keyPair = kg.generateKeyPair();
		KeyFactory factoty = KeyFactory.getInstance("RSA");
		RSAPublicKeySpec publicKeySpec = factoty.getKeySpec(keyPair.getPublic(), RSAPublicKeySpec.class);
		RSAPrivateKeySpec privateKeySpec = factoty.getKeySpec(keyPair.getPrivate(), RSAPrivateKeySpec.class);
		PublicKey publicKey = factoty.generatePublic(publicKeySpec);
		PrivateKey privateKey = factoty.generatePrivate(privateKeySpec);

        // 平文
		byte[] plain = new byte[] { 0x01, 0x02 };

        // 秘密鍵で暗号化して公開鍵で復号する。
		Cipher encrypterWithPrivateKey = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		encrypterWithPrivateKey.init(Cipher.ENCRYPT_MODE, privateKey);
		byte[] encryptedWithPrivateKey = encrypterWithPrivateKey.doFinal(plain);
	    System.out.println("encryptedWithPrivateKey (" + encryptedWithPrivateKey.length + " bytes):");
		System.out.println(decodeHex(encryptedWithPrivateKey));

		Cipher decrypterWithPublicKey = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		decrypterWithPublicKey.init(Cipher.DECRYPT_MODE, publicKey);
		byte[] decryptedWithPrivateKey = decrypterWithPublicKey.doFinal(encryptedWithPrivateKey);
	    System.out.println("decryptedWithPrivateKey (" + decryptedWithPrivateKey.length + " bytes):");
		System.out.println(decodeHex(decryptedWithPrivateKey));

		// 公開鍵で暗号化して秘密鍵で復号する。
		Cipher encrypterWithPublicKey = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		encrypterWithPublicKey.init(Cipher.ENCRYPT_MODE, publicKey);
		byte[] encryptedWithPublicKey = encrypterWithPublicKey.doFinal(plain);
	    System.out.println("encryptedWithPublicKey (" + encryptedWithPublicKey.length + " bytes):");
		System.out.println(decodeHex(encryptedWithPublicKey));
		
		Cipher decrypterWithPriavteKey = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		decrypterWithPriavteKey.init(Cipher.DECRYPT_MODE, privateKey);
		byte[] decryptedWithPriavteKey = decrypterWithPriavteKey.doFinal(encryptedWithPublicKey);
	    System.out.println("decryptedWithPriavteKey (" + decryptedWithPriavteKey.length + " bytes):");
		System.out.println(decodeHex(decryptedWithPriavteKey));
	}

	/** byte配列を16進数表記に変換する。 */
	public static String decodeHex(byte[] bytes) {
		StringBuilder sb = new StringBuilder();
		for (byte b : bytes) {
			sb.append(String.format("%02x", b));
		}
        return sb.toString();
	}
}
```

[paiza.io](https://paiza.io/projects/uu2EoByOUJunp40XAG51yg)で実行する。
XserverにSSHログインできることに感動した！のでメモする

##SSH設定

公式マニュアル：SSH設定
https://www.xserver.ne.jp/manual/man_server_ssh.php

サーバーパネル > SSH設定 > SSH設定タブ
　"ONにする"ボタンを押下する

サーバーパネル > SSH設定 > 公開鍵認証用鍵ペアの生成タブ
　パスワードを入力して"公開鍵認証用の鍵ペア生成（確認）"ボタンを押下する
→秘密鍵がダウンロードされる


##SSH接続

公式マニュアル：SSHソフトの設定(Tera Term)
https://www.xserver.ne.jp/manual/man_server_ssh_connect_tera.php

TeraTerm等を使用します

ホスト
sv9999.xserver.jp (sv9999の部分はサーバーID)

TCPポート
10022

ユーザー名
xxxx(ユーザーID)

パスフレーズ
サーバーパネルで入力したパスワード

秘密鍵
ダウンロードされた秘密鍵


##laravelインストール

XSERVERでssh接続
https://qiita.com/chr/items/aaa5a0e005958c7a9a16

laravelマニュアル
https://readouble.com/laravel/5.5/ja/installation.html

cd /home/xxxx(ユーザーID)/xxxxx(URL)/public_html/
/usr/bin/php7.2 /usr/bin/composer create-project --prefer-dist laravel/laravel blog "5.5.*"

インストール結果
http://www.uneri.tokyo/php/blog/public/
IFTTTで保育園の送迎を楽にしたい

#動機
保育園の送迎の時、QRコードで打刻するシステムが導入された。おそらく現金の取扱いを減らしたいということでの導入だろうと思う。送り迎えの時間帯は保護者も保育者も忙しいので、そんなところで現金の取扱いをするのは微妙だなぁとは思っていた。月極の保育料は銀行引き落としになる予定だし、延長保育料はこれまで都度精算していたのを月ごとに集計するようにする予定だそうだ。であれば、集計を自動にしなければ大変である。

導入されたのは[学研教育みらい](https://gakken-kyoikumirai.co.jp/)の「すまぁと園業務支援システム」というそうだがネットに該当する情報はない。[らくらく園業務支援システム](http://hoikucan.jp/enpyuta/support-sys/index.php)というのがあるので、それが名前を変えたのだろうか。保護者としては、預けるときと引き取るときにQRコードをかざすだけであり、負担は最小限といっていいはず。

そのQRコード、紙で配られて「スマホなどに貼っていただければ」と言われたけど、それならスマホにデータとして持った方が良い。ただ、送迎のタイミングでQRコードを出すためにスマホ操作をするのは意外と面倒である。保育園に近づいたらQRコードが自動的にポップアップすれば便利なのではないか。

というわけでIFTTTを使って近接したら通知でQRコードが出るようにしてみた。

#QRコード
紙にプリントされたQRコードは小さく、スキャンしても画質が悪いので、いったん[QR Code Editor](http://www.psytec.co.jp/docomo.html)で読み込み、ついでに誤り訂正レベルを上げて再生成した。この時点で元々配られたパターンとは別物になっている。当然だが、以降のQRコードその他はIDと思しき箇所を書き換えたフェイクである。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/253516/80fbbea6-d91a-35d2-840d-db40e98b4873.png)

VPNを使ってサーバーにアクセスしているらしいが、ホスト名らしきところに[nuc6cayh](https://www.intel.co.jp/content/www/jp/ja/products/boards-kits/nuc/kits/nuc6cayh.html)という文字列が見えているのがご愛敬である。開発に使っているのか、あるいは標準ハードウェアなのだろうか。まさか運用系のホスト名を型番そのままにしてるということはないと思うが…。

今回のQRコードは一辺49セル（バージョン8）で生成されたので、余白4セルずつを加え1セル5ピクセル換算で285×285ピクセルとした。これを幅600高さ300ピクセルの中央に配置した画像ファイルを作成し、Dropboxに置いて共有リンクを作成する。

今回いちばん面倒だったのが画像ファイルの大きさの設定で、なぜかは知らないがあまり小さい画像ファイルはIFTTTの通知で表示されないため、あれこれ試行錯誤して600x300というサイズにしてみた。最終的に画面に表示されるQRコードが大きすぎても、リーダーに遠くからかざす羽目になって辛いため、なんとなくいい感じになるように設定したのが上記のとおりである。この辺はスマホの画面サイズとかにも依存するだろう。

#IFTTT
Locationで保育園の近くに入ったらトリガーが引かれるようにする。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/253516/eb7c0acc-8c02-6520-cfe0-a65f1e45ba61.png)

アクションはNotificationsで、画像付きのrich notificationを選択し、Dropbox上のQRコード画像ファイルへの共有リンクを表示するように設定する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/253516/04b5672c-7d6a-daaf-cbfc-ba04f200bff5.png)

ちなみに共有リンクは通常提供されるものそのままではなく、www.dropbox.comをdl.dropboxusercontent.comに書き換えている。これは画像サイズが小さくて通知に表示されない原因を探っているうちにこうなったもので、もしかすると通常提供される共有リンクの末尾をdl=1とするだけでもいいかもしれない。

そもそもDropboxを使う必然性はまったくないので、スマホの内部ストレージに画像ファイルを配置してfile://とかでアクセスした方がセキュリティ的には良いかもしれない。

#テスト
Fake GPSアプリを入れて徐々に保育園に近づけていくと通知がポップする。

![Screenshot_20180601-211647.jpg](https://qiita-image-store.s3.amazonaws.com/0/253516/78385af6-6c73-e990-31f9-aad7e2df6c5a.jpeg)

よしよし、これであとは迎えに行くだけだ。

#実際
ところが、実際にやってみるとポップアップしない。まあ位置情報なんてそんなもんだよね、と思いながらDropboxを開こうとするが、ちっともネットに繋がらない。もしやと思って周りを見渡すと、QRコードリーダーの横にソフトバンクWi-Fiスポットのルーターが鎮座しておるではないか…。きっとあれの設定がおかしくてネットに繋がらないのであろう。とほほ。

追記：その後ちゃんと使えています。
Node.jsでつくるNode.js - Step 1：ソースのパース

# はじめに

「RubyでつくるRuby ゼロから学びなおすプログラミング言語入門」([ラムダノート](https://www.lambdanote.com/products/ruby-ruby), [Amazon](https://www.amazon.co.jp/dp/4908686017)) という本を読んで、簡易的なプログラミング言語を作りたい熱が出てきました。そんなおりに [PythonでつくるPython](http://akimacho.hatenablog.com/entry/2018/05/22/220109)という記事を読み、自分でもNode.jsでミニNode.js作りにチャンレンジするとにしました。
どこまで続くかわかりませんが、最後はブートストラップまで行くことを目指して始めます。

* [もくじ](https://qiita.com/massie_g/items/3ee11c105b4458686bc1)

# Step 1 - ソースコードのパース

「RubyでつくるRuby」の実装は2つの部分に分かれています。

* ソースコードを解析するところ (parse)
* ソースコードを実行するところ (evaluate)

parseの部分はあらかじめ作者が用意している minruby.rb が担当してくれていて、読者は実行のevaluateだけ作る構成になっています。

PythonでつくるPythonでもparseはastモジュールで行なっていました。

Node.jsでもAST（抽象構文木）という名前は耳にします。調べて見ると、次の2つの系列があるようです。([JavaScript ASTを始める最初の一歩](https://efcl.info/2016/03/06/ast-first-step/)より)

* Esprima
* Acorn

特にこだわりもないので、Esprimaを使ってみます。

```
$ npm install esprima
```

# 初めての AST

こんなコードを書いて、パースした結果のASTがどうなっているか見ました。

```js

const esprima = require("esprima");

function parseSrc(src) {
  const ast = esprima.parseScript(src);
  return ast;
}

function printObj(obj) {
  console.dir(obj, {depth: 10});
}

// --------

const ast1 = parseSrc('1');
printObj(ast1);

```

'1' をパースした結果がこちらです。

```
Script {
  type: 'Program',
  body:
   [ ExpressionStatement {
       type: 'ExpressionStatement',
       expression: Literal { type: 'Literal', value: 1, raw: '1' } } ],
  sourceType: 'script' }
```

何やらそれっぽいです。
もう一丁、'2+3' をパースした結果もやってみます。

```
Script {
  type: 'Program',
  body:
   [ ExpressionStatement {
       type: 'ExpressionStatement',
       expression:
        BinaryExpression {
          type: 'BinaryExpression',
          operator: '+',
          left: Literal { type: 'Literal', value: 2, raw: '2' },
          right: Literal { type: 'Literal', value: 3, raw: '3' } } } ],
  sourceType: 'script' }
```

想像していたより複雑になってますが、ソースの構造が反映されているようです。今後これを出発点に進めていきます。

# ASTが使われているところ

AST初心者なので、実際どんなところで使われているのか調べてみました。

* ESLint ...　静的検証ツール
    * ASTはespreeというモジュールで生成 https://eslint.org/docs/developer-guide/architecture#the-eslint-object
* power-assert ... JavaScriptのテスト用フレームワーク
    * t_wadaさんの東京Node学園祭2014での講演資料 [power-assert, mechanism and philosophy](https://www.slideshare.net/t_wada/power-assert-nodefest-2014/15)
* AltJS の変換 ... babel などのツール
    * babel ... [Babel Plugin Handbook](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/ja/plugin-handbook.md)

ASTを使いこなせば、自分でAltJSを作るのも不可能ではなさそうです。

# 次回

* [Step2：単純化](https://qiita.com/massie_g/items/6c852f96f7271e9e70bf)
MySQLのインストールから文字コードの変更、初期設定

#MySQLのインストールから文字コードの変更、初期設定

自分のメモ用です。


##目次
1,前提条件
2,インストール
3,文字コードの設定
4,起動
5,確認


##1,前提条件
OS : CentOS7.5
DB : Mysql5.7

##2,インストール

```
//デフォルトでmysql installを実行するとmariadbが入るため一応削除
yum remove mariadb-libs
rm -rf /var/lib/mysql/

//リポジトリ追加
yum localinstall http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm

//インストールバージョン確認
yum info mysql-community-server

//インストール
yum -y install mysql-community-server

//バージョン確認(まだ起動させません)
mysqld --version

```

##3,文字コードの設定

```
vi /etc/my.cnf
(※以下を追記)
-------------------------------------------------
[mysqld]
character-set-server=utf8mb4
[client]
default-character-set=utf8mb4
-------------------------------------------------

```


##4,起動


```
//起動 & 自動起動設定
systemctl enable mysqld.service
systemctl start mysqld.service

//初期パスワード確認
vi /var/log/mysqld.log
以下のような一行があり、そこにパスワードが記載されている。
[Note] A temporary password is generated for root@localhost: ********

//初期化処理
mysql_secure_installation

```

##5,確認

```
//ログイン
mysql -u root -p
mysql> show variables like '%char%';
+--------------------------------------+----------------------------+
| Variable_name                        | Value                      |
+--------------------------------------+----------------------------+
| character_set_client                 | utf8mb4                    |
| character_set_connection             | utf8mb4                    |
| character_set_database               | utf8mb4                    |
| character_set_filesystem             | binary                     |
| character_set_results                | utf8mb4                    |
| character_set_server                 | utf8mb4                    |
| character_set_system                 | utf8                       |
| character_sets_dir                   | /usr/share/mysql/charsets/ |
| validate_password_special_char_count | 1                          |
+--------------------------------------+----------------------------+

```
Docker for Macの仮想マシンのコンソールに接続する

## 接続する

```
screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty
```

## 切断する

```
CTRL-A CTRL-\ and then y (for yes) to exit
```

## 他の方法

コンテナを起動して接続する

```
docker run -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh
```

この方法ではexitで切断できます
ES Modules対応のgsapの使い方

ウェブのトゥイーンエンジンの老舗「GSAP（グリーン・ソック・アニメーション・プラットフォーム）」（旧 TweenMax）のnpmでの使い方をまとめる。

※本記事ではNode.js v14以上を開発環境に利用しているものとして、webpackでの利用方法を解説する。webpackの導入方法については記事「[最新版で学ぶwebpack入門 \- JavaScriptのモジュールバンドラ \- ICS MEDIA](https://ics.media/entry/12140)」を参照のこと。


## Babelでの使い方

次のコマンドを入力して`gsap`モジュールをインストールする。

```bash
npm i gsap
```

詳しくはサンプルを参照。

[Babel + webpackのサンプル](https://github.com/ics-creative/170330_webpack/tree/master/tutorial-babel-gsap)


## TypeScriptでの使い方

次のコマンドを入力して`gsap`モジュールをインストールする。
型定義ファイルは`gsap`モジュールに含まれているので、別途インストールする必要はない。

```bash
npm i gsap
```

TypeScriptでは以下のように設定ファイルを用意した。

```tsconfig.js
{
  "compilerOptions": {
    // TSはECMAScript 5に変換
    "target": "es5",
    // TSのモジュールはES Modulesとして出力
    "module": "es2015",
    "moduleResolution": "node"
  }
}

```

```webpack.config.js
module.exports = {
  // モード値を production に設定すると最適化された状態で、
  // development に設定するとソースマップ有効でJSファイルが出力される
  mode: 'production',

  module: {
    rules: [
      {
        // 拡張子 .ts の場合
        test: /\.ts$/,
        // TypeScript をコンパイルする
        use: 'ts-loader'
      }
    ]
  },
  // import 文で .ts ファイルを解決するため
  resolve: {
    extensions: [
      '.ts', '.js'
    ]
  }
};

```

詳しくはサンプルを参照。

[TypeScript + webpackのサンプル](https://github.com/ics-creative/170330_webpack/tree/master/tutorial-typescript-gsap)

## import 文の書き方

```js
import { gsap } from 'gsap';
```
といった感じで`gsap`から使いたいモジュールを読み込む。

イージングもgsapモジュールから読み込むことができる。GSAP 3では文字列でイージングを指定できるようになったが、importするのが好きな人は文字列でなくても大丈夫だ。

```js
import { gsap, Bounce } from 'gsap';
```



## おまけ

次の記事の作例をgsap v3にマイグレーションした。

[高機能なモーション制作用JSライブラリGSAPを使ったタイムリマップ表現 \- ICS MEDIA](https://ics.media/entry/7162)

![](https://ics.media/wp-content/uploads/2015/06/150601_threejs_mosaic_DemoIcons.jpg)
RetrofitのGoogle Protocol Buffer Converterを使っていた場合のProGuard設定メモ

RetrofitとProtocol Buffersを連携させる場合、下記のConverterを使うケースが多いのかと思います。

Google Protocol Buffer Converter
https://github.com/square/retrofit/tree/master/retrofit-converters/protobuf

今回、Retrofit + Google Protocol Buffer Converter なAndroidプロジェクトで、ProGuardを設定しようとしたらエラーでハマったのでメモとして投稿します。

# エラー内容
特にProGuardの設定なく実行させてみると、下記のエラーが吐かれました。

```
Caused by: java.lang.IllegalArgumentException: Found a protobuf message but jp.co.b.a.a.g$a had no parser() method or PARSER field.
```

`parser()` というメソッドが難読化されて別名になったためと思われます。

コードを追うと、
https://github.com/square/retrofit/blob/master/retrofit-converters/protobuf/src/main/java/retrofit2/converter/protobuf/ProtoConverterFactory.java#L67
ここらへんでリフレクションを使って `parser()` というメソッドを使うようになっているみたいです。

# 対策

```
-keepclassmembers class your.generated.class.** {
    public static ** parser();
}
```
.protoファイルから自動生成されたクラスに対して、 `parser()` というメソッドを難読化から除外することで、エラーが吐かれることなく実行できるようになりました。:grinning:
DockerはどうやってコンテナのIDを決定しているか

Dockerがコンテナを作成したときのIDをどうやって決定しているかを説明します。
結論から言うと、ランダムなIDを生成しています。

`newContainer`関数の中で`generateIDAndName`が呼ばれ、同ファイルの`generateID`関数が呼ばれてここでランダムなIDが生成されています。

## newContainer

[daemon/container.go#L128](https://github.com/moby/moby/blob/a9bd60d674f85c2161bb702404b23501d6b746c3/daemon/container.go#L128)

```golang
func (daemon *Daemon) newContainer(name string, operatingSystem string, config *containertypes.Config, hostConfig *containertypes.HostConfig, imgID image.ID, managed bool) (*container.Container, error) {
	var (
		id             string
		err            error
		noExplicitName = name == ""
	)
	id, name, err = daemon.generateIDAndName(name)
	if err != nil {
		return nil, err
	}

	if hostConfig.NetworkMode.IsHost() {
		if config.Hostname == "" {
			config.Hostname, err = os.Hostname()
			if err != nil {
				return nil, errdefs.System(err)
			}
		}
	} else {
		daemon.generateHostname(id, config)
	}
	entrypoint, args := daemon.getEntrypointAndArgs(config.Entrypoint, config.Cmd)

	base := daemon.newBaseContainer(id)
	base.Created = time.Now().UTC()
	base.Managed = managed
	base.Path = entrypoint
	base.Args = args //FIXME: de-duplicate from config
	base.Config = config
	base.HostConfig = &containertypes.HostConfig{}
	base.ImageID = imgID
	base.NetworkSettings = &network.Settings{IsAnonymousEndpoint: noExplicitName}
	base.Name = name
	base.Driver = daemon.imageService.GraphDriverForOS(operatingSystem)
	base.OS = operatingSystem
	return base, err
}
```

## GenerateNonCryptoID

[github.com/docker/docker/pkg/stringid/stringid.go#L69](https://github.com/docker/cli/blob/master/vendor/github.com/docker/docker/pkg/stringid/stringid.go#L69)

```golang
// GenerateNonCryptoID generates unique id without using cryptographically
// secure sources of random.
// It helps you to save entropy.
func GenerateNonCryptoID() string {
	return generateID(readerFunc(rand.Read))
}
```

## generateID

[github.com/docker/docker/pkg/stringid/stringid.go#L44](https://github.com/docker/cli/blob/master/vendor/github.com/docker/docker/pkg/stringid/stringid.go#L44)

```golang
func generateID(r io.Reader) string {
	b := make([]byte, 32)
	for {
		if _, err := io.ReadFull(r, b); err != nil {
			panic(err) // This shouldn't happen
		}
		id := hex.EncodeToString(b)
		// if we try to parse the truncated for as an int and we don't have
		// an error then the value is all numeric and causes issues when
		// used as a hostname. ref #3869
		if _, err := strconv.ParseInt(TruncateID(id), 10, 64); err == nil {
			continue
		}
		return id
	}
}
```
ターミナルをフレンズにする

#ターミナルのプロンプトをフレンズにします
デフォだと下のようになっているので

```~/.bashrc
PS1="[\u@\h \W]\$ "
```


次のように変更する

```~/.bashrc
PS1="\u@\h \W すごーい！君はbashなフレンズなんだね\$ "
```

<img width="400" alt="Screen Shot 2018-06-01 at 20.24.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/212334/588a2695-be57-6921-389c-77abd3b3e769.png">
Slackって更新したくなる

macのApp storeのアップデート通知、、Slackの更新内容説明だけは、ついついアップデートしたくなる。

> 絵文字ファイルを不必要に重複してロードしていたために、チャンネル切り替えが若干重くなるという不具合がありましたが、これを修正しました。重いコートを脱いで足取りも軽くなる春、余分な物を脱ぎ捨てて動作がより軽やかになった Slack をお届けします！

[リリースノート](https://slack.com/intl/ja-jp/release-notes/mac)

## 速攻追記、、、
なんか本当に体感的に速くなった気がする。これまで絵文字投稿のウィジェット的なので一覧表示する時激重だったから、絵文字ってSlackサービスにおいて結構クリティカルポイントだったんかな。。この辺りチャーミングなリリースノート添えて更新してくれるアプリって、職人気質＋商人気質の両方感じられて感服。
そろそろ XHR を Fetch で置き換えれるようになってきた

みなさんの記憶には、 Fetch ではリクエストのキャンセルや progress が取れなく、 XHR を置き換えることはできないといったイメージがあるかと思います。

ですが、ブラウザは常に進化しています。既にリクエストもキャンセルできますし、 progress も取得可能です（対応ブラウザに限る）。

以下で紹介します。

## リクエストのキャンセル

`fetch()` メソッドには第2引数に signal を渡せます。この signal と AbortController を使うことでリクエストのキャンセルが実現できるのです。

```javascript
const controller = new AbortController();
const signal = controller.signal;

setTimeout(() => controller.abort(), 10);

fetch('http://www.example.com/', {signal})
    .then(res => {
        return res.text();
    })
    .then(text => {
        console.log(text);
    })
    .catch(e => {
        if (e.name === 'AbortError') {
            console.error('The user aborted a request.');
        } else {
            console.error(e);
        }
    });
```

- [ブラウザの対応状況](https://caniuse.com/#search=abortcontroller)
- [polyfill](https://www.npmjs.com/package/abortcontroller-polyfill)

## progress

これは `XHR#onprogress` を使っていた処理のことです。
Fetch では Streams API の `ReadableStream` を使って実現します。

```javascript
fetch('<URL>')
    .then(res => {
        const total = parseInt(res.headers.get('content-length'), 10);
        let loaded = 0;

        return new Response(
            new ReadableStream({
                start(controller) {
                    const reader = res.body.getReader();

                    async function read() {
                        let result = await reader.read();
                        while (!result.done) {
                            const value = result.value;
                            loaded += value.byteLength;
                            console.log(`${loaded} / ${total}`);
                            controller.enqueue(value);
                            result = await reader.read();
                        }
                        controller.close();
                        return;
                    };
                    read();
                }
            })
        );
    })
    .then(res => res.blob())
    .then(data => console.log('download completed'))
    .catch(e => console.error(e));
```

<img width="1619" alt="progress.png" src="https://qiita-image-store.s3.amazonaws.com/0/15757/99e43a88-ab69-fc40-ae67-ce49181f25af.png">


- [ブラウザの対応状況](https://caniuse.com/#search=streams)
- [polyfill](https://www.npmjs.com/package/fetch-readablestream)
LambdaにAlexa Smart HomeのトリガーをAWS CLI / Terraformから追加する

# 結論から先に言うと

- AWS CLIから[add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html)を実行する。その際、以下の設定が必要
 - principalに`alexa-connectedhome.amazon.com`を指定
 - event-source-tokenに`Alexa Smart HomeのスキルID`を指定
 - source-arnは特に指定しない
 - ~~terraformからはevent-source-tokenを指定できないため、Alexa Smart Homeのトリガーは[設定できない](https://github.com/terraform-providers/terraform-provider-aws/issues/2248)(2018/06/01現在)~~
     -  terraformからも、version 1.29.0以降のAWS Providerを利用することで、event-source-tokenを指定できるようになった。
     -  AWS CLIと同様のパラメータを指定することで、AlexaSmartHomeのトリガーを設定できる。
     - https://www.terraform.io/docs/providers/aws/r/lambda_permission.html#event_source_token

# 前提

Alexa Smart Home SkillのコードはAWS上でLambda関数としてホストされる。

そのために、Alexaコンソールに表示されているスキルIDを指定して、Alexa Smart HomeをLambdaのトリガーとして設定しなければならない。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/96675/547463c5-012f-c0a7-c122-cd960acb2b06.png)

AWS Console上で設定する方法はドキュメントに記載されていたが、AWS CLIまたは、Terraformで設定したかった。

# AWS CLIからAlexa Smart Homeのトリガー設定

以下の通り指定することで LambdaにAlexa Smart Homeのトリガーを追加することができる。

```bash
aws lambda add-permission \
--region us-west-2 \
--function-name (対象のLambda Function名) \
--statement-id (statement-id) \
--principal alexa-connectedhome.amazon.com \
--action lambda:InvokeFunction \
--event-source-token (Alexa Smart HomeのスキルID)
```

Lambdaからadd-permissionする際は、ARNを指定する場合が多いが、Alexa Smart Homeの場合は`event-source-token`にスキルIDを指定する。

Principalは`alexa-connectedhome.amazon.com`を指定。

# TerraformからAlexa Smart Homeのトリガー設定

~~当初、terraformで上記の設定を行えないかと調べたが、event_source_tokenが設定できないため、SmartHomeSkillのトリガー追加には未対応のようで[issue](https://github.com/terraform-providers/terraform-provider-aws/issues/2248)が挙げられていた。(2018/06/01現在)~~

Terraformからも、event_source_tokenを指定することができるようになったため、
同様の設定内容を指定することで、トリガーを追加することができる。
https://www.terraform.io/docs/providers/aws/r/lambda_permission.html#event_source_token
https://github.com/terraform-providers/terraform-provider-aws/pull/5264

event-source-tokenの詳細は[公式ドキュメントに記載されている](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html)

# 余談
ちなみに、カスタムスキルのトリガー設定方法については、公式ドキュメントに記載されている
https://developer.amazon.com/ja/docs/custom-skills/host-a-custom-skill-as-an-aws-lambda-function.html#use-aws-cli
AK4382Aのモード設定プログラム

旭化成のAK4382AというDACチップをHardOffで324円で購入したジャンクからはがして、USB DAIに接続出来るようにしてみました。DAIはTIのPCM2706でI2Sでの接続になります。AK4382Aはデーターシートを見てみると、デフォルトの入力がI2Sではありません。このチップは3線の独自仕様のコントロールになっていて、ATTiny13でI2Sに設定する簡単なプログラムを作ってみました。

![スクリーンショット（2018-06-01 19.13.09）.png](https://qiita-image-store.s3.amazonaws.com/0/104066/a6480957-c3ee-b0e2-b5f5-8c0477e6f034.png)

```c
/*
ASAHI KASEI AK4382A Mode Control Program
for ATTiny13 on Arduino
*/

#include <avr/sleep.h>

#define CSN  PB0
#define CCLK PB1
#define CDTI PB2

void setbit(int bit)
{
  digitalWrite(CCLK, LOW);
  digitalWrite(CDTI, bit);
  digitalWrite(CCLK, HIGH);
}

void setreg(unsigned char addr, unsigned char data)
{
int i;
  digitalWrite(CSN, LOW);

  setbit(LOW);   // C1
  setbit(HIGH);  // C0
  setbit(HIGH);  // R/W

  // Register Address
  for(i = 4; i >= 0; --i) {
    setbit(addr & (1 << i) ? HIGH : LOW);
  }

  // Control Data
  for(i = 7; i >= 0; --i) {
    setbit(data & (1 << i) ? HIGH : LOW);
  }

  digitalWrite(CCLK, HIGH);
  digitalWrite(CSN, HIGH);
}

void setup()
{
  pinMode(CSN, OUTPUT);
  pinMode(CCLK, OUTPUT);
  pinMode(CDTI, OUTPUT);

  digitalWrite(CSN, HIGH);
  digitalWrite(CCLK, HIGH);
  
  set_sleep_mode(SLEEP_MODE_IDLE);

  delay(5000);
}

void loop()
{
  unsigned char reg;
  
  reg = 1 << 7;  // RSTN
  reg |= 1 << 1; // PW
  reg |= 1 << 0; // ACKS
  reg |= 3 << 2; // DIF
  setreg(0, reg);

  reg = 1 << 1;  // DEM0
  reg |= 1 << 7;  // DZFE
  setreg(1, reg);
  
  reg = 0 << 2;  // DZFB
  setreg(2, reg);
    
  sleep_mode();
}
```

電源投入後5秒後に設定を行ってスリープします。バイナリは530バイトくらいでした。

AK4382AはHI/LOパルス幅は80ns以上となっていてかなり短く、とくにDelayをいれなくても大丈夫なようです。

![写真（2018-06-26 13.10） #2.jpg](https://qiita-image-store.s3.amazonaws.com/0/104066/c8162c12-af20-4cfd-4bc8-cf94540f9e58.jpeg)


FN1242は入力フォーマットをピンで設定できますが、このチップはこのようにマイコンから設定する必要があります。

このチップは2002年くらいのチップで最近の旭化成のDACチップはI2Cで制御になっているようです。

このチップのデジタル系は5VですがHiが2.2V以上なので3.3VのI2Sマスターに接続しても問題ないようです。

このDACはΔΣなチップで結構音よいです。

後日追記

このチップを製造していたと思われる、旭化成エレクトロニクス株式会社の延岡工場は2020/10の火災で焼失してしまいました。
sphinxを入れるために__init__.pyを後から入れたら大変な事になったので、今からでも気を付けることをまとめる

基礎的な話ばかりだけど、「こういう場合ってどうなんだっけ？」って頻繁に悩んでgoogle先生に教えを乞うので、この機会にきちんと整理！
コーディング規約から保守から、雑ながら包括的に。

ちょっとだけsphinxの導入とか、パッケージを意識したモジュールづくりの話とかもします。

# sphinxを入れるために\_\_init\_\_.pyを後から入れたら大変な事になったので、今からでも気を付けることをまとめる
# ファイル構成
今回の環境はこういう形で作ってます。

``` tree.
(root)
├── README.md
├── run.py
├── app
│   ├── __init__.py
│   ├── main.py
│   ├── libs
│   │   ├── __init__.py
│   │   ├── modules.py
│   │   ... py
│   └── src
│       ├── __init__.py
│       ├── modules.py
│       ... py
└── sphinx
    ├── Makefile
    ├── conf.py
    ├── make.bat
    ... rst
```

元々は\_\_init\_\_.pyなんてなかったし、appとかsphinxとかのディレクトリも後付けです。
出力先の階層が一段深まってしまったので、パスもそれぞれ書き直すことになってしまいました。
**実装に着手する前に変更に強い仕組みを考えておくのは非常に重要な事だと改めて思いました。**

## \_\_init\_\_.pyについて補足
なにかモジュールが呼ばれた場合（たとえばapp/main.py）、同階層の\_\_init\_\_.py（app/\_\_init\_\_.py）が実行するより先に呼ばれるため、
後述のapp/src/modules.pyの from ..libs import modulesも１：app/\_\_init\_\_.pyを通って２：app/libs/\_\_init\_\_.pyを通ってlibs/modules.pyが実行されます。

これを検証する場合、各ファイルの先頭にprint \_\_file\_\_とすると流れをつかみやすいが、上の通り何度も呼ばれるので、呼ばれた回数を正しく追う方が大事。
つまり、sphinxのビルド時にエラーになると呼ばれた回数だけエラー件数が増えるので、\_\_init\_\_.pyには基本的には何も書かないようにします。

## (current)
ここには\_\_init\_\_.pyを置く必要はありません。
パッケージの外から実行した時のイメージです。

``` run.py
"""
パッケージの外なのでfrom .app import mainとしない
"""

import app.main
```

### (current)/app
sphinx-apidocのソーススクリプトで指定するパッケージ（ディレクトリ）
サブディレクトリ含む以下がドキュメントとして生成される

``` app/main.py
"""
srcのモジュールを参照して何らかの処理をする
"""

from .src import modules
```

#### (current)/app/src
``` app/src/modules.py
"""
ここは普通に書く
main.pyから呼び出されて、libs/modules.pyを呼ぶ
"""

from ..libs import modules
# ～なにかの処理
```

#### (current)/app/libs
``` app/libs/modules.py
"""
ここは普通に書く
src/modules.pyから呼び出される
"""

# ～なにかの処理
```

# ハマりどころ
当たり前だがモジュールはimportされたその瞬間、その場所から当該ファイルが１行ずつ処理されます。
この時、相対的なパスで通ってきた\_\_init\_\_.pyは通るたびに呼ばれるので、夥しい量のエラーメッセージを吐き出す可能性が高く、デバッグ時に血反吐を吐くことになります。
当然、\_\_init\_\_.pyに同階層のモジュールをimportして、同階層のモジュールが巡り巡って…なんて無限ループが発生しうる可能性も考えられます。

うっかり忘れがちですが、python3では暗黙的な相対パスでのimportは禁止。
\_\_init\_\_.pyがなくてもimportができるので、本当に忘れがち。
sphinxを入れると必須になるので、この問題も未然に防げます。

sys.path.appendを使う方法も考えられるものの、相対パスが使えるならそちらを選択したいですね。

このあと、WLSで生成したsphinxドキュメントがwindows10の権限回りでハマったのですが、別記事にて。


# 参考
- <a href="https://qiita.com/sukobuto/items/15c1173b3f37f0306dd5">Python におけるモジュールとパッケージは「名前空間」</a>
- <a href="https://www.yoheim.net/blog.php?q=20160612">[Python] コーディング規約(PEP8)を学んで、Pythonらしいコードを書く</a>
- <a href="http://d.hatena.ne.jp/chlere/20110618/1308369842">Pythonでディレクトリの上層にあるモジュールをimportするときの注意点</a>
- <a href="https://qiita.com/ysk24ok/items/2711295d83218c699276">[Python] importの躓きどころ（筆者註：importの話）</a>

# 読了後いいね！をお願いします。
どれだけの方に読んでもらっているか知りたいので、お手数をおかけしますがご協力いただけると嬉しいです。
Talend - tMysqlXXXXX のパフォーマンス向上

TalendでtMysql系コンポーネントを利用する際（一部は一般的）に
パフォーマンス向上の為に意識しておくべき設定をまとめておきます。

# 対象読者 or 前提条件 or 環境
- Talendユーザ
- Talend Open Source for Big Data 6.5.1

# tMysqlConnection
「追加JDBCパラメータ」に、必要に応じてパラメータ設定を行います。

特に、何も考えずに大量データをSELECTすると、全てJVMに乗っかってしまってヒープ不足に陥るので
大量データをSELECTする場合は、以下のように適切なフェッチサイズを設定すると良いです。

&useCursorFetch=true&defaultFetchSize=10000

# tMysqlOutput

## 挿入毎の行数
「詳細設定」の「挿入毎の行数」を少し大きめに設定します。
※ここは「基本設定」の「データ操作」が「挿入」になっていると表示されます。

デフォルトだと「100」と小さめの値になっているので、「10000」ぐらいにするとかなりパフォーマンスが向上します。

## 挿入または更新、更新または挿入
いわゆるUpsert処理になりますが、おすすめしません。
自分で実装することを考えると分かりますが、UpdateなのかInsertなのかを逐一チェックして処理するので
パフォーマンスがかなり悪いです。

事前に、Updateするレコード、Insertするレコードを振り分けて
tMysqlOutputでは「挿入」だけか「更新」だけにしたほうがパフォーマンスが良いです。

# 参考

- [MySQL＋Connector/Jを使って、大量データのSELECT⇒INSERTした時の挙動を確認する](http://d.hatena.ne.jp/Kazuhira/20151010/1444498210)
git pushするとエラー（railsチュートリアル）

 ! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'http://(サーバーのリポジトリURL)'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

・原因
ローカルリポジトリが最新でないことが原因みたいです。

https://www.ipentec.com/document/git-error-non-fast-forward-in-git-pushによると
git reset コマンドなどを実行した後で、リモートリポジトリでは管理対象になっており、ローカルリポジトリでは管理対象外であり、ファイルが存在している場合、上記のエラーが発生します。管理対象外になったファイルをローカルのディレクトリから削除します。
という事も考えれるみたい。　

・解決法
まずgit fetchでもエラーが返ってくる。
git pull = git fetch →　git merge
だからすべてダメかと思ったがhttps://qiita.com/takanatsu/items/fc89de9bd11148da1438によると
Git 2.9から mergeコマンドとpullコマンドでは，--allow-unrelated-historiesを指定しない限り，無関係なヒストリを持つ２つのブランチをマージすることはできなくなった。
とのことでgit merge --allow-unrelated-histories origin/master
をすると今までの
workspace/sample_app (master) $
が
workspace/sample_app (master|MERGING) $
に変わった。

よく見ると
$ git merge --allow-unrelated-histories origin/master
Auto-merging README.md
CONFLICT (add/add): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.

と、conflictが発生している。ここはドットインストールのGIT入門を参考にvimで直した。

さて、改めてgit push origin master
結果は

Warning: Permanently added 'bitbucket.org,104.192.143.3' (RSA) to the list of known hosts.
Counting objects: 20, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (19/19), done.
Writing objects: 100% (20/20), 2.06 KiB | 1.03 MiB/s, done.
Total 20 (delta 14), reused 0 (delta 0)
To bitbucket.org:k-kiku/sample_app.git
   fbf7b46..3397615  master -> master
rasilsチュートリアル１１章

問題　→　sign upしようとしてもメールが送信されない。

解決　→　config/envoronment/production.rbの中の
host = 
にwebアプリのurlが入ってなく入れた。
するとメールが届いた。

補足　→　バリデーションがかかっていて１つのアドレスを何回もsign upに使えないから試せなくなる。そこで使ったのが、http://sute.jp/　という24h限定でアドレスを作れるサービス。
railsチュートリアル１１章

forgot passwordからメールを送ろうとするとエラー
原因はNoMethodError
token_digestなんて無いと。
コントローラー等を確認しても、チュートリアルのコードと照らしても何の間違いもない。
ググってググって。ん？
データベースのカラムだったっけtoken_digestって、、、
そしてデータベースに反映されてない。チュートリアルを見ると

$ rails generate migration add_activation_to_users \
> activation_digest:string activated:boolean activated_at:datetime
(8.2.4でも指摘しましたが、上の２行目にある > は改行を示すためにシェルが自動的に挿入する文字です。手動で入力しないよう、注意してください。

とある。改めてこなすと問題は解決。
要は、>　を消さずにやってたみたい。

rails db:migrateして、エラーはとれました。」
railsチュートリアル　画像投稿しようとするとエラー

・問題
　ログインして画像を投稿しようとするとエラーが起きる。
　We're sorry, but something went wrong.
  If you are the application owner check the logs for more information.

・解決策
heroku logs でログを見るとAccess Deniedが原因みたい。そして　:status        => 403
403エラーみたい。403エラーとは？
403エラー Forbiddenは、サーバーからのアクセス拒否を意味します。

AWSのIAMのポリシーを AmazonS3FullAccessのみアタッチするようにして
heroku run rails db:migrate　する事によって解決しました。

・参考資料
https://qiita.com/ryuchan00/items/8e414562b7122e7ec4fb
https://cloudpack.media/5726
railsチュートリアルで作ったアプリを改造する為に

・命題
チュートリアルで作ったsample_appは、そのまま保管した状態で、別にsample_appを基に改造したアプリを作りたい。

・取り組んた事
まずググってたら、git clone　を使ってsample_appのクローンを使ったらいいんじゃないかという案が出てきました。
しかしgit cloneについて調べていると問題発見。

「・git cloneした場合はread-only(読むことしかできない状態)になる」

参考資料：https://tech-camp.in/note/technology/4841/

更にググると　git pull　でリモートリポジトリから取り込む方が　git clone　よりややこしくないんじゃないか？
と思いググると　git fetch を使う方がよさげ。

参考資料：https://qiita.com/usamik26/items/28be7d2c221a7a53c2c3

結論
・ググって聞いてブランチを切る事にしました。
分からない方は、ブランチを切るでググる。

・ブランチを切ってbitbucketに新アプリ用のリポジトリを作って
そっちにpush先を変える。

現在のアドレスを確認
git remote -v

向き先を変更
git remote set-url origin {new url}

参考資料：https://qiita.com/etet-etet/items/b9c1420f3879193edaec

・そして新リポジトリに切ったブランチのみをpushする
例えばローカルのhogeブランチをリモートのmasterブランチにpush！する場合

コマンドに落としこんでみましょう。

git push origin hoge:master

参考資料：http://shoma2da.hatenablog.com/entry/2014/03/08/234523

・herokuに切ったブランチのみをpushする

ブランチをpushする書き方
git push app名 ブランチ名:master

参考資料：https://qiita.com/pugiemonn/items/bd79abbc72c20d8ee9a7


これでサンプルアプリを残したまま改造アプリを作る下準備ができました。