OmniAICreator/Qiita-1.07M huggingface dataset:
Apache Geodeのログ設定について

### はじめに
Apache Geodeのログについてあえて記載します。ログに関しては大きな罠があるためです。
1. デフォルトではログは無制限にたまり続ける
2. Javaクライアントを使用すると、Log4j2の使用を強制される

1については、ある日突然サーバ停止の憂き目に会います。２についてはシステム全体でログ方針が決まっている組織においては、採用を見送る事に繋がります。
実際私のチームではLogbackを採用した監視システムを構築していたため、Geodeを使用するためだけに大きな移行コストを払うことになりました。事前にこの事が判明していれば、Geodeの採用はなかったことでしょう。

###ログレベルを変更する
デフォルトでは大量にログが出てしまうため、安定稼働へ移行した場合は、ログレベルを下げる事で容量を節約できるでしょう。

```
gfsh>start locator --name=locator　--log-level=WARN

gfsh>start server --name=server　--log-level=WARN
```
###ファイルサイズを制限する
１ファイル辺りのファイルサイズと、全体のファイルサイズを制限することができます。
公式サイトでは`gemfire.properties`を使用する方法が紹介されています。下記のようにファイルを作成します。

```
#１ファイル辺りのサイズ（MB)
log-file-size-limit=100
#全体のファイルサイズ（MB）
log-disk-space-limit=1000
```

```
gfsh>start locator --name=locator　--log-level=WARN --properties-file=./gemfire.properties
```
試したことはないですが、おそらくJオプションでも設定は可能と思います。

```
gfsh>start locator --name=locator　--log-level=WARN --J='-Dlog-file-size-limit=100 -Dlog-disk-space-limit=1000'
```

### Log4j2を使用する
さらに詳細なログ設定が必要な場合あ、Log4j2を利用できるようです。
http://geode.apache.org/docs/guide/16/managing/logging/configuring_log4j2.html
### まとめ
利用状況にもよりますが、ある日突然のサーバ停止を招かないためには、本番運用をしていくうえでは、ログの設定は必須と考えます。
CSVから行列データを読み込んで行列計算、結果を書き出す


pandasとnumpyの組み合わせを試してみる。
すげえ・・・。強烈だ。マジすげえ。。。

実質数行でこんなことができてしまうのか。これをCで書こうと思うと気が遠くなる。

```matrix_test.py
import numpy as np
import pandas as pd
import csv

'''CSVファイルの読み込み'''
csvdata = pd.read_csv("./test_data.csv", header=None)
csvdata2 = pd.read_csv("./test_data_2.csv", header=None)

'''CSVから読んだデータをnumpyの行列に入れる'''
myarray     = np.array
myarray2    = np.array
myarray     = csvdata.values
myarray2    = csvdata2.values
print(myarray)
print(myarray2)

'''行列の掛け算'''
result = myarray * myarray2
print(result)

'''結果の行列をCSVファイルに書き出し'''
with open("result_data.csv", "w") as f:
    csv_w = csv.writer(f, lineterminator='\n')
    csv_w.writerows(result)

```

ちなみに実行結果。各成分を2倍。
> python .\vector_001.py
[[1 2 3]
 [4 5 6]
 [7 8 9]]
[[2 2 2]
 [2 2 2]
 [2 2 2]]
[[ 2  4  6]
 [ 8 10 12]
 [14 16 18]]

言わずもがなですが、CSVは普通のカンマ区切りデータ。エクセルで作った。
![sample.png](https://qiita-image-store.s3.amazonaws.com/0/283529/18de8ea6-8cff-415c-2421-4d4324e90162.png)
Spectacle で Mac のウインドウ移動・リサイズをショートカットキーでいい感じに

Mac でウインドウを複数開いているとき、重なった部分をドラッグでリサイズしながら調整するのが面倒でした。


Windows では標準で [Windowsキー] + [矢印キー] でウインドウのリサイズ・移動ができた気がしますが、Mac では無いようで。。

そんな中、Macでもショートカットでウインドウ操作できないかなと探していて見つけたアプリ、 <a href="https://www.spectacleapp.com/" target="_blank" rel="nofollow noopener">Spectacle</a> を紹介します。

## Spectacle とは

<a href="https://www.spectacleapp.com/" target="_blank" rel="nofollow noopener">Spectacle</a> とは、ショートカットキーでウインドウのリサイズ・移動ができるようになるアプリです。

## 環境

* MacOSX 10.13.6
* Homebrew 1.7.3

## インストール方法

Homebrew がある場合は、 `brew cask` でインストールできます。

```
$ brew cask install spectacle
```

Homebrew を使っていない方は、<a href="https://www.spectacleapp.com/" target="_blank" rel="nofollow noopener">公式サイト</a>の [Download Spectacle] から zip をダウンロードし、解凍してアプリケーションフォルダにコピーしてください。

## 起動方法

Spectacle を起動すると下記画面が表示されるので、[Open System Preferences] をクリックします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/222030/9feadfdc-63a8-b0a1-b294-db5e276bf9d8.png)

[System Preferences] - [Security & Privacy] - [Accessibility] より、`Spectacle.app` のアクセスを許可します。

許可する前に、左下の鍵アイコンをクリックし・Mac パスワードを入力し、変更を許可できるようにしておきましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/222030/56a13730-9942-1193-9e77-30678ab9dbf0.png)

起動するとステータスメニューに眼鏡アイコンが表示されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/222030/a25b418a-d6e6-e2d0-6f9e-0d486129c0ab.png)

## 操作方法

メニューを開くと一通りキー設定を確認できます。ショートカットキーは `Option`、`Command`、`Shift`、`↑↓→←` を組み合わせて操作する形です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/222030/50327365-ecdb-3dce-d872-65e7d0adfa12.png)

## 設定変更

設定変更は、上記メニューの `Preferences..` から実施できます。

ショートカットキーの変更、ログイン時起動、ステータスメニューでの起動 or バックグラウンドでの起動の選択などが設定できます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/222030/0d8d58c7-36ce-32b5-2f83-5cafeac900db.png)

## 操作イメージ

試しに Mac の付箋アプリ Stickies で、ショートカットキーを使ってウインドウ操作をしてみました。

小気味良くウインドウの大きさの調整・移動ができて便利です…！

![Sep-08-2018 13-14-03.gif](https://qiita-image-store.s3.amazonaws.com/0/222030/6d655552-6aa9-0f31-3cc2-251609d1d9cb.gif)

## 終わりに

Spectacle を使うことで、ドラッグでのウインドウ操作よりもだいぶ楽になったなと感じています。

多分似たような Mac アプリはあると思うのですが、`brew cask` でインストールできたり、必要最小限のショートカットが準備されているということで、僕はこちらで満足しています。

## 参考サイト

* <a href="https://pc-karuma.net/mac-app-spectacle/" target="_blank" rel="nofollow noopener">Mac - ウィンドウをショートカットキーでリサイズ・移動・整頓 - アプリ「Spectacle」 - PC設定のカルマ</a>
* <a href="https://www.code2bits.com/how-to-install-spectacle-on-macos-using-homebrew/" target="_blank" rel="nofollow noopener">How to Install Spectacle on macOS using Homebrew - Code2Bits</a>
Pythonでイテレータの先読みやPushBackをするには

イテレータの先読みやPushBackをするにはmore-itertoolsのpeekableが便利だとわかったのでメモ

[1, 1, 2, 4, 4, 4, 1, 2, 2, 4, 4, 5, 5]
が
[[1, 1], [2], [4, 4, 4], [1], [2, 2], [4, 4], [5, 5]]
になるように、連続する要素をまとめるコード例

```peek.py
from typing import TypeVar, Iterable, Generator, List
from more_itertools import peekable

T = TypeVar("T")
Gen = Generator[T, None, None]


def partition(items: Iterable[T]) -> Gen[List[T]]:
    items = peekable(items)
    result = []
    sentinel = object()
    for item in items:
        next_item = items.peek(sentinel)
        result.append(item)
        if item != next_item:
            yield result
            result = []


parted = partition([1, 1, 2, 4, 4, 4, 1, 2, 2, 4, 4, 5, 5])
print(list(parted))

```

peek関数は引数に何も入れない場合、最後に（先のアイテムがなくて読み込めないとき）例外出すので番兵（sentinel）を置いています。
Rにおける頻出パターンマイニングと系列パターンマイニング

Rで頻出パターンマイニングと系列パターンマイニングの手順をまとめてみました。

#頻出パターンマイニング
```
library(arules) #頻出パターンマイニングのライブラリ
library(arulesViz) #可視化のためのライブラリ

#データの読み込み
ds <- read.transactions('C:\\path\\to\\dataForR.csv', sep=',', format='basket')

#データ確認
str(ds)
summary(ds)

#頻出パターンマイニング
ds.ap <- apriori(ds) #ルール抽出
inspect(head(sort(ds.ap, by="support"),n=10)) #上位10件のルールの表示
plot(ds.ap,method='graph',control=list(type='items',layout=layout.show())) #可視化
```

#系列パターンマイニング
```
系列
library(arulesSequences) #系列パターンマイニングのライブラリ
library(arulesViz) #可視化のためのライブラリ

#データ読み込み
ds2 <- read_baskets('C:\\path\\to\\dataForR.csv', sep = ',', info = c("sequenceID","eventID","SIZE"))
#系列パターンマイニング
ds2.sp <- cspade(ds2, parameter=list(support=0.001), control=list(verbose=TRUE)) 
```
ちなみに、arulesSequencesのcspadeはRstudioで発生するbugがあるようです。


上記に関して、間違いなどあればご指摘ください。
Laradockdでmysqlが起動後すぐにexited(2)になってしまう

LaravelのDocker環境Laradockで、mysqlコンテナが起動後すぐに落ちてしまうときのメモ。

自分の場合は、mysqlのバージョンを最新の8.0から5.7に変えて使いたかったので.envを

```txt:.env
- MYSQL_VERSION=latest
+ MYSQL_VERSION=5.7
```
変えたところ、上記の現象が発生しました。（ちなみに、すでに一度mysqlコンテナを立ち上げた後です)



mysqlのdockerイメージを削除してビルドしなおしても元に戻りませんでした。そこで、mysqlのデータフォルダを削除してやり直すとうまくいきました。

```ext:.env
- DATA_PATH_HOST=~/.laradock/data
+ DATA_PATH_HOST=.laradock/data

```

直下の.laradockフォルダには他のmysqlデータも入っていてそのまま消したくなかったのと、後でまたいじれるように、laradockフォルダ内にデータフォルダの場所を変更しました。

この後、dockerイメージを削除、ビルドしなおすとしっかりコンテナが立ち上がっていてくれるようになりました。
【rails db:migrate:reset】とは

###【rails db:migrate:reset】とは
下記のコマンドを一度に実行してくれる。

1. rails db:drop
2. rails db:create
3. rails db:migrate

###rails db:seedは別で実行する


参考：https://blog.naichilab.com/entry/db_reset-vs-db_migrate_reset
      https://qiita.com/parsetree/items/e9b08c6b11f762b949de
Scala用DIコンテナ airframeの使い方

ScalaでDIコンテナというとGoogle Guiceを使っている人が多いと思うけど、僕は最近airframeを使い始めました。

https://github.com/wvlet/airframe

何がどう違うのというのは以下の記事を読んで欲しい。個人的には、Scalaで使うための設計が前提になっているかが大きいと思っています。Guiceでもいいけど、無邪気に使っているとJava前提のライブラリはハマることもあるし、Scalaの独自機能に対するケアもないので…。

https://wvlet.org/airframe/docs/comparison.html

使い方は[Quick Start](https://wvlet.org/airframe/docs/index.html)を読んでください。たけぞえさんのブログ記事 「[Scala用のDIライブラリAirframeを試してみた](http://takezoe.hatenablog.com/entry/2016/12/25/215609)」 でも紹介されています。[^1]

以上、終了でもよかったのですが、日本語で簡単に解説しておきます。

最低限知っておくとよいのは、Design, Sessionです。あとは、DIコンテナがサポートするLife Cycleは[ドキュメント](https://wvlet.org/airframe/docs/index.html)をみてください。DesignとSessionだけ、公式ドキュメントのコードを例に説明します。

## コンストラクタ・インジェクション

インジェクションのパターンには、以下の二つがあります。

- コンストラクタ・インジェクション
- イン・トレイト・インジェクション

以下はコンストラクタ・インジェクションの例です。アノテーションは不要です。

```scala
import wvlet.airframe._

class MyApp(val config:AppConfig)
case class AppConfig(appName:String)
```

イン・トレイト・インジェクションは以下のようにtraitのフィールドに対するインジェクションですが、具体的には最後に紹介します。

```scala
class Database(name:String, conn:Connection)
trait DatabaseService {
  val db = bind[Database]
}
```

## Design

GuiceのAbstractModule#configure内で記述するバインディングはDesignを使うとできます。newDesignの後に続けてbindとかtoInstanceとか、GuiceのDSLと似ています。戻り値もDesignになるので、状況に応じてDI設定を追加したり削除したりできます。

`Design#bind[A].`の後続で使えるメソッドはGuice同様様々あります。詳しくはドキュメントを参照してください。

```scala
// Define a design
val d: Dession = newDesign
  .bind[AppConfig].toInstance(AppConfig("Hello Airframe!"))
```

## Session

GuiceのInjectorに相当するのがSessionです[^2]。Sessionを使うには以下が必要です。

- Sessionがなければ Design#newSessionで生成する
- Sessionを開始するために、Session#startを呼ぶ
- Sessionを停止するために、Session#shutdownを呼ぶ

つまり、Sessionの生成・開始・停止が必要になります。当然、これらのマニュアル操作を行ってもよいですが、以下の便利な高階メソッドで自動化できます。[^3]

- `Design#build[A](body: A => Any): Any`
- `Design#withSession[U](body: Session => U): U`

```scala
// Create MyApp. AppConfig in the design will be used
d.build[MyApp]{ app => // new MyApp(AppConfig("Hello Airframe!"))
  // Do something with app
  // e.g.) println(app.config.appName)
}
// Session will be closed here
```

```scala
val appName = d.withSession{ session =>
  session.build[MyApp].config.appName
}
```
## イン・トレイト・インジェクション

最後にイン・トレイト・インジェクションを説明します。traitが持つフィールドを初期化する際にbindを使うだけです。クラスでは使えないので注意。

```scala
import wvlet.airframe._

class Database(name:String, conn:Connection)
trait DatabaseService {
  val db = bind[Database]
}

val d = newDesign
  .bind[Connection].to[ConnectionImpl]

d.withSession { session =>
  // Creates a new DatabaseService with ConnectionImpl
  val service = session.build[DatabaseService]
}

// [DON'T DO THIS] You cannot use bind[X] inside classes:
class A {
  val a = bind[B] // [Error] Because class A can't find the current session
}
```

## まとめ

airframeは、Guiceの知識があれば簡単に始められて、Guice以上にシンプルにコードが書けます。ここでは紹介しなかったのですが、タイプエリアスやジェネリック(高階型も対応)のサポートもあります。お勧めです。

次は、airframeを使った、高階型を持つ型のDIについて書きます。

追記: 書きました → [高階型の型パラメータを持つDDDリポジトリをDIできるようにする](https://qiita.com/j5ik2o/items/fd5ae7c0bf78ae4dee21)

[^1]: AccountControllerでbindを使ってますが、多分これはコンストラクタ・インジェクションにするか、classをtraiｔに変えないとDIが失敗するかも。
[^2]: 厳密には責務が違うので相当するといってはいけない気がするが、Guice脳にもわかりやすく…。
[^3]: Sessionをfor式で合成できるようにReader化するものいいですね。`type SessionRedader[A] = Reader[Session, A]`とか
laravelのwithとloadの違い

## はじめに
laravel案件で、`load`と`with`という記述を見かけたので、どのような違いがあるかまとめさせていただきました。
laravelのバージョンは5.1を使っています。

## Lazy Loading
loadとwithは以下のような「Lazy Loading」（怠惰な読込み）の問題を解決してくれます。
ユーザーテーブル`users`と投稿テーブル`posts`が1対Nであったとして、

```php
$posts = App\Post::all();

foreach ($posts as $post) {
    echo $post->user->name;
}
```
postsに10レコードあった場合、ユーザーの名前を取得するためにクエリ発行が10回されてしまい、効率的ではありません。

```sql
SELECT * FROM posts;

SELECT * FROM users WHERE id = 1;
SELECT * FROM users WHERE id = 2;
SELECT * FROM users WHERE id = 3;
‥
```
上記のような呼び出しは「Lazy Loading」（怠惰な読込み）と呼ばれます。


## with
withは「Eager Loading」（熱心な読込み）と呼ばれ、効率的なクエリ発行をする機能です。

withを使えば、10回のクエリを１回にすることができます。

```php
$posts = App\Post::with('user')->get();

foreach ($posts as $post) {
    echo $post->user->name;
}
```

以下のようなクエリが実行されます。

```sql
SELECT * FROM posts;

SELECT * FROM users WHERE id IN (1,2,3,4,5,‥)
```


## load
loadは「Lazy Eager Loading」（怠惰で熱心な読込み）と呼ばれ、既に親モデルで検索した後に効率的な読込みを実施する機能です。

利用ケースは以下のようになります。

```php
$posts = App\Post::all();
$posts->load('user');
```

先にpostで検索実行したことを「怠惰」として、その後に関連するuserに対し「熱心な読込み」を実施しています。

<br>

以下の記事を参考にさせていただきました。
https://laravel.com/docs/5.6/eloquent-relationships#eager-loading
JUnitでPowerMock使おうとしたらIllegalAccessErrorになった

# はじめに

JUnitのテストで、PowerMockを使いたくて導入しようとしてみたんですが、エラーが発生したので、その解決法をまとめます。



# 症状

```java
// Fooのテスト
public class FooTest {
	@Test
    public void testFoo() {
        // Mockを作成
        Bar bar = mock(Bar.class);
        
        // いろいろなテスト
    }
}
```

PowerMock導入前にこんな感じのテストコードを書いており、正常に動作していました。

pom.xmlにPowerMockを追加してみたところ、テスト実行時に以下のエラーが発生するようになりました。

```console
java.lang.IllegalAccessError: class org.mockito.internal.creation.jmock.ClassImposterizer$1 cannot access its superclass org.mockito.internal.creation.cglib.MockitoNamingPolicy
```

pom.xmlの内、関係ありそうなところはこんな感じです。

```xml
<dependencies>
  <!-- Spring Boot Starter Test -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
  <!-- Powermock -->
  <dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito</artifactId>
    <version>1.5.4</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>1.5.4</version>
    <scope>test</scope>
  </dependency>
  <!-- その他外部ライブラリ -->
</dependencies>
```



# 分析

ググってみたところ、こちらのQ&Aが参考になりました。

[stackoverflow - Junit Mockito error on initialization](https://stackoverflow.com/questions/41985155/junit-mockito-error-on-initialization)

こちらによると、`spring-boot-starter-test 1.4.2.RELEASE`は`Mockito 1.10.19`をデフォルトで利用しており、1.10.19には`org.mockito.internal.creation.jmock.ClassImposterizer` が入っていないそうです。

私の環境では、`spring-boot-starter-test 1.5.14.RELEASE`を使っておりまして、Mavenの依存関係を確認したところ、こちらも`Mockito 1.10.19`を利用していることがわかりました。

1.9.5には`org.mockito.internal.creation.jmock.ClassImposterizer`が入っているそうです。



# 解決法

pom.xmlを以下のように変更します。

```xml
<dependencies>
  <!-- Spring Boot Starter Test -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <!-- Mockitoを除外 -->
    <exclusions>
      <exclusion>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
  <!-- Mockitoを追加 -->
  <dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>1.9.5</version>
    <scope>test</scope>
  </dependency>
  <!-- Powermock -->
  <dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito</artifactId>
    <version>1.5.4</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>1.5.4</version>
    <scope>test</scope>
  </dependency>
  <!-- その他外部ライブラリ -->
</dependencies>
```

これで、エラーが発生しなくなりました。



# さいごに

わかりやすいQ&Aがあって助かりました。
Ruby　バッチ処理の流れ

#wheneverのgemをinstall
wheneverによりcrontab(バッチ処理設定)を設定できるようになる。

#config/schedule.rbファイル生成
このファイルに定期的に実行する頻度と、実行するファイルを記述する。
（どういったバッチがどういう周期でまわっているのか一目瞭然）

``` schedule.rb 
set :output, 'log/crontab.log'　←ここにログを吐く
env :PATH, ENV['PATH']

every :day, :at => '2:30 am', :roles => [:app] do　　←バッチ処理の時間設定
  rake "test:sample"　　　　　←実行するrakeタスクの名前
end
```

#rakeファイル作って、実行したいコードを書くだけ。
```lib/task/test.rake
namespace :test do　　←namespaceは必要なら入れるの
  desc "説明文書いた"　　←タスクの説明文
  task :sample => :environment do　　　←sampleという名前つけている
    実行したい処理
  end
end

```

　＊処理を書くのにメソッドが必要なら、service.rbにメソッド書いてそれ使ったり。

＊cronとはUNIX系のOS（Linuxとか）に入っているプログラムのひとつ。
事前に「いついつになったら、このプログラムを動かしてね」と指示を出しておくと、その時間になったときに指定しておいたプログラムを動かしてくれるやつです。


#まだこれで終わりじゃない。指定した時間に動くように設定する。
最後に、cronに反映する際のコマンドを入力する必要があるねん。

``` $ bundle exec whenever --update-crontab ```

これで何もエラーでなければOKっす。
これで定期的にバッチを回せます。



参考：https://qiita.com/yumiyon/items/388fbb84450f49a6ab0d
rsyslogでシステムログ管理

##はじめに
Linuxでのログ管理では定番のrsyslogに関して記事にしました。
詳細は説明は省き、構築や設計時に使えるネタをまとめました。

##rsyslogとは
- ログ管理システム<br>
  RHEL7系・6系ではrsyslogが標準<br>
  RHEL5系ではsyslogが標準

rsyslogではUDPの他、TCPでログを送ることができるようになった。

##動作確認環境

|項目| バージョン|
|:-----------------|:------------------|
|OS|CentOS Linux release 7.4.1708 (Core)|
|rsyslog|rsyslog-8.24.0-12.el7.x86_64|

rsyslogはデフォルトでインストール済み。

##rsyslog設定(送信側)

・書式

```
UDPで送信
 [送信するファシリティ/プライオリティを指定] @remote-host:514

TCPで送信
 [送信するファシリティ/プライオリティを指定] @@remote-host:514
```

・例

```
*err;mail.none;authpriv.none;cron.none @@192.168.10.1:514
```

err以上のログを、192.168.10.1へTCPで転送する。
noneを指定したファシリティは転送しない。

##rsyslog設定(受け側)
受付けるプロトコルを設定します。
デフォルトではコメントアウトされている為、利用するプロトコルに合わせてコメントアウトを解除します。

UDP・TCP両方利用する場合は、下記のように設定する。

```
# Provides UDP syslog reception
#$ModLoad imudp
#$UDPServerRun 514
#↓コメントアウト解除
$ModLoad imudp
$UDPServerRun 514

# Provides TCP syslog reception
#$ModLoad imtcp
#$InputTCPServerRun 514
#↓コメントアウト解除
$ModLoad imtcp
$InputTCPServerRun 514
```

##ログ書き込みレートを設定する。
デフォルトでは、5秒、200行まで書き込みを行いますが、200行以降は破棄されてしまいます。

5秒に200行以上ログが転送されるようなシステムの場合、チューニングが必要な項目になります。

- 無制限に書き込む

```
$SystemLogRateLimitInterval 0
```


- 5秒、1000行まで書き込む、以降は破棄

```
$systemLogRateLimitInterval 5
$SystemLogRateLimitBurst 1000
```

##ログ振り分けを行う
転送されてきたログの振り分け(err以上とwarn以下)を行いたい場合に、簡単な条件式が利用できます。

warn,notice,infoは /var/log/sv/hoge.logに書き込む。


```
if $fromhost-ip == "IP Address" and $syslogseverity > '3' then /var/log/sv/hoge.log
& stop
```

err,crti,alert,emerg,panicは/var/log/sv/hoge-err.logに書き込む。

```
if $fromhost-ip == "IP Address" and $syslogseverity < '4' then /var/log/sv/hoge-err.log
& stop
```

syslogseverityの値を利用して、条件により振分けを行っている。

|syslogseverity|syslogseverity-txt|
|-----|-----|
|0|emerg,panic|
|1|alert|
|2|crit|
|3|err|
|4|warning|
|5|notice|
|6|info|
|7|debug|

また、「& stop」を入れることですでに振り分けたログは以降の処理で書き込まない様にできる。

「& stop」を入れない場合、デフォルトで設定されている下記設定によって/var/log/messageにも転送ログが書き込まれる。
処理は上から順に行われる為、下記設定より上に記述する。

```
*.info;mail.none;authpriv.none;cron.none                /var/log/messages
```

##ネットワーク機器からのログ
ネットワーク機器からのログは、ファシリティを利用する。

- ネットワーク機器側の設定

|ファシリティ|syslogseverity|リモート先|
|-----|-----|-----|
|local2|0～7|IP Address|
ファシリティはlocal0～local7で任意の値を利用する。

- サーバ側の設定
 
```
local2.err                /var/log/nw/honge-nw.log
```
ネットワーク機器が複数ある場合は、送信元IPで識別して振り分けを行います。

```
if $fromhost-ip == "IP Address" then /var/log/sv/hoge-nw1.log
& stop

if $fromhost-ip == "IP Address" then /var/log/sv/hoge-nw2.log
& stop
```
古いMacBook Airを、High Sierraに上げて開発環境を設定する

外で開発する事が増えたので、古いMacBook AirのOSをHigh Sierraに上げました。
ついでに開発環境(Node.jsとか)を入れた際に、少しハマったのでメモです。


# かつてインストーラで入れた、古いNode.jsが入っていたので、消す

- [Mac OS X から Node.js をアンインストールする方法](http://d.sonicjam.co.jp/post/52541343939)

```
lsbom -f -l -s -pf /var/db/receipts/org.nodejs.pkg.bom \
| while read i; do
  sudo rm /usr/local/${i}
done
sudo rm -rf /usr/local/lib/node \
     /usr/local/lib/node_modules \
     /var/db/receipts/org.nodejs.*
```


# nodebrewというNode.jsのバージョン管理ツールを入れる

```
brew install nodebrew
vi .~/.bashrc
####以下を追加####
export PATH=$HOME/.nodebrew/current/bin:$PATH
####
source ~/.bashrc
nodebrew -v
```

# Node.jsのインストール

```
nodebrew setup
nodebrew ls-remote   # インストールできるバージョン一覧を得る
nodebrew install-binary stable   #最新バージョンをインストール
nodebrew ls   # ダウンロードしたnodeのバージョンを確認
nodebrew use v10.10.0
node -v    # v10.10.0
npm -v   # 6.4.1
```

## npmでパッケージが入らない

- sudoをつけずに実行してみる

```
npm install -g truffle-hdwallet-provider
```

## npmでパッケージを入れたのに、requireしようとすると見つからず、```Error: Cannot find module 'モジュール名'```が出る

- require で探すモジュールのパスを確認する。[参考ページ](https://qiita.com/DNA1980/items/11fdb7233fc288ac3502)。

```
node
> global.module.paths
[ '/Users/ユーザ名/repl/node_modules',
  '/Users/ユーザ名/node_modules',
  '/Users/node_modules',
  '/node_modules',
……
]
```
- 不足していたら追加する

```
echo $NODE_PATH   #空っぽ
vi ~/.bash_profile
に
export NODE_PATH=`npm root -g`
を追加。
```

## 現在のシェルが何か調べる
```
echo $SHELL    # /bin/bash でした。
```

## ターミナルで、.bashrcが読み込まれない
.bash_profileに以下を追加

```
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi
```


# ローカルのディレクトリをApacheで公開する設定
- かつては「サイト共有」という機能が「システム環境設定」の「共有」にありましたが、無くなりました。
- OSアップグレード前にあった、~/Sites というフォルダは残っています。

```
sudo vi /etc/apache2/httpd.conf
以下の行のコメントをはずす
#LoadModule userdir_module libexec/apache2/mod_userdir.so
と
#Include /private/etc/apache2/extra/httpd-userdir.conf


sudo vi /etc/apache2/users/ユーザ名.conf  # ユーザごとの設定ファイルを作成

<Directory "/Users/*/Sites/">
AllowOverride All
Options Indexes MultiViews
Options +FollowSymLinks
Require all granted
</Directory>
```


```
vi /private/etc/apache2/extra/httpd-userdir.conf

UserDir enabled
UserDir Sites
Include /private/etc/apache2/users/*.conf
<IfModule bonjour_module>
       RegisterUserSite customized-users
</IfModule>
```

## Apache起動
```
sudo apachectl start
```
【Rust】windowsでggez(ゲーム開発ライブラリ)を動かすまで

2019/4/13 追記
ggez の開発が進んでおり、SDL2 の設定は不要になりました。
当記事の内容は古いので、現時点で動く（画像表示/BGM/SE/キー入力）サンプルを置いておきます。
https://github.com/ahyaemon/ggez_template
150行程度のサンプルなので、ソースコードを読めばある程度分かるかと思います。
使用している曲は自作の超良曲です。

# はじめに
[昔作ったゲーム](http://ahyaemon.matrix.jp/game/super-libre.html) の次回作を Rust で作ろうと思い、良いゲームライブラリがないか調べたところ ggez というものがありました。
https://github.com/ggez/ggez

まだほとんど触っていませんが、hello world を出すところまでやったので書いておこうかと思います。

# 環境
OS: Windows 10
rustc: 1.28.0
tool-chain: stable-x86_64-pc-windows-msvc

rust は rustup-init.exe を使用してインストールしています。
https://www.rust-lang.org/ja-JP/install.html

# Rust-SDL2のインストール
ggez を動かすためには Rust-SDL2 がインストールされている必要があります。
https://github.com/Rust-SDL2/rust-sdl2

### 1. SDL2-devel-2.0.x-VC.zip のダウンロード
下記サイトの Download ページからダウンロードします。
http://www.libsdl.org/

私がダウンロードしたときのバージョンは SDL2-devel-2.0.8-VC.zip でした。
※ toolchain に msvc を使用しているため、VC をダウンロードしています。

### 2. zipを解凍
一応私は C ドライブ直下に解凍しましたが、どこでもいいです。

### 3. .libファイルをコピー
解凍した zip の中に、
> SDL2-devel-2.0.x-VC\SDL2-2.0.x\lib\x64\

というフォルダがあり、その中の .lib ファイルを必要な場所にコピーします。
※ .lib ファイルと一緒に .dll ファイルも入っていますが、後で使います

rustup-init.exe を使用して rust をインストールしている場合、
> C:\\Users\\{ユーザー名}\\.multirust\\toolchains\\{アクティブなtoolchain}\\lib\\rustlib\\{アクティブなtoolchain}\\lib

というフォルダがあるので、その中にコピーします。

※ rustup-init.exe 以外の方法で rust をインストールしている場合はコピー先が異なるので、[Rust-SDL2のgithub](https://github.com/Rust-SDL2/rust-sdl2)を参考にしてください

# cargoプロジェクトの作成・実行
### 1. プロジェクトを作成
```
cargo new my_first_ggez --bin
```

### 2. SDL2.dll をコピー
先ほど解凍した SDL2 の
> SDL2-devel-2.0.x-VC\SDL2-2.0.x\lib\x64\

の中に SDL2.dll というファイルがあります。
これをプロジェクト直下に置きます。
> my_first_ggez\SDL2.dll

### 3. Cargo.tml の編集
sdl2, ggez への依存関係を追記します。

```
[dependencies]
sdl2 = "0.31"
ggez = "0.4"
```

### 4. サンプルをコピー
#### 4.1. hello_world.rs のコピー
ggez のサンプルページから、hello_world.rs を丸ごとコピーして、main.rs に貼り付けます。
https://github.com/ggez/ggez/blob/master/examples/hello_world.rs

#### 4.2. DejaVuSerif.ttf のコピー
hello_world.rs では フォントファイル DejaVuSerif.ttf を使うので、コピーしてきて resources フォルダに置きます。
https://github.com/ggez/ggez/blob/master/resources/DejaVuSerif.ttf
> my_first_ggez\resources\DejaVuSerif.ttf

### 5. ビルド
```
cargo build
```
※　次の run の時にビルドされるので、build はやらなくてもいいです

### 6. 実行
```
cargo run
```

### 7. 結果
<img width="596" alt="hello_world.png" src="https://qiita-image-store.s3.amazonaws.com/0/244354/af4357b4-a9b3-87be-3d55-3d8e6cb36bcb.png">

# おわりに
あとは色々サンプルを見ながら作りたいゲームを作りましょう。
Item 61: Prefer primitive types to boxed primitives

# 61.ボクシングされたプリミティブ型（boxed primitive）より、プリミティブ型（primitive）を選択すべし
## ボクシングされたプリミティブ型とプリミティブ型の違い
Item6でも述べられれているように、オートボクシングとオートアンボクシングにより、ボクシングされたプリミティブ型（以下boxed primitive）とプリミティブ型（以下primitive）の違いはあいまいになっている。
しかし、これらの2つには違いがあり、使用時にはその差異に気を付けながら使わなければならない。その違いは3つで、
* primitiveは値のみを持つが、boxed primitiveは値とは異なる形で参照を持つ。
* primitiveは機能する値しか持ちえないが、boxed primitiveはnull（nonfunctional value）があり得る。
* primitiveのほうが、時間的にも省メモリスペース的にも優れている。

## boxed primitiveを使用した場合の誤り例

### primitiveは値のみを持つが、boxed primitiveは値とは異なる形で参照を持つ
以下のコードは一見うまく比較をしてくれるメソッドにみえる。

```java
// Broken comparator - can you spot the flaw?
Comparator<Integer> naturalOrder =
    (i, j) -> (i < j) ? -1 : (i == j ? 0 : 1);
```
しかし、このメソッドを```naturalOrder.compare(new Integer(42), new Integer(42))```のように用いると、想定としては等しいので0を返すはずだが、実際には1を返す。
1つ目の判定（i < j）は、auto-unboxedされて正しく動作する。
一方、2つ目の判定（i == j）は、同値であることをみる、つまり、参照が同じであるかをみている。よって、この比較はtrueにはならず、結果として1が返却される。 boxed primitiveに対して==演算子を用いることはたいてい間違っている。

上記の誤りを防ぐためには、```Comparator.naturalOrder()```を用いるか、自身でcomparatorを書くのであれば、以下のようにprimitiveでの比較を行うようにする。

```java
Comparator<Integer> naturalOrder = (iBoxed, jBoxed) -> {
    int i = iBoxed, j = jBoxed; // Auto-unboxing
    return i < j ? -1 : (i == j ? 0 : 1);
};
```

### primitiveは機能する値しか持ちえないが、boxed primitiveはnull（nonfunctional value）があり得る

以下のプログラムでは、ヌルポが発生する。

```java
package tryAny.effectiveJava;

public class BoxedPrimitive {
    static Integer i;

    public static void main(String[] args) {
        if (i == 42)
            System.out.println("Unbelievable");
    }

}
```
i==47のところで、Integerとintを比較している。
boxed primitiveとprimitiveが混じった処理においては、**たいていの場合boxed primitiveがauto-unboxされる。**
nullを参照しているオブジェクトをunboxするとヌルポが生じるが、それがここでは起きている。

### primitiveのほうが、時間的にも省メモリスペース的にも優れている
以下は、Item6で扱ったプログラムである。

```java
package tryAny.effectiveJava;

public class BoxedPrimitive2 {
    // Hideously slow program! Can you spot the object creation?
    public static void main(String[] args) {
        Long sum = 0L;
        for (long i = 0; i < Integer.MAX_VALUE; i++) {
            sum += i;
        }
        System.out.println(sum);
    }

}
```
box化、unbox化が繰り返し起こるため、これはローカル変数の型をlongにした場合よりも格段に遅い。

## 総括
3つの問題点があったが、最初の2つは結果がおかしくなり、最後の1つは性能が悪くなる。

boxed primitiveの使い時としては以下の場合がある。
* collectionの要素、キー、バリューとして使うとき。primitiveをcollectionに入れることはできないので使わざるを得ない。
* パラメータ化された型に用いるとき。例えば、```ThreadLocal<int>```という型は宣言できないが、```ThreadLocal<Integer>```は宣言できる。
* リフレクションでメソッドを参照するときはboxed primitiveを使う（？）。（Item65）
Mac OSX で共有ライブラリを-rpathを付けてリンクしたのに、実行時に共有ライブラリが見つからないエラーが出て格闘した。

# 参考情報
  - [Mach-Oバイナリのライブラリロードパスをカスタマイズする方法](http://mojavy.com/blog/2013/05/17/mach-o-rpath/)
  - [Install_name on OS X](http://log.zyxar.com/blog/2012/03/10/install-name-on-os-x/)

# 実行ファイルのコンパイルオプションの問題ではない模様
## 症状
``clang++ -o foo foo.cc -Wl,-L,${somewhere} -Wl,-rpath,${somewhere} -lbar``とコンパイル、リンクしたのにもかかわらず、``foo``を実行すると、``dyld: Library not loaded: libbar.X.Y.dylib``といったエラーがでる。もちろん、``${somewhere}/``以下に``libbar.X.Y.dylib``は存在する。環境変数``DYLD_FALLBACK_LIBRARY_PATH``を設定すれば実行することは可能であるが、それではもともと``-rpath``をつけてリンクしたかった意図は実現できていない。

## 調査
``otool -L foo``として該当する共有ライブラリの項目をみると、``libbar.X.Y.dylib``とだけ表示されてる。一方、``-rpath``でリンクして実行時に思い通りに見つけられている共有ライブラリの場合、``@rpath/libaaa.X.Y.dylib``もしくはフルパスで表示される。
## 対処
  - 参考情報によると、共有ライブラリのコンパイル時に適切に"install_name"が適切に設定されていないと、実行ファイルのコンパイル時に``-rpath``オプションを付けても実行時共有ライブラリ検索パス設定が働かない、ということらしい。対処法としては、2つあるらしい。

  1. 共有ライブラリを修正する。リンカオプション``-Wl,-install_name,@rpath/libbar.X.Y.dylib``(もしくはフルパスで指定)をつけて構築しなおす。もしくは、構築後の共有ライブラリを``install_name_tool -id "@rpath/libbar.X.Y.dylib"　${somewhere}/libbar.X.Y.dylib``として修正してしまう。（ただし、この方法を取れるかどうかは環境（ユーザー権限）によるであろう。）
  1. 実行ファイルを修正する。参考情報によると、``install_name_tool -change "libbar.X.Y.dylib" "@rpath/libbar.X.Y.dylib" 実行ファイル``でいけるらしい。（まだ試していない。）
Serverspecを使ってみた（２）

[１回目](https://qiita.com/ttjhykw2/items/d016ac822036d9e26280)の続きです。

# テストファイル（続き）
パッケージとサービスのテストを行います。

07package_spec.rb

コメント欄にも書きましたが、CentOS7の場合、何のコマンドでテストしているのかと、思ったら、yumとかではなく`rpm -q` でした。この辺り、Serverspec(Specinfra)のコードを読まないと分からないため、何も知らない人でも使えるツールとは言えないのはしょうがないかなとは思いました。ツールではなくフレームワークですから。

```07package_spec.rb
require 'spec_helper'

# check by "rpm -q" on RedHat
describe package('chrony') do
  it { should be_installed }
end

describe package('chrony') do
  it { should be_installed.by('rpm').with_version('3.1-2.el7') }
  #it { should be_installed.by('rpm').with_version('3.1-3') }
end
```

08service_spec.rb

これもソースを読んで確認しましたが、CentOS7だとsystemd配下であることを前提にサービスの確認をしています。つまり最後のテスト

> describe service('chronyd') do
>   it { should be_running.under('systemd') }
> end

は、無くても良いです。

```08service_spec.rb
require 'spec_helper'

# checked by systemctl on Redhat7
describe service('chronyd') do
  it { should be_enabled }
end

describe service('chronyd') do
  it { should be_enabled.with_level(3) }
end

describe service('chronyd') do
  it { should be_running }
end

describe service('chronyd') do
  it { should be_running.under('systemd') }
end
```

今回はここまで。まだ続きます。
DNSの勉強ノート【その1】名前解決


## はじめに

- 今回の内容
  - 名前解決の概要と歴史
  - ドメイン

## 名前解決とは

- TCP/IPにおいて通信相手を特定するのはIPアドレスだが、人間にとって数字の羅列は覚えにくい。
- 通信相手を、人間にとって覚えやすい文字列（ドメイン名）で指定できるようにする仕組みがほしい。
- この仕組みの下では **IPアドレスとドメイン名とを対応させる** 必要があり、この機構を **名前解決** と呼ぶ。
- 名前解決の下では、ユーザはIPアドレスを意識する必要がなくなる。
   - IPアドレスを覚える必要がない。
   - ドメイン名だけを固定しておけば、IPアドレスの変更に伴うユーザへの周知が必要ない。

- 名前解決の1つが、**DNS (Domain Name System)** である。
- DNSの簡単な仕組みは、「 **IPアドレスとドメイン名を対応させたデータベースに対して、クライアントが問い合わせる** 」というもの。

## DNS以外の名前解決

### Hostsファイル

- かつて、ホスト名とIPアドレスとを対応させた一覧表 **Hostsファイル** で名前解決を行っていた。
- 以下の図のような流れで名前解決を行う。

![hosts_file.png](https://qiita-image-store.s3.amazonaws.com/0/288168/1fd5ec3b-6a24-6217-6eaa-aa5a6e5c1535.png)


### Hostsファイルによる名前解決の問題点

- ネットワークに存在する全てのホストが最新のHostsファイルを持っている状態を担保するのが難しい。
- ホストの台数が増加してHostsファイルが肥大化し、トラフィックが増大してしまう。

## DNSによる名前解決

- DNS下では...
   - 名前情報は、ネームサーバで一括管理される。
   - クライアントは通信の都度、ネームサーバに問い合わせる。
- 組織内でホストの情報を管理できる。ホスト名やIPアドレスの登録・変更をしても、組織内の処理で完結する。

### ドメイン名前空間

- DNSの下では、 **ホスト名** （ネットワーク上で名前を持つ機器の機器名）と **ドメイン名** （ホストを管理する組織の名前）はツリー構造で管理される。
   - rootは **rootドメイン**
   - nodeはドメイン名
   - leaf（終端node）はホスト名
- ツリー構造により、rootから辿っていけば、全ホストを探しだすことが可能となる。
- DNSのツリーを **ドメイン名前空間（Domain Name Space）** という。
- ドメイン名前空間にドメイン名が登録されてはじめて、そのドメインはDNSの対象となる。
- あるドメイン配下のノードは同階層で同じ名前を持つことができない。
- つまり、ドメイン名前空間は同じ階層でドメイン名が重複しないように管理される必要がある。

### ドメインの管理

- インターネット上のドメイン名は、 **ICANN (Internet Corporation for Assigned Names and Numbers)** により管理されている。
- ICANNは **レジストリ（registry）** にrootドメイン直下のドメインの管理を移譲している。
- 日本のレジストリは **JPRS (Japan Registry Service)** といい、以下の情報を管理している。
   - `jp`ドメイン
   - jpドメイン下のネームサーバの情報
-  実際に組織がドメイン名を取得する際は、 **レジストラ（registrar）** に登録を依頼する。

![registry_registrar.png](https://qiita-image-store.s3.amazonaws.com/0/288168/19ff3eda-b4c3-458b-39f4-3b90de3f24bb.png)

### TLDとSLD

- レジストリが管理するドメインを **トップレベルドメイン（Top Level Domain, TLD）** といい、TLDには以下の種類がある。
   - **Country Code TLD, ccTLD** （その国内の組織のみ使える2文字のTLD。米国は例外）
   - **Generic Code TLD, gTLD** （所属する国に関係なく使える3文字以上のTLD）
   - **米国のみ、組織の形態を意味す3文字以上のTLDを使うことができる**
- TLD直下のドメインを **セカンドレベルドメイン（Second Level Domain, SLD）** といい、**組織の属性を表す**。
- JPRSが管理するドメインには、**SLDがつくものとつかないものがある**。

#### 汎用JPドメイン

- 日本の個人・企業なら制限なしに取得可能なドメイン。
- SLDなし（e.g. `hoge.jp`）。

#### 属性型JPドメイン

- SLDとして組織の属性がつくドメイン（e.g. `huniv.ac.jp`）。
- 属性に合った組織でなければ取得できない。
- 1組織につき、1ドメインまで。

![domain.png](https://qiita-image-store.s3.amazonaws.com/0/288168/f0527a48-6947-658d-0291-e610a39066c1.png)

### FQDN

- 同じドメイン直下にいるホストは、ホスト名だけで宛先の指定が可能な場合がある。
- rootドメインから全てのドメイン名を記述するドメインの表記を **Fully Qualified Domain Name, FQDN** という。

## つづく

[DNSの勉強ノート【その2】A/CNAME/NS/MXレコード](https://qiita.com/RyomaTaniyama/items/6d8748e8096ea4f18b5b)

## 参考文献

- 網野衛二 (2009) 『3分間DNS基礎講座』 技術評論社
- 竹下隆史・村山公保・荒井透・苅田幸雄 (2012) 『マスタリングTCP/IP 入門編』 オーム社
5分でオンラインストレージを作る【ownCloud】

#やりたい事
急いで **安全に** 大き目のファイルを送受信したい。
この作業は、送受信各一回しか行わない。

#検討してみる
メール添付→メールサーバの制限に引っかかる
SaaS型オンラインストレージを使う→無償版は怖い。有償版一回しか使わないので勿体無い
S3バケットをIP制限した上で公開してダウンロードさせる→送信先担当者がアップロードができない
S3のPut権限を付けたIAMユーザを作成渡す→送信先担当者のリテラシーが足りない
👇
オンラインストレージ作ればいいじゃん。という結論に至る

#必要スキル
- AWS EC2インスタンスを作成する事ができる
- Linuxがなんとなくわかる

#作りかた
BitnamiのownCloudを使います

##マニュアルなど参考情報はこちら
●Bitnami共通のAWS説明 
　　　　https://docs.bitnami.com/aws/get-started-console/
　　　　AWSを使う上で当たり前の感じの事が書かれている感じですが念のため。。

●BitnamiのownCloudイメージサイト 
　　　　https://bitnami.com/stack/owncloud
　　　　AWS以外のプラットフォームについても書かれている感じです。

●BitnamiのownCloudをAWS上で使う際の必要情報
　　　　ドキュメント　　　　👉 https://docs.bitnami.com/aws/apps/owncloud/
　　　　利用可能なAMI　　　　👉 https://bitnami.com/stack/owncloud/cloud/aws/amis

##インスタンスの作成
上記、「利用可能なAMI」から、東京リージョンのHVMのリンクを選びます

|![スクリーンショット 2018-09-08 10.29.02.png](https://qiita-image-store.s3.amazonaws.com/0/185989/7229a7b4-3023-4397-5a59-5e4e689a515a.png)|
|:-:|

EC2インスタンス作成のパラメータ設定をすると、インスタンスが起動します。
ちなみに、必要スペックですが、t2.micro で十分です
インスタンス作成は終わりです。勝手にWebサービスとか起動されますので待ちます。

##ブラウザでhttpで表示してみる
と・・・
![own01.png](https://qiita-image-store.s3.amazonaws.com/0/185989/7f6f17e6-b396-ac9e-dc74-4184c8276410.png)
とりあえずWebサービスが起動しているが、アプリケーション側で制限しているっていうメッセージが出てます

**config/config.php** ファイルの　**trusted_domains** 項目に、このサイトがアクセスされるときのURLを書く
と言っていますので
マニュアルだと[このあたり](https://docs.bitnami.com/aws/apps/owncloud/#how-to-modify-the-owncloud-trusted-domains)ですね。。

##コンフィグファイル修正
SSHで入るます
ログインのIDは、ec2-user ではなく bitnami です。

```terminal
sudo vi /opt/bitnami/apps/owncloud/htdocs/config/config.php
```
からの

```php:config.php
'trusted_domains' =>
array (
    0 => "FIRST_DOMAIN",
    1 => "SECOND_DOMAIN",
    2 => "THIRD_DOMAIN",
),
```

0 => "FIRST_DOMAIN",
の **FIRST_DOMAIN** に、このサイトのドメイン名を書きます。
例えば、プライベートIPが192.168.1.1で、パブリックIPが50.50.50.50で、DNSでhoge.hoge.comを割り当ているなら

```php:config.php
'trusted_domains' =>
array (
    0 => "192.168.1.1",
    1 => "50.50.50.50",
    2 => "hoge.hoge.com",
),
```

で
再度ブラウザで見ると、リダイレクトされてログインページが表示される
![own02.png](https://qiita-image-store.s3.amazonaws.com/0/185989/a0dbbee1-9b66-3afd-5cbb-ae4faf89e814.png)

##ログインする
初期パスワードは、AWS管理コンソールで確認できます
このインスタンスのシステムログを見ると・・・
![own03.png](https://qiita-image-store.s3.amazonaws.com/0/185989/844cef26-f777-1907-dbef-861a6aaabe9a.png)
これです。

ログインできたら、あとはブラウザ内で色々いじってみたら良いです。


#まとめ
セキュリティは一切考慮していませんが、セキュリティグループでIP制限して、ユーザアカウントの管理に気を付けておけば
十分 **安全** じゃないでしょうか。。
業務利用が終わったら、アクセスログを取得して、とっととインスタンス削除してしまえば良いです。
python3 ウエブスクレイピングことはじめ

流行りのウエブスクレイピングを試してみた。
対象はこういうの大丈夫そうなスラド。

定番のBeautifulsoup。
初めてやってみたけど簡単だな！

アタマの3つを拾ってURLをHTMLに吐き出してみた。
嫁が帰ってくるまでの30分、勢いで書いたのでコードが美しくないのはすみません。

```test.py
'''URLを扱うモジュール'''
import urllib.request
from bs4 import BeautifulSoup
import webbrowser
import os

'''スクレイピング機能クラス'''
class Scraper:

	def __init__(self, site):
		self.site = site

	'''BeatifulsoupでURLスクレイプ'''
	def scrape(self):
		geturl = []
		r = urllib.request.urlopen(self.site)
		html = r.read()
		parser = "html.parser"
		sp = BeautifulSoup(html, parser)
		for tag in sp.find_all("a"):
			url = tag.get("href")
			if url is None:
				continue
			if "html" in url:
				geturl.append(url)

		return geturl 

	'''アタマ3つのURLをhtmlに書き出す'''
	def create_html(self, _url):
		with open("test.html", "w", encoding="utf-8") as f:
			f.write("<html>" + "\n")
			f.write("<head>" + "\n")
			f.write("<meta charset=\"utf-8\">" + "\n")
			f.write("<title>super head line!!</title>" + "\n")
			f.write("</head>" + "\n")
			f.write("<h2>This page is \"{}\" headline</h><p>".format(self.site) + "\n")
			for i, new in enumerate(_url):
				l = "<h5><a href=" + "\"" + _url[i] + "\"" + " target=\"_blank\">URL:{}</a>".format(_url[i])
				l += "<br>"+ "\n"
				f.write(l);
				if i == 3:
					break
			f.write("</html>" + "\n")
			

'''メイン処理'''
news = "https://srad.jp/"
url = []
url = Scraper(news).scrape()
Scraper(news).create_html(url)

'''デフォルトブラウザで開く'''
webbrowser.open_new_tab("./test.html")



```
USDZ形式の3DモデルをModel I/Oで読み込みSceneKitで利用する

WWDC18で発表されたARコンテンツの新フォーマット "USDZ" ですが、同WWDCでのセッション「Integrating Apps and Content with AR Quick Look」では`QLPreviewController`やSafariでプレビューするためのHTMLの解説はあれど、ARKit・SceneKitで利用するための実装方法については提示されていませんでした[^1]。

[^1]: "usdz is supported on iOS and macOS, in SceneKit and Model I/O"と、サポートされている旨だけはサラッと述べられたが、これだけ。

しかし、「ARKitアプリケーションの実装をしなくてもAR体験を提供できるフォーマット」という点がUSDZの最もインパクトがある点だとしても、それを含めて「ユニバーサル」[^univ]である点がUSDZという新フォーマットの売りであるはずで、ARKitでの利用方法（＝SceneKitでの利用方法）について明示されないのは片手落ち感を感じてしまいました。「ブラウザやプレビューでAR体験を提供するための『専用』フォーマット」**ではない**はずで。

[^univ]: USDZのベースとなるフォーマットUSDは"Universal Scene Description"の略です。

おそらく、USDZはSceneKitでの利用だけ見るとUSDと同様で、**USD自体はModel I/Oでの読み込みがiOS 10で既にサポートされていた**ので、そこは自明（新しいフィーチャーではない）として解説しなかったのでしょう。

とはいえ私のように「で、USDZってARKit（SceneKit）ではどう利用するの」とググった方（これからググる方）は多いと思われるので、ここに実装を示しておきます。

## 実装

### `.usdz`ファイルから`MDLAsset`を初期化する

読み込みにはModel I/Oフレームワークを利用します。アプリケーションバンドル内の`.usdz`ファイルのURLを`MDLAsset`のイニシャライザに渡して初期化するだけです。

```swift
guard let url = Bundle.main.url(forResource: name, withExtension: "usdz") else { fatalError() }
let mdlAsset = MDLAsset(url: url)
```

ちなみに、`MDLAsset`がサポートしている（ロード可能な）ファイル形式は、`MDLAsset`の`canImportFileExtension(_:)`から調べることができます。[同メソッドのリファレンス](https://developer.apple.com/documentation/modelio/mdlasset/1391813-canimportfileextension)にも、サポートしているファイル形式が載っています。[^3]

- Alembic
  - `.abc`
- Universal Scene Description
  - `.usd`, `.usda`, `.usdc`
- Universal Scene Description (Mobile)
  - `.usdz`
- Polygon
  - `.ply`
- Wavefront Object
  - `.obj`
- Standard Tessellation Language
  - `.stl`

[^3]: Twitterで[Gemmbu](https://twitter.com/Gemmbu)さんに教えていただきました。

### `MDLAsset`から`SCNScene`を初期化する

SCNSceneのリファレンスを見ると、次のようなイニシャライザがあります。

```swift
convenience init(mdlAsset: MDLAsset)
```

しかし、このイニシャライザは、`import ARKit`や`import SceneKit`、`import ModelIO`していても**使えません**。次のように`SceneKit.ModelIO`をインポートする必要があります。

```swift
import SceneKit.ModelIO
```

先ほど作成した`MDLAsset`オブジェクトをイニシャライザに渡し、`SCNScene`を初期化します。

```swift
let scene = SCNScene(mdlAsset: mdlAsset)
```

あとは通常通り（`.scn`ファイル等から`SCNScene`を初期化した場合と同様）のSceneKitの実装になります。


## サンプルコード

「ARKit-Sampler」に[Appleの公式配布usdzファイル](https://developer.apple.com/arkit/gallery/)をARKitで使うサンプルを追加しました。

- https://github.com/shu223/ARKit-Sampler

<img src="https://qiita-image-store.s3.amazonaws.com/0/3180/6589f232-1866-3320-277f-237b370f1740.jpeg" height="600">

（本サンプルはiOS 11で動作させています）
Unity　ボタンを常時最前面に表示する方法

UnityでVideoPlayerを使っています。

タイトル画面表示に、VideoPlayerを利用して動画再生します。
再生終了後、Menuなどのボタン類を前面に表示させるにはどのようにしたらできますでしょうか？
よろしくお願い致します。　設定でできないか見ているのですが、なかなか見つけられません。
DynamoDBの全データ削除について

# 書くこと
DynamoDBは仕様上、全てのデータを削除するAPIが提供されていません。
そのため全てのデータを削除したい場合


- [データを個々に削除する。](https://dev.classmethod.jp/cloud/aws/dynamodb-delete-item-all/)
- テーブルを削除し、再作成する。
- [TTL属性を使用して、DynamoDBに削除をお願いする。](https://aws.amazon.com/jp/blogs/news/new-manage-dynamodb-items-using-time-to-live-ttl/)


要件に応じて、この中から選択する形になると思います。
このうち今回は、**テーブルを削除し、再作成する**について記載したいと思います。
Node.jsで書かれたものが見つからなかったので、実装してみました。


# 実装
動作環境：　Lambda（Node.js 8.10）
git: [URL](https://github.com/HagaSpa/sandbox/blob/master/deleteAllDynamoData/index.js)

```refleshDynamoDB.js
const AWS = require('aws-sdk');
const Dynamo = new AWS.DynamoDB();

exports.handler = async (event) => {
    const params = {
        TableName: "Music"
    };

    try {
        // テーブル情報を取得する
        const tableInfo = await getTableInfo(params);

        // delete実行
        await deleteTable(params);

        // deleteが完了したのを確認する
        await waitForDeleted(params);

        // 取得したテーブル情報を用いて、テーブル作成用パラメータを生成
        const createParams = {
            AttributeDefinitions: tableInfo.Table.AttributeDefinitions,
            KeySchema: tableInfo.Table.KeySchema,
            ProvisionedThroughput: {
                ReadCapacityUnits: tableInfo.Table.ProvisionedThroughput.ReadCapacityUnits,
                WriteCapacityUnits: tableInfo.Table.ProvisionedThroughput.WriteCapacityUnits
            },
            TableName: tableInfo.Table.TableName
        };

        // create実行
        await createTable(createParams);

        const response = {
            statusCode: 200,
        };

        return response;
    } catch (err) {
        const response = {
            statusCode: 500,
            err: err
        }
        
        return response;
    }
};

/**
 * DynamoDBの情報を取得する
 * @param {*} params 
 */
const getTableInfo = (params) => {
    return Dynamo.describeTable(params, (err, data) => {
        if (err) err;
        else data;
    }).promise();
};

/**
 * DynamoDBを削除する
 * @param {*} params 
 */
const deleteTable = (params) => {
    return Dynamo.deleteTable(params, (err, data) => {
        if (err) err;
        else data;
    }).promise();
};

/**
 * テーブルの削除が完了されるまで待つ
 * @param {*} params 
 */
const waitForDeleted = (params) => {
    return Dynamo.waitFor('tableNotExists', params, (err, data) => {
        if (err) err;
        else data;
    }).promise();
}

/**
 * DynamoDBを作成する
 * @param {*} params 
 */
const createTable = (params) => {
    return Dynamo.createTable(params, (err, data) => {
        if (err) err;
        else data;
    }).promise();
};

```

# 説明
このコードでは`Music`テーブルの削除→作成を行います。
再作成されたDynamoDBは`Music`と同じハッシュキー、スキーマ、キャパシティを持ちます。

処理内容としては下記になります。
1.テーブルの情報を取得
2.テーブル削除
3.1で取得したテーブル情報を使ってテーブル作成

またGSIも情報として取得できるので、`createParams`の生成時にプロパティにセットしてあげれば、GSIも同様のものを作成することができるはずです。

ただし再作成されたテーブルは`arn`が違うので、参照している他リソースを修正する必要があります。

# 結論
データを個々に削除する場合、`scan`をする必要があります。
`scan`は設定されたキャパシティーに依存するため、削除するデータ量によってはキャパシティーユニットの設定を上げる必要が出てきます。（＝つまりコストが増える）

それに比べてテーブルを再作成する場合、コストは増えませんが完全に同じ設定のテーブルにはなりません。
また本番環境などでは、リスクが伴います。

その辺考えると、個人的にはTTLによる削除がいいのかなぁと思います。
ただこれも設定した時間丁度に削除はしてくれないので、要件との兼ね合いも考える必要があります。
（自分の場合、10分ほど遅れて削除されました）

それぞれの特徴を考えて、選択していきたいと思います。
Rails 絞り込み検索のよりスマートな書き方

#絞り込み検索の選択肢がべた書きでダサい件について。

例）
　・モデルabc
　・カラム :name, :year, :title
　・一つのデータごとに:yearには2015~2018年のいずれかが入っている。
　　→絞り込み検索で各年のデータを取得・表示したい。

こんな感じで書くことで一応問題なく絞り込めています。

```:abcs_controller.rb
  def index
      @abcs = Abc.all
  end

  def search
      @abcs = Abc.where('year LIKE ?', "%#{params[:year]}%")
      render :index
  end

　※以下params(省略)
```

```:index.html.erb
<%= form_tag(abc_search_path, method: "get") do %>
  <%= select_tag(:year, options_for_select([["2015","2015"],["2016","2016"],["2017","2017"],["2018","2018"]])) %>
  <%= submit_tag "絞り込み" %>
<% end %>

<% @abcs.each do |f| %>
  <p><%= f.name %></p>
  <p><%= f.year %></p>
  <p><%= f.title %></p>
<% end %>
```

ご覧の通り、options_for_selectで["2015","2015"]などとして絞っています。
前の"2015"は選択肢として表示される文字で、後ろの"2015"はvalueとして送られる値（だと思ってます...）。
つまり、選択肢で2015、2016、2017などと表示し、2015を選んでsubmitすれば"2015"が、2016を選んでsubmitすれば"2016"がvalueとしてabc_search_pathで送られ、コントローラーのsearchアクションで絞り込んだyearカラムからvalueが一致したものを表示している(???)。
　　
と、まぁ解釈が間違っていたとしても、これで実際に問題なく動いています。
　　※解釈が間違っていたらご指摘いただけると助かります。'cause 初心者

本題はここからです。
上で見た記述のこの部分、

```:index.html.erb

  <%= select_tag(:year, options_for_select([["2015","2015"],["2016","2016"],["2017","2017"],["2018","2018"]])) %>
  
```
選択肢が["2015","2015"],["2016","2016"]...　と、べた書きになってしまっています。選択肢が少なければいいのかもしれませんが、これが["2019","2019"],["2020","2020"]...　と続いていくと、htmlがおデブになります。

何かいい方法はないでしょうか。

ちなみに、当初は選択肢をカラムからそのまま引っ張ってくる書き方をしたのですが、(当然...)選択肢が2017,2018,2017,2015,2018...のようにデータid順にすべて出てしまうわ被りもあるわで、上記に変更した次第です。


---

sashim1343さんからいただいたコメントを試し、controllerとviewを以下に書き変えてみたところ、見事選択肢をカラムからそのまま引っ張ってきて、ソートされ、かつ被りなしのプルダウンメニューを作れました。
sashim1343さん、ありがとうございます!!!!!!!!!!!

```:abcs_controller.rb
  def index
      @abcs = Abc.all
      @year = Abc.group(:year).pluck(:year).sort　#ここを追加！
  end

  def search
      @abcs = Abc.where('year LIKE ?', "%#{params[:year]}%")
      @year = Abc.group(:year).pluck(:year).sort　#ここを追加！
      render :index
  end

　※以下params(省略)
```

```:index.html.erb
<%= form_tag(abc_search_path, method: "get") do %>
<%= select_tag(:year, @year) %>　#ここを書き換え！
<%= submit_tag "絞り込み" %>
<% end %>

<% @abcs.each do |f| %>
  <p><%= f.name %></p>
  <p><%= f.year %></p>
  <p><%= f.title %></p>
<% end %>
```
備忘録　Javascript classについての疑問




## Javascriptのclassの実装について疑問があったので、コードを書いて検証した。

### 疑問点

1. 属性と同名のgetterが書けるのか？
1. 引数付きのgetterは書けるのか？
1. 引数ありと引数なしの同名のmethodを書けるのか？

```Javascript
class Test {
  constructor(val) {
    this.attr1 = val; //---(1)
  }
  get attr1() {
    return this.attr1;
  }
  get attr2(val) {  //---(2)
    return Number(val) * this.attr1;
  }
  func1() {
    return this.attr1;
  }
  func1(val) {   //---(3)
    return this.attr1 / Number(val);
  }
}
```

## 結果は、
1. 属性と同名のgetterが書けるのか？　**→書けない**
<br>(1)のところでエラーとなる。<br>
`TypeError: Attempted to assign to readonly property.`
<br>なるほど、そう解釈しているんだ！

1. 引数付きのgetterは書けるのか？　**→書けない**
<br>(2)のところでエラーとなる。<br>
`[Error] SyntaxError: Unexpected identifier 'val'. getter functions must have no parameters.`
<br>書けると便利な場面があるんだけどな！

1. 引数ありと引数なしの同名のmethodを書けるのか？　**→書けるけど動きが違う**
<br>書くには書けるが期待した動作にならず。引数あり／なしのどちらで呼び出しても、(3)のメソッドが呼ばれる。つまり後勝ちってことだろう。

## まとめ
上記はどれも、Javascriptには「型」の概念がない（まったく無い訳ではないが、ほぼほぼ無いに等しい）ことに起因していると考えると、どの結果も「なるほど、そっかー」の結果であった。実行時エラーとなってくれたらよいが、しれっと動くとバグに気付かず悩むことに・・・。<br>
誤って同名のメソッドを定義してしまい、期待通りに動かずに悩んだ経験がある。同名関数は気を付けないと・・・。ドキュメントを書かずに直接コードを書いている時点でダメかも。
さくら VPS 場所 確認方法 のメモ

VPSのコントロールパネル（サーバー設定画面）に書いてありました

<img width="1352" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/44791/620bebfd-e00b-bf44-6f56-83d712f498fa.png">
vagrant の基本

vagrantは、Macosや、windowsosのようなosを切り替える際に有効となる。

新たにcentosなどのOSもvagrant上で管理することができる。


## vagrant コマンド

- vagrant box list =>vagrant 上で管理しているboxを確認することができる。
- vagrant box add [box名] =>新たにboxを追加する
- vagrant init =>boxを初期化する。Vagrantfileを作る。新たにboxを作った際の初めにすべきこと。
- vagrant up =>virtual machine を起動する。
- vagrant ssh => 接続する。
- vagrant status => vagrantが動いているかなどを確認できる。
- vagrant halt => vagrant を停止する。

##参考
- https://qiita.com/pugiemonn/items/bcd95a35c3ec7624cd61
Vue.js と Microsoft Flow を使って Strikingly のコンテンツ管理を楽にする

こんにちは、ここのところ Strikingly 推しの僕です。

ウェブ作成からホスティングまでを簡単に行えるサービスはウェブ制作においてコーディングから開放してくれるのでコンテンツづくりに集中できます。

最近ではデザインもかなり洗練されてきているので、使いやすくなりました。

ところが、例えばイベント日程などの動的な情報でも手動で管理するのが基本なので更新忘れや内容の間違いといったことが発生しやすいのが悩みの種です。

そこで、カスタム HTML に Vue.js を導入し、手動での管理を不要にしようと思い立ったのがこの記事を書く動機です。

## 構成
- Google Calendar
- Microsoft Flow
- Vue.js
- Strikingly (Pro プラン)

Microsoft Flow は Google Calendar のデータを JSON 化して公開する API の役割として使っています。

こちらのやり方は先日書いた記事が役に立つかと思います。

[Microsoft Flow を使って Spreadsheet で管理しているデータを JSON にして提供する \- Qiita](https://qiita.com/shingorow/items/72060f9e832ebd138358)

Vue.js に関する部分は割愛。いい記事いっぱいあります。

## ハマりポイント

### DOMContentLoaded イベントで DOM を取れない

Strikingly でカスタムコードを使う際、思わぬ挙動でびっくりしました。

ページ内に挿入するカスタムコードのブロック内にある DOM が、DOM 読み込み直後だと取得できないんですね。。。

```js
const init = () => {
  // カスタム HTML の DOM を取得する処理
}

window.addEventListener('DOMContentLoaded', init);
```

これが動きません。

カスタム HTML 以外の DOM は取れるのでカスタムコードはレンダリングのタイミングが違うんでしょうか。

結局、カスタム HTML の中に HTML も JavaScript も記述するという方法で解決しました。

## Vue.js を書けるのにわざわざ Strikingly を使う意味

Vue 書けるなら Strikingly 使わずスクラッチで作ればいいのではっていう意見が聞こえてきそうですが、SEO 関連の記述とか色の管理みたいなものを GUI でできるし、HTML のコンテンツではない部分のコーディングを省けるので Strikingly を使う意味は十分あると思います。

とにかく少しでもラクしたいんです、はい。

---

出来上がったページを掲載しておきますので、反応速度とか気になる方は見てみてください。

何かのタイミングで閉じるかもしれませんが、その際はご了承ください。

https://neco.engrowth.work/
3日ほどherokuのデプロイに失敗し続けた話

##毎回ユーザー名とパスワードを聞かれる
前回はこちら。[UbuntuでHerokuを使おうと思ったらエラーになった](https://qiita.com/jeq/items/b2604ac74463d004a38f)
herokuにログインして、その後。

```
$ git push heroku master
```

```
remote: !       WARNING:
remote: !       Do not authenticate with username and password using git.
remote: !       Run `heroku login` to update your credentials, then retry the git command.
remote: !       See documentation for details: https://devcenter.heroku.com/articles/git#http-git-authentication
```
何度この文章を見たことか。

様々な記事で紹介されているように、ここでは
・ユーザー名：空のまま
・パスワード：herokuのAPIキー
を入力するとのこと。
参考：[Herokuにアプリをpushしたときにエラーが出る場合の対処法](https://web.plus-idea.net/2017/04/heroku-app-pushauth-error/)

しかし、何度やってもダメ。
丁寧に一文字ずつ入力してみたり、コピペしてみたり、試行錯誤をするのだが、毎回このエラー。

ひょっとしてubuntuの画面にはパスワードを入力している感触がないため、
ひょっとして入力されてないのでは…？と疑心暗鬼になってきてしまっていた。

##解決：ユーザー名に何かいれてみよう
そんなこんなで早三日。
LINEbotを作りたいだけなのに…。
と思って嘆いていたそんな時、
ふと「ユーザー名入れてみるか」
と思い立ち、適当に入力。

すると…！

```
Counting objects: 9, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (9/9), 2.11 KiB | 432.00 KiB/s, done.
Total 9 (delta 1), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Python app detected
(省略)
remote: Verifying deploy... done.
To https://git.heroku.com/[アプリ名].git
 * [new branch]      master -> master
```
おおおおお！！

出来ました。

##考察
ユーザー名を入力しないと、
パスワード入力を受け付けない？
UIRefreshControlの使い方メモ

UITableViewControllerでUIRefreshControlを実装する想定。
なんか罠が多かったのでメモしておく。
swift4。

```swift
override func viewDidLoad() {
    let refreshControl = UIRefreshControl()
    refreshControl.addTarget(self, action: #selector(self.refreshControlValueChanged(sender:)), for: .valueChanged)for: .valueChanged)
    self.refreshControl = refreshControl

    // ここにこうやって書くとViewController生成時にロードもやってくれる
    self.refreshControl?.beginRefreshing()
    self.refreshControl?.sendActions(for: .valueChanged)
}

@objc func refreshControlValueChanged(sender: UIRefreshControl) {
    // ~ 更新処理ここに書く ~
    sender.endRefreshing()
}
```