OmniAICreator/Qiita-1.07M huggingface dataset:
zsh + tmuxで効率的なシェル環境を構築する

#はじめに
今更ながらzshとtmuxを使ってみたら劇的に作業効率が高まって感激しているのでメモ。screenは使いにくさしか感じなかったがtmuxは非常に快適です。
各々の機能に関する詳細については文中リンクで詳しく記されているのでここでは書かず、設定内容に特化して有用なリンクをまとめます。

#完成品（主にtmuxの紹介）
![スクリーンショット 2018-06-13 23.10.43.png](https://qiita-image-store.s3.amazonaws.com/0/208561/57a8eef5-f9de-3633-9aa7-10f9bacbc653.png)

#zsh
[こちらのQiitaの記事](https://qiita.com/iwaseasahi/items/a2b00b65ebd06785b443)がよくまとまっていて、手順に従うだけで簡単に初期設定できました。
これ以外では、`.zshrc`ファイルへ2点変更を加えました。

- 言語設定を英語にするため`export LANG=en_US.UTF-8`のコメントアウトを消す
- エイリアスを記載した`.zprofile`を読み込むため、`source ~/.zprofile`を追記

次に[こちら](http://www.sirochro.com/note/terminal-zsh-prompt-customize/)を参照し、プロンプトを自分の好みのもの（下記参照）に変更しました。
```PROMPT='
[%{$fg[green]%}%n@%m%{$reset_color%}:%{$fg[yellow]%}%~%{$reset_color%} %*] ${vcs_info_msg_0_}
$ '```
プロンプトの記法がbashとは異なる点に注意が必要です。
また上記リンクでgitの情報を表示する設定も紹介されていて、大変便利です。

さらにzshのタブ補完時に表示される候補の文字色の設定を、普段自分が使っているlsの色と一致させるため、[こちら](https://qiita.com/yuyuchu3333/items/84fa4e051c3325098be3)の設定を参照しました。
これでとても快適なシェル環境ができました！

#tmux
まず`brew install tmux`でインストール（macOSの場合）。
.tmux.confについては[こちら](https://qiita.com/succi0303/items/cb396704493476373edf)の設定をそのままコピーした上で、以下の点を修正

- Prefixキーについて、Macではctrl-aがカーソルを行頭へ移動させるコマンドなので、他との競合がなさそうなctrl-tへ変更。
    - `set -g prefix C-t`
- ステータスバーの色の変更（好みです）
    - `set -g status-bg "#000080"`
    - `setw -g window-status-fg yellow`
    - `setw -g window-status-current-fg black`
    - `setw -g window-status-current-bg colour226`
- ペインボーダーについては後述の設定を反映させるためコメントアウト
    - `#set -g pane-border-fg green`
    - `#set -g pane-border-bg black`
- アクティヴなペインはシアンに（やはりただの好み）
    - `set -g pane-active-border-bg cyan`
- Prefixキーが押されているかどうかを表示するため、[こちら](https://qiita.com/dtan4/items/363e92525e7c5a16f3fc)を参照
    - `set -g status-left "#[fg=#ff00ff, bg=#000080]#{?client_prefix,#[reverse],}#h #[fg=green]Session: #S #[fg=yellow]#I #[fg=cyan]#P"`
- リフレッシュ感覚を1秒に
    - `set -g status-interval 1`

そしてtmuxのステータスバーに負荷･電源･音量･SSIDに関するMacの情報を表示するため、[こちら](https://qiita.com/arks22/items/a792d9d43d913c373520)を参照。
個人的にはこの設定に一番感動した。
最後に同じ著者による投稿から、ペインのステータスラインにgitブランチを表示するよう設定。[こちら](https://qiita.com/arks22/items/db8eb6a14223ce29219a)を参照。やはりこの設定も素晴らしい。

#おわりに
先人たちの知恵に感謝です。そしてQiitaにも感謝ですね。僕がやっているのはただのキュレーターです。
あとはそろそろdotfilesのGit管理もしなければと思いつつまだ実行できていない今日この頃。

#記事で挙げた参考リンク
zsh
https://qiita.com/iwaseasahi/items/a2b00b65ebd06785b443
http://www.sirochro.com/note/terminal-zsh-prompt-customize/
https://qiita.com/yuyuchu3333/items/84fa4e051c3325098be3

tmux
https://qiita.com/succi0303/items/cb396704493476373edf
https://qiita.com/dtan4/items/363e92525e7c5a16f3fc
https://qiita.com/arks22/items/a792d9d43d913c373520
https://qiita.com/arks22/items/db8eb6a14223ce29219a
ChefからInSpecにattributeをJSON経由で渡したら、シンボルが文字列になっていた

#問題
ChefレシピからattibuteをJSONでテストに渡していたら、symbolを想定していた変数がstringとして設定されていた。

考えてみれば当たり前だが、JSONの書式にはsymbolに相当するものが無い。
JSON.pretty_generateなどでJSONに変換した時点でstringに置き換えられていた。

```ruby:recipes/default.rb

node.default['service']['foo']['action'] = [:start, :enable]

...

require 'json'
IO.write('/tmp/node.json', JSON.pretty_generate(node.to_hash))

```



#対応1: 文字列の前提でテストを作る
シンプルに比較対象をシンボルから文字列にする。。。
まあchefのattributeでsymbolが必要なのはactionとnotifies, subscribes くらいの様な気がするので、主にそこだけ気をつければ良いのだが。。。。


```ruby

hash['service'].each do |s_name, s_attr|
  describe service(s_name) do
    it { should be_enabled }     if s_attr['action'].include?('enable')
    it { should_not be_enabled } if s_attr['action'].include?('disable')
    it { should be_running }     if s_attr['action'].include?('start')
    it { should_not be_running } if s_attr['action'].include?('stop')
  end
end
```

#対応2: symbolのまま渡す方法は無いか。。

レシピ側で、.inspectメソッドでハッシュを文字列として書き出し、

```ruby:recipes/default.rb

...

hash = node.to_hash
hash['run_list'] = node['run_list'] # ここだけ読み込み時のエラー回避の為に置き換え
IO.write('/tmp/node.hash', hash.inspect)
```

テストシナリオではevalで読み込ませれば、うまく行きそうに思えた。。。。が、

```ruby:test/integration/default/default_test.rb
node = {}
eval('node = ' + `cat /tmp/node.hash`)

...

```

##残念
試してみると、Chefはリモート、InSpecはローカルで実行されていて、InSpecのテストから直接はリモートのファイルを参照できなかった。


~~shell veriferにして $KITCHEN_USERNAME などを使うか、テストスクリプト中で ssh などを行えばできるのだろうが、、、
その様なことを考えなくて良いjson( ).params によるjson渡しが楽すぎて、シンボルをそのまま渡すことはとりあえず断念。~~



##追記：kitchen exec を用いることで1ノードなら対応できた

```ruby:test/integration/default/default_test.rb
node = {}
eval('node = ' + ` kitchen exec --command='cat /tmp/node.hash' | tail +2 `)

...

```
kitchenのインスタンス名は渡せていないので、対象が1システムの場合のみ。
やはりshell veriferで素直にローカルにscpかな。。



#実はjson( ).paramsはすごかった

InSpecのテストで、jsonからパラメーターを読み込むのに、何気に使っていたjson( ).paramsは、テスト実行ノードがたとえリモートでも、そこのファイルを読み込んでくれる native inspec resource の様子。

```ruby:test/integration/default/default_test.rb
node = json('/tmp/node.json').params

...

```
require 'json' も不要


#対応3: レシピでノードオブジェクトのvalueとしてsymbol(もしくはsymbolのarray)は使わない様に統一

レシピでactionに渡す値を最初から.to_symや.mapを使って加工すれば良いのでしょうが、。。。本末転倒な感じ。

追記：
そもそもChefだけの場合でもJSONでattributeを渡さなければいけないケースがありうることから、結局はこの対応が必要なのか。
[Chefでリソースのactionへの引数を、String(もしくはそのArray)から変換する](https://qiita.com/hiroyuki_onodera/items/48a180345ed0023bc308)


#参照
- [Read Chef attributes within the tests ? #541](https://github.com/inspec/inspec/issues/541)
- [Chefでユーザーによるdeep_mergeを必要としないnodeオブジェクトのjson書き出し](https://qiita.com/hiroyuki_onodera/items/75f6ea446d47f1c57e3e)
v-bind:srcでハマった

nuxtで開発していてハマったので記録を残しておきます。
やりたかったことはオブジェクトの中身を全てrequireして画像を表示したいというものです。

結局問題だったのはWebpackのところで、静的パスを指定する必要がありました。
っていう内容です。

```javascript
const store = () => new Vuex.Store({

  state: {
    data: {}
  },
  mutations: {
    getDocuments(state) {
      // 画像を取得する
    }
  },
  getters: {
    getImgPath: state => {
      return require(state.data.img) // ここでエラー
    }
  },
  actions: {}
})
```

静的に指定しなければならないので以下のように修正したところエラーを解消することができました。

```javascript
const store = () => new Vuex.Store({

  state: {
    data: {}
  },
  mutations: {
    getDocuments(state) {
      // 画像を取得する
    }
  },
  getters: {
    getImgPath: state => {
      // data.imgは画像ファイル名となるようにする
      return require('~/assets/' + state.data.img + '.jpg')
    }
  },
  actions: {}
})
```

もっとスマートな方法あれば教えて頂きたいです。
Arduino: ダイソーの綿と布で作ったゲーム用コントローラ

## 概要
- 大学のProcessingの授業で、最終課題が何かのライブラリを使ったインタラクティブなプログラムだった。
- ゲームを作ることにして、せっかくだからコントローラも作った。
- 一般的なコントローラとは趣向を変えて、ダイソーの綿と布で柔らかいコントローラを作った。

![softroller.jpg](https://qiita-image-store.s3.amazonaws.com/0/257854/bc35613b-6f05-0da8-65a5-c18255dff756.jpeg)


## 材料
・Arduino Uno
・FSR406(圧力センサ)
・KXR94-2050(3軸加速度センサ)
・ブレッドボード配線タイプの基盤
・ダイソーの手芸用品売り場で買った綿と布


## 実装
- ファミコンのコントローラのような形状をイメージ。
- 基盤を中心にして左右に圧力センサを1つずつはんだ付け。
- 中心部に3軸加速度センサをはんだ付け。

![softroller_sensor.jpg](https://qiita-image-store.s3.amazonaws.com/0/257854/c9f9ba3f-454d-b459-bb76-a34617afdec9.jpeg)

- Arduinoに接続。ArduinoはStandardFirmataでセンサ値をProcessingに送信する。

![sortroller_all.jpg](https://qiita-image-store.s3.amazonaws.com/0/257854/6fbfa368-3600-83e5-d9d1-861b684dd2ad.jpeg)

- コントローラっぽく布を裁断して縫い合わせて、基盤とセンサを入れる。
- 最後に綿をいい感じの触り心地になるまで詰め込む。


## ゲーム
- ヘリコプターを操作して上下左右からくる玉を避けるだけの簡単なゲーム。
- 玉に当たったらゲームオーバー、生存時間がスコアになる。
- 3軸加速度を使ってヘリコプターを操作して玉を避けるので、コントローラを傾けて遊ぶ。
- 圧力センサはスタートボタンの役割などに割り当てた。ぎゅっと押すとスタートする。

![game.png](https://qiita-image-store.s3.amazonaws.com/0/257854/ec8bee84-cca4-1709-b428-60c6ac591ee0.png)


## 良かった点
- 行きたい方向にヘリコプターを操作できた。
- 圧力センサの動作も良好だった。


## 反省点
- 配線が短くてちょっと操作しづらかった。
- ゲームがシンプルすぎて圧力センサを持て余した。
- こっちからも攻撃できるようなゲームにしたら良かったかも。
mapStateToPropsのownPropsとは　個人メモ

以下のような発言と出会った。

>Second argument of mapStateToProps is your component's props. So when you connect(mapStateToProps)

```js
function mapStateToProps (state, ownProps) {
  console.log(ownProps)
  return {
    value: state.somestate.someobject[ownProps.variable]
  }
}
```

つまり、ownPropsとは現在のpropsを表すらしい。
console.log(ownProps)とすると、現在のpropsが表示された。
素晴らしい。
blkidから/etc/fstabへUUIDを書き込むときにコピペが面倒なので変換するスクリプト

# はじめに
こんにちは。
サーバでディスクを追加した時などにblkidから`/etc/fstab`へUUIDを書き込むときにコピペが面倒なので変換するスクリプトを書きました。

https://github.com/yousan/uuid2fstab

後ろの`bash`に「抜き出したいドライブレター」と「マウントポイント」を書くとそれっぽく吐き出します。

```bash
$ curl -sL https://goo.gl/KioV7L | bash -s /xvdb /mnt/hoge
UUID=123455-ba64-4142-93fb-8f278e7a2b0b	/mnt/hoge	xfs	defaults	0	0
```

`tee`や`sudo sh -c`などで`/etc/fstab`に書き出すと良いです。

```bash
$ curl -sL https://goo.gl/KioV7L | bash -s /xvdb /mnt/hoge | sudo tee -a sudo /etc/fstab
UUID=123455-ba64-4142-93fb-8f278e7a2b0b	/mnt/hoge	xfs	defaults	0	0
```

マウントできるか確かめます。

```bash
$ mount -a
```

# スクリプトの中身

```bash
blkid | grep $1 | sed -r 's#^.*UUID="([a-Z0-9\-]+)".*TYPE="([a-Z0-9\-]+)".*$#UUID=\1\t'$2'\t\2\tdefaults\t0\t0#'
```

こんな感じになっています。
`blkid`の戻り値にダブルクォートが入っているのでそれを取り除きつつ、fstabの書式に合わせています。

# 注意点
`/dev/xvdb`などのドライブレターは`grep $1`で抜いているだけなので、`dev`みたいにゆるい書き方をすると複数行抜かれてしまいます。

真ん中に変数があるのはいただけない気も。

というかすでにこういうスクリプトというか`blkid`のオプションでありそうな気がしますが気にしないようにします！

# 参考サイト

助かりました。
http://yut.hatenablog.com/entry/20111013/1318436872
https://qiita.com/koara-local/items/2911bd81df2420a420ad
https://qiita.com/todanano/items/5be0f9a85602844d2c2d
http://program.station.ez-net.jp/special/handbook/sh/variables/sed.asp
Bundle Update のエラー（deviseを追加した際）


## 開発環境
AWSのcloud9で、ruby on railsを構築中に、deviseを追加したときにエラーが発生しました。
解決したので、メモに残しておきます。

## 実際にやったこと
deviseを追加するために、Gemfileに

```
gem 'devise', '3.4.1'
```
と記入してから、
bundle update
を実行すると、以下のエラーが表示されます。

```
The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`.
Fetching gem metadata from https://rubygems.org/.........
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies...
Bundler could not find compatible versions for gem "railties":
  In Gemfile:
    devise (= 3.4.1) was resolved to 3.4.1, which depends on
      railties (< 5, >= 3.2.6)

    rails (~> 5.2.0) was resolved to 5.2.0, which depends on
      railties (= 5.2.0)
```

エラーの内容を「互換性のあるrailtiesが見つからない」のところを見て、railtiesを変更すればよいのかと色々やったが、問題はそこではなくdeviseというgemがlistにないということが原因だったみたい。
色々やった結果。解決。まず、

```
gem list
```
を実行すると、一覧にdeviseの表示がない。
インストールが必要みたい。

```
gem install devise
```
を実行した後に、gem listを見ると、devise(4.4.3)と表示されるようになりました。

そこで、Gemfileのファイルの中のdeviseの行を以下のように変更します。

```
gem 'devise', '4.4.3'
```

そして、bundle update　が成功しました。
RHEL における ntpd/chrony の注意事項

RHEL における ntpd/chrony を利用して時刻を取得する場合、幾つか注意事項があるのでそれをまとめてみた。

# ntpd と chronyd の違い
まずはそれぞれの違いについて。

RHEL7 からは ntpd と chronyd が存在している。
当然だが、ntpd と chronyd には違いが存在し、RHEL がどのような環境で動作しているかで選択するサービスは異なる。
それぞれの違いについては、以下に記載されている。

第15章 CHRONY スイートを使用した NTP 設定
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/ch-configuring_ntp_using_the_chrony_suite

ざっくりとだけど、以下のような感じ。

- chronyd:仮想環境や NTP サーバと常に通信できない環境で選択
- ntpd:NTP サーバと常に通信できる環境で選択

# 注意事項
## NTP サーバの選択について
続いて、ntpd や chrony で時刻を取得する上で参照する上位の NPT サーバの決める上での注意事項について。

以下のドキュメントを参照した上で、上位の NTP サーバを決める必要がある。

Best practices for NTP
https://access.redhat.com/solutions/778603

Red Hat Enterprise Linux server using NTP will not keep time in sync with Windows-synced NTP server / windows NTP server
https://access.redhat.com/solutions/23365

Can NTP be used with two NTP servers, specifying one as primary and another as backup?
https://access.redhat.com/solutions/58025

まとめると以下のような内容になる。

- 上位の NTP サーバは最低 4 台が推奨される
  - 1 台でも時刻を取得することはできるけど、妥当と考えられる時間の刻みを計るには複数の NTP サーバが必要。
- 必要ではない限り、ローカルクロック (127.127.1.0) は参照しない
  - あまり精度が高くないから。
- 仮想マシンを上位の NTP サーバにするのは駄目
  - 精度が……
- Windows Server (特に Windows Server 2016 より前) を上位の NTP サーバにするのは駄目
  - 精度が……

## その他
ntpd/chrony によるハードウェアクロック調整と hwclock コマンドについて。

ntpd は以下の通り -x オプション無しでサービスを起動するとハードウェアクロックを調整 (システムクロックに同期) する。

How to check if 11 mints mode syncing hardware clock to system clock?
https://access.redhat.com/solutions/2455681

なお、上記の機能については、RHEL6 以降は ntpdate の起動も必要。また、ハードウェアクロックが ± 15 分離れると無効らしい。

16.18. ハードウェアクロック更新の設定
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/s1-configuring_the_hardware_clock_update

11 minute mode not syncing hardware clock to system clock
https://access.redhat.com/solutions/55432

chrony については、rtcsync の説明から同様の機能がある。
https://chrony.tuxfamily.org/doc/2.1/manual.html



ただし、man hwclock にあるが、上記の機能の有効にした状態で hwclock を実行するとハードウェアクロックが
正常に機能しなくなるので、注意。

```shell-session
  If your system runs with 11 minute mode on, don't use hwclock --adjust or hwclock --hctosys. 
  You'll just make a mess. It is acceptable to use a hwclock --hctosys at startup time to get 
  a reasonable System Time until your system is able to set the System Time from the external 
  source and start 11 minute mode.
```
man hwclock に記載の --adjust や --hctosys だけでなく hwclock コマンド自体が NG のはず。
ntpd/chrony による調整と hwclock コマンドのタイミングが重複すると OS を再起動するまでハードウェアクロックが更新されなくなる事がある。
※そもそも、上記の「11 mints mode」が存在する時点で、hwclock コマンド自体を実行する必要性はない気がするが。

# おまけ
以下で ntpd 設定用のスクリプトを作成可能。

NTP Configuration
https://access.redhat.com/labs/ntpcc/

以下の情報も参照しておくこと。

Understanding RHEL System Clocks And Time Protocol Implementations
https://access.redhat.com/articles/1456843
Apache Maven のインストール（ソースから）

必要があったのでメモ
Java1.7以上がインストール済みのCentOS7.5でやっています

# 手順
1. Mavenのバイナリファイルをダウンロードする

    ```
    # cd /opt/
    # curl -LkvOf http://ftp.jaist.ac.jp/pub/apache/maven/maven-3/3.6.0/binaries/apache-maven-3.6.0-bin.tar.gz
    ```

2. ファイルを展開する

    ```
    # tar xzvf apache-maven-3.6.0-bin.tar.gz
    ```

3. パスを通す

    ```
    # vi /etc/profile
    ```

    ```/etc/profile
    
    （省略）
    
    export PATH=/opt/apache-maven-3.6.0/bin:$PATH
    ```

4. sourceコマンドを実行する

    ```
    # source /etc/profile
    ```

## 確認
以下のコマンドを実行して、バージョンが表示されればOK

```
# mvn -v

Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-25T03:41:47+09:00)
Maven home: /opt/apache-maven-3.6.0
Java version: 1.8.0_202, vendor: Oracle Corporation, runtime: /usr/java/jdk1.8.0_202-amd64/jre
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "3.10.0-957.1.3.el7.x86_64", arch: "amd64", family: "unix"
```

# 参考
- [Installing Apache Maven](https://maven.apache.org/install.html)
はじめてのperlワンライナー

## perlワンライナーの使い所/メリット

- ワンライナー用途はrubyが良さそうだけど、導入できないってとき。
- sedもawkもシンプルだけど、細かい文法・正規表現が覚えられないし調べにくい。少し凝った処理したいとき辛い。
- sedはGNU系UNIX系で違うし、awkもgawk,mawkやらあり、いろんな差異が辛い。
  - perlならどこのLinuxサーバーにもだいたいperl 5.8 以降がはいってるので、ほぼ同じように使える。
  - perlなら機能も情報も豊富。



※スクリプトを書くならperlよりpython3で書きたいですが、ワンライナーについては perl　と ruby　が得意としています。

---

# はじめてのワンライナー

```bash:bash
$ perl -e 'print "hello\n"'
hello
```

## ワンライナーをコードとして確認 (-MO=Deparse)


```bash:bash
$ perl -e 'print "hello\n"' -MO=Deparse
print "hello\n";
-e syntax OK
```

-MO=Deparseをつければ、perlがワンライナー実行前にどんなコードに解釈してる表示してくれます。
よってperlのコードの書き方について学んでいくと、perlワンライナーへ結びつくことがわかるかと思います。
ワンライナーの内部がわからなくなったら、-MO=Deparseにて適宜、確認しつつ学習していくと理解していきやすいかと思います。


## perl自体の参考サイト
- 参考：[Perlゼミ(サンプルコードPerl入門)](http://d.hatena.ne.jp/perlcodesample)

上記サイトがとても参考になります。（本もおすすめです。）

# ワンライナーによく使うスイッチ(-anle)
- 参考：[パール、アナルを使え！または私は如何にして Perl のワンライナーを書けるようになったか](https://motemen.hatenablog.com/entry/2013/10/02/%E3%83%91%E3%83%BC%E3%83%AB%E3%80%81%E3%82%A2%E3%83%8A%E3%83%AB%E3%82%92%E4%BD%BF%E3%81%88%EF%BC%81%E3%81%BE%E3%81%9F%E3%81%AF%E7%A7%81%E3%81%AF%E5%A6%82%E4%BD%95%E3%81%AB%E3%81%97%E3%81%A6_Perl_)

基本はこれをつけておけばよいという定番です。上記のサイトが大変に参考になりました。

---

以上が、perlワンライナーの学習に必要な基礎となります。
あとは、ワンライナーやperlに関する記事を調べながら、
よく使うスイッチや特殊変数について覚えていけばいいと思います。
公式のperldocは翻訳されてて、網羅的に詳しいです（詳しすぎる）。ので、適宜に確認してください。


# 各スイッチの説明、及びワンライナー例

- 参考：[実用 perl ワンライナー](https://qiita.com/ohtsuka1317/items/92c339a65533e1e6c6fc)

上記の記事がとても参考になります。

雰囲気をひと目で掴むため、上記の記事をもとに、-MO=Deparseした結果を添えて以下、図表にまとめてみました。
赤字は一番左のスイッチの効果で、青字はみやすさのためprint部分に付けたものとなります。
![CheatSheet.PNG](https://qiita-image-store.s3.amazonaws.com/0/107635/f64ef0a0-5fa8-0963-6f5f-d5b0217143cb.png)


※こういう部分的に文字に色付けした表を、楽に記事にする方法がわからずスクリーンショットに。何かいい方法があれば知りたい。。。


- 参考：[perl のワンライナーの初歩 #1](https://qiita.com/bunzaemon/items/fdb1115ac97fc0955236)

この記事書いてから上記サイトに気づきました。とても参考になります。
SSHによるログイン先のホスト鍵更新時の挙動

###確認したのは下記条件
<dl>
<dt>OS</dt><dd>AIXとdebian(かなり古いやつ)</dd>
<dt>認証方式</dt><dd>鍵(パスフレーズ有と無)とパスワード</dd>
<dt>オプション</dt><dd>StrictHostkeyChecking=yesとno</dd>
</dl>

###手順
ホスト鍵更新の代わりに、クライアントのknown_hostsを出鱈目に編集してサーバへ接続。

###結果
|認証方式|結果|
|:--:|:--:|
|パスワード|パスワードも入れられず失敗|
|鍵|ログイン成功(known_hosts追記/書き換え無し)|

※ログインの方向、パスフレーズ有無、オプション有無による違いが結果に現れなかったので表からは省略。

###実は
警告メッセージを真面目に読んだら、『現状だとパスワードとキーボードインタラクティブは駄目。メッセージが鬱陶しいならホスト鍵は自力で修正しろ。何か挟まっているかも？』(意訳)と書いてあった。よく読め>俺。
Raspberry pi 3 上で、Seeed Studio社製 RIP Motion Sensor Large Lens を動かしてみた

# はじめに
Raspberry pi 3の電子工作にハマり、人感センサーで遊んでみようと言うことで、「RIP Motion Sensor Large Lens」を購入してました。

今回は動かすことメインで！！！

# 構成

Raspberry pi 3(OS:Raspbian)
Seeed Studio社製 RIP Motion Sensor Large Lens（人感センサー）

接続図は以下の通り

![スクリーンショット 2018-06-13 22.04.23.png](https://qiita-image-store.s3.amazonaws.com/0/232494/390901ba-86f0-fc4f-84f1-583013961402.png)


# 手順

## お試しコード

人感センサー(GPIO:23に接続)の状態に応じて、5秒置きに表示を行う

- 人検知：「Motion Detection...」
- 人未検知：「No Motion」

```python:rip.py
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

GPIO.setup(23, GPIO.IN)

try:
    time.sleep(2)
    while True:
        if GPIO.input(23):
            print("Motion Detection...")
        else:
            print("No Motion")
        time.sleep(5)
except:
    GPIO.cleanup()
```

## 動作確認

以下のpythonファイルを起動することで、人感センサーの検知によって、出力が変わる
※ Ctrl + C で終了

```terminal:terminal
$ python rip.py

No Motion
No Motion
Motion Detection...
```
# まとめ
人感センサーの状態を他のデータと紐づけてクラウドに上げて、分析をしてみる


# 参考URL

- [公式サイトのwiki](http://wiki.seeedstudio.com/PIR_Motion_Sensor_Large_Lens_version/)
- [PIR Motion Sensor with Raspberry Pi](https://www.hackster.io/hardikrathod/pir-motion-sensor-with-raspberry-pi-415c04)
emacs で World Cup の日程をサクッと表示する

# 目的

calfw.el、calfw-ical.el を使用して、World Cup の日程をワンコマンドで表示します。
ぶっちゃけ calfw-ical で以下を設定するだけです。

- http://www.skysports.com/calendars/football/fixtures/competitions/world-cup

# 設定

1.  calfw.el のインストール (M-x package-install calfw)
2.  calfw-ical.el のインストール (M-x package-install calfw-ical)
3.  init.el に以下を追加

```elisp:init.el
(require 'calfw)

(require 'calfw-ical)
(setq worldcup2018-calendar-url
"http://www.skysports.com/calendars/football/fixtures/competitions/world-cup")

(defun worldcup2018-calendar ()
(interactive)
(cfw:open-ical-calendar worldcup2018-calendar-url))
```

# 結果

M-x worldcup2018-calendar
![Screenshot_2018-06-13_19-47-53.png](https://qiita-image-store.s3.amazonaws.com/0/263158/043c687a-1f7a-5d08-5c56-13c0bd0d3dd8.png)

M	で月表示、W	で 1週間表示、T で 2 週間表示、D で日表示、f で次の日、など。

# おまけ

J リーグの予定も同時に表示させたければ

```elisp:init.el
(require 'calfw)

(require 'calfw-ical)
(setq worldcup2018-calendar-url
"http://www.skysports.com/calendars/football/fixtures/competitions/world-cup")
(setq J-calendar-url
"http://web-japp.datastadium.net/J/icals/download3/0/0/0/ical.ics")

(defun football-calendar ()
(interactive)
(cfw:open-calendar-buffer
:view 'month
:contents-sources
(list
(cfw:ical-create-source "J-league" J-calendar-url "#b7193f")
(cfw:ical-create-source "WC2018" worldcup2018-calendar-url "DarkOrange")
)))
```

M-x football-calendar
![Screenshot_2018-06-13_20-01-30.png](https://qiita-image-store.s3.amazonaws.com/0/263158/7da2dd4a-e4c5-ab6b-8594-13fced5d1810.png)


org まで落したい人は以下より。

- [It's here: Org Agenda for the World Cup 2018](http://www.sastibe.de/2018/06/its-here-org-agenda-for-the-world-cup-2018/) ([日本版](https://github.com/clothoid/org-world-cup))

# 参考

- [kiwanami/emacs-calfw](https://github.com/kiwanami/emacs-calfw)
- [World Cup calendar](http://www.skysports.com/football/news/15241/9066717/world-cup-calendar)
- [日程ダウンロード](http://web-japp.datastadium.net/J/icals/index/)
- [さっかりん - スケジュール ダウンロード](http://soccer.phew.homeip.net/download/schedule/) < Jチームごとならこれがいいかも

...初めての投稿です。 org に~~するの面倒くさいのですが、~~ [しました](https://github.com/clothoid/org-world-cup) (Thu Jun 14 2018) が、その他、いい方法があったら教えてください。
pipでエラー"zlib.error: Error -5 while decompressing data..."の対処法

## 解決したいこと

以下のような「zlib.error: Error -5 while decompressing data: incomplete or truncated stream」エラーが出たときの対処です。

OSはUbuntu 16.04です。

```
ib/python3.5/dist-packages/pipenv/patched/piptools/repositories/pypi.py", line 372, in open_local_or_remote_file
    response = session.get(url, headers=headers, stream=True)
  File "/usr/local/lib/python3.5/dist-packages/pipenv/vendor/pip9/_vendor/requests/sessions.py", line 521, in get
    return self.request('GET', url, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/pipenv/vendor/pip9/download.py", line 386, in request
    return super(PipSession, self).request(method, url, *args, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/pipenv/vendor/pip9/_vendor/requests/sessions.py", line 508, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.5/dist-packages/pipenv/vendor/pip9/_vendor/requests/sessions.py", line 618, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/pipenv/vendor/pip9/_vendor/cachecontrol/adapter.py", line 37, in send
    cached_response = self.controller.cached_request(request)
  File "/usr/local/lib/python3.5/dist-packages/pipenv/vendor/pip9/_vendor/cachecontrol/controller.py", line 111, in cached_request
    resp = self.serializer.loads(request, cache_data)
  File "/usr/local/lib/python3.5/dist-packages/pipenv/vendor/pip9/_vendor/cachecontrol/serialize.py", line 114, in loads
    return getattr(self, "_loads_v{0}".format(ver))(request, data)
  File "/usr/local/lib/python3.5/dist-packages/pipenv/vendor/pip9/_vendor/cachecontrol/serialize.py", line 176, in _loads_v2
    cached = json.loads(zlib.decompress(data).decode("utf8"))
zlib.error: Error -5 while decompressing data: incomplete or truncated stream
```

　`pipenv install`したときに起こりました。

## 解決方法

以下のコマンドで`.cache/pip/`内のファイルを削除しました。
（実際は削除は怖いので`mv`で違う名前変えました）

```bash
rm -rf ~/.cache/pip/*`
```


## このエラーの原因だと思われること

`pipenv install OOO`をしたときに“(No space left on device”でpipが強制終了したのが、影響しているのではないかなと思ってます。そのため、想定外な状態でpipが終了して、キャッシュが悪さをしてこのエラーが起こっていたのだと思います。

このエラー`pipenv`に限った問題ではなく`pip`に関することだ思います。参考のリンクでも`pip install XXX`でこのエラーが起こっていたようです。


## 参考

* [python - 'error: Error -5 while decompressing data: incomplete or truncated stream' when installing pip package - Stack Overflow](https://stackoverflow.com/questions/31878423/error-error-5-while-decompressing-data-incomplete-or-truncated-stream-when/31878424#31878424)
React NativeでiOSのシミュレータが起動しないときにやることリスト

# はじめに
React Nativeでの開発で、iOSのシミュレータが起動しないことがよくあります。
その度に解決方法を調べているので、まとめておこうと思いました。

# 1. node_modules周りをリセット
node_modules/ 以下を消して、キャッシュをクリアします。

```
$ watchman watch-del-all
$ rm -rf node_modules/
$ yarn install
$ yarn cache clean
```

# 2. CocoaPod周りをリセット
CocoaPodを導入している場合は、そちらもリセット。

```
$ rm -rf ~/Library/Caches/CocoaPods
$ cd ios
$ rm -rf Pods/
$ pod install
```

# 3. デバッグモードにしている場合、Chromeの再起動
一度デバッグモードにすると、次にアプリを起動したときも自動でデバッグモードになります。
その際に、Chromeとの接続が悪いのか、うまくデバッガが起動せず、エラーになることがあります。

その場合は、Chromeのキャッシュを消して再起動し、再度 `react-native run-ios`　を実行することでうまくデバッガが起動し、アプリも立ち上がるようになります。

# 4. iOSシミュレータのリセット
シミュレータが起動したがアプリは起動しないような場合、シミュレータをリセットすると直ることがあります。

シミュレータのメニューの「Hardware > Erase all Content and Settings...」を選択すると、今までシミュレータ上に追加されたアプリが消え、リセットされます。

![debug.png](https://qiita-image-store.s3.amazonaws.com/0/120309/d560041e-eeef-5ddf-7050-cc0dedc1d6c5.png)

シミュレータが再起動されたことを確認できたら、一度ターミナルも消して再度 `react-native run-ios` を実行します。

# 5. Xcodeからキャッシュを削除する
Xcodeの「Product > Clean」でクリーンを実行します。
![xcode.png](https://qiita-image-store.s3.amazonaws.com/0/120309/78cf318f-f0fa-2a0a-c0bf-f106e299b9cd.png)

( `Shift + Command + k` でも実行できます）

# 6. ターミナルにエラーログが出ていないか確認する
`react-native run-ios` を実行した際に一緒に立ち上がるターミナルに何かしらエラーが出ていることがあります。

（1番最初にReact Nativeのプロジェクトを作ってシミュレータを起動しようとしたとき、ターミナルにnodeへのパスが通ってないエラーが出ていたのですが、長いこと気が付かずに全然違う解決方法を試して時間を無駄にしてしまいました…。）

#　まとめ
React Nativeは何のエラーのためにシミュレータが立ち上がらないのかわからないことが多く、
大体1と2のキャッシュクリアを試すと解決することが多いです。

ほかにもシミュレータが起動しない原因とその解決方法があったら追記していきます！
非公開関数のユニットテストについて (C#)

# 非公開関数のユニットテストについて (C#)

備忘録として.

非公開関数のユニットテストをしたいときには以下のようにする.

1. 対象のアクセス修飾子を`internal`にする.
2. 対象のプロジェクトの`Properties\AssemblyInfo.cs`を開き、`[assembly: InternalsVisibleTo("ユニットテストのアセンブリ名")]`を追記する.
nuxtでmomentを動かす

# nuxtでmomentを触る時に苦労したので導入を説明します。

nuxtコミュニテイのmoduleを使いましょう
[nuxt-community/moment-module](https://github.com/nuxt-community/moment-module)

基本的にはここのreadmeに従えば良いです。

`yarn add moment @nuxtjs/moment OR npm i moment @nuxtjs/moment`

```nuxt.config.js
{
  modules: [
    ['@nuxtjs/moment', ['ja']]
 ]
}
```

これだけでvueインスタンスへ$momentを登録します。そのためdatepickerなどのmoduleを入れようとして間違えてvue-momentやmoment自体を導入しpluginsにてVue.useとかすると**意図していない動作をします。**（当たり前）

View側では$momentでアクセスすることが可能です。
注意してほしいのはVueのインスタンスに登録されているのでvueインスタンスに組み込まれるメソッド内（methodsやcomputedなど）では**this.$moment**でアクセスします。
Scene Builder 文字化け

#Scene Builder文字化け対応

##現状
![rapture_20180613203900.png](https://qiita-image-store.s3.amazonaws.com/0/32912/99cfbbd5-6939-a960-791a-caeaf6445893.png)


##目標
このまま使えないので、取りあえず**英語版**にする。

##手順１
インストール場所にの配下にの「**SceneBuilder.cfg**」というファイルを探す。

![rapture_20180613204020.png](https://qiita-image-store.s3.amazonaws.com/0/32912/d7f8b234-326d-9909-126b-a8d4a5dc9078.png)
*※万が一の時のために、コピー取るのをお忘れずに。*

##手順２
エディターで開いて、以下の行を追加、保存。

```ini:SceneBuilder.cfg
-Duser.language=en
```

![rapture_20180613204119.png](https://qiita-image-store.s3.amazonaws.com/0/32912/4383e8a9-9a3c-c371-f13a-93105c113e6d.png)
*※修正後のイメージ*

##結果
英語になりました。
![rapture_20180613204207.png](https://qiita-image-store.s3.amazonaws.com/0/32912/d5619542-9c50-979a-b528-2a59d6dccdb9.png)

---
#######参考
\[1\].[Java デフォルト・ロケールの上書き実行](http://d.hatena.ne.jp/happynow/20120525/1337978514)
UnityのAndroidビルド時にFailed to Move File / Directory from...が出て困ったら

Unityでバージョンを上げたりしていると、Androidビルド時に以下のようなメッセージが出て失敗してしまうことがあります。

```
IOException: Failed to Move File / Directory
 from 'Temp/StagingArea/android-libraries/com.google.android.gms.play-services-ads-license-11.8.0/classes.jar'  
 to 'Temp/StagingArea/android-libraries/com.google.android.gms.play-services-ads-license-11.8.0/libs/classes.jar'.
```

そんなときは以下で解消されます。

```
Asset - Play Services Resolver - Android Resolver - Force Resolve
```

いつも忘れて焦ってしまうのでメモっておきます。
ROS講座22 リモートでロボットの電源を切る

# 環境
この記事は以下の環境で動いています。

| 項目 | 値 |
|:-:|:-:|
| CPU | Core i5-8250U |
| Ubuntu | 16.04 |
| ROS | Kinetic |

インストールについては[ROS講座02 インストール](https://qiita.com/srs/items/e0e0a9dc3f94c2d3348e)を参照してください。
またこの記事のプログラムはgithubにアップロードされています。[ROS講座11 gitリポジトリ](https://qiita.com/srs/items/25a56a6abda41dcf396e)を参照してください。

# 概要
意外と面倒なのがロボットの電源を切ることです。「sudo shutdown now」程度のコマンドなら簡単に行えますが、ロボットには通常時はキーボードやモニタがつながっていないのでこんなことも面倒です。
普通はsshで接続して電源を切るのですが

1. ssh r_user@robot1
2. パスワードを入力
3. sudo shutdown now
4. パスワードを入力

と意外と手間がかかります。これをroslaunchでリモートlaunchすることでコマンド1つで実行しようというのが今回の趣旨です。今回の記事では以下の2点を説明します。

* c++でbashコマンドを実行する方法
* sudoが必要なコマンドを実行する方法

# c++でbashコマンド実行
C++のプログラム中からは`system()`関数を使うとbashコマンドを実行できます。`system()`関数を使うには`#include <stdlib.h>`のインクルードをする必要があります。例えば以下のようにするとbashコマンドを実行できます。

```c++:robot_shutdown.cpp
#include <stdlib.h>
int main(void){
    system(" COMMAND ");
    return 0;
}
```

# sudoコマンドの実行
上記の例を踏まえて以下のようなプログラムを実行すると失敗します。これはsudoを打つことによってパスワードを対話的に要求されてしまうためです。

```c++:sudoコマンドの実行：失敗する
#include <stdlib.h>
int main(void){
    system("sudo shutdown now");
    return 0;
}
```

これを解決する方法として`sudo -S`のオプションを使うという方法です。これはパスワードを標準入力から受け取るというオプションです。例えばパスワードがpasswordだった場合は`echo 'password' | sudo -S command`とすると実行できてしまいます。パスワードが直書きなのでセキュリティー的には大変よろしくないのですが、一番簡単な解決策です。

# 結論
最終的な案を以下に示します。

```c++:net_lecture/src/net_shutdown.cpp
#include <stdlib.h>
int main(void){
    system("echo 'password' | sudo -S shutdown now");
    return 0;
}
```

これを普通のROSのC++プログラムと同じようにCMakeList.txtを書いてコンパイルします。ROSのC++プログラムもただのC++プログラムにROSのライブラリを追加しただけのものです。

```cmake:net_lecture/CMakeLists.txtに追加
add_executable(net_shutdown src/net_shutdown.cpp)

target_link_libraries(net_shutdown
  ${catkin_LIBRARIES}
)
```

これを*shutdownする対象のロボット上*でbuildします。

これをlaunchファイルから起動します。

```xml:et_lecture/launch/remote_shutdown.launch
<launch>
  <machine name="robot1" address="192.168.1.20" env-loader="/home/r_user/catkin_ws/devel/env.sh" user="r_user" password="password"/>
  <node machine="robot1" pkg="adv_lecture" type="robot_shutdown" name="robot_shutdown" required="true"/> 
</launch>
```

`<machine>`タグではshutdownをする対象のPC(ロボット)を指定します。このROSノードを起動するとPCがシャットダウンするのでROSノードももちろん落ちます。この時に`required="true"`を指定しておくとそのROSノードが落ちた時に自動的にlaunchも停止します。

```shell:robot1がshutdownする
roslaunch net_lecture remote_shutdown.launch
```

上のコマンドでネットワークでつながっている別のPC（ロボット）の電源を切ることができます。
この時`robot_shutdown`はrobot1側で実行されるのでこのプログラムが入っているROSパッケージであるadv_lectureがrobot1に入っている必要があります。

# 目次ページへのリンク
[ROS講座の目次へのリンク](https://qiita.com/srs/items/5f44440afea0eb616b4a)
【10分でほぼ解決】Twitter広告 タグが発火しない時の対処法

#**Twitter広告 ユニバーサルウェブサイトタグ／単一CVタグが発火しない時の対処法**
WEB広告の担当者、運用者、営業の方々の悩みのたね**「タグの発火確認」**。
今回は備忘録として試した方法と解決方法を記載します。

##結論：タグ着火しない→問い合わせから着火しないんですけどって伝える
これを結論に書いていいものか迷いましたが、今回のケースではこの方法で解決しました。
しかも問い合わせてから数時間以内でスピード解決していますので、包み隠さず結論に置きました。

###1：これで知識アップ！タグの仕様
- 複数のTwitterタグは設置OK、ユニバーサルと単一CVタグの両方を同じLP内に貼ってOK、他アカウントのタグとかぶってもOK
- 反映は24時間後くらい
- 管理画面＞コンバージョン＞タグのステータス＞トラッキングなったらOK

###2：これで技術力アップ！タグが着火しない理由と調べ方や対応
- 設置されていない：LP内をF12で探す。再設置
- 設置位置が```<body></body>```内じゃない：LP内をF12で探す。再設置
- コードに不要な改行が含まれる：エクセルを使い、LPのタグと媒体のタグをEXACTで確認
- タグマネを使っている：公開になっているか確認。トリガーなどの設定を確認
- タグマネを使い、直にも生タグを貼っている：同じタグの重複はエラーになる可能性がある
- Twitterタグより上部の階層がエラー：他のタグは動いているのか確認。F12を押してエラーがあるか確認

##まとめ
WEB広告あるある**タグ発火しない時の対処法**をお送りしました。
複数の代理店や複数の担当者が関わる場合にタグのエラーが起こりやすいようです。
考えられる原因はすべて潰したのに解決しないあなた！ 実はサーバーサイドのエラーが原因かもしれません。
Googleで検索するよりも、媒体へ問い合わせる方が早く解決することもあります。
（とは言いつつ、媒体問い合わせの前に英語で検索してしまう気持ちもすごくわかります）
ありがとうございました。

＃Twitter
RxSwift：特定のエラーが起きたときに一定回数までその処理をやり直す

# 実用例
認証が必要なAPIを叩くとき、もし認証トークンが無効でAPIが失敗したらトークンを更新して再度APIを叩く、但し一定回数リトライしても認証トークンが無効となるようだったらリクエストを諦めてリクエスト失敗扱いにする

# 方法
1. 特定のエラーが起きたら処理をやり直したい
  - `retryWhen` 使う
1. ただしリトライは一定回数までにしたい
  - 今何回目のエラーか判断できればいいので、 `enumerated` で回数をつける
 
## サンプルコード
リクエストの結果はSingleで受け取れる想定
成功するとsuccess、失敗するとerrorが流れてくる

```APIWithTokenSample.swift
requiredAuthRequest.post(with: parameters)    // 認証が必要なAPIを投げる
    .retryWhen { errorObservable in
        return errorObservable.enumerated()
            .flatMap { retryCount, error -> Single<Int> in
                // 自分のAPIサーバの固有エラーかチェックする
                guard let myApiError = error as? MyApiError else {
                    return .error( error)
                }
                guard myApiError.type == .invalidAuth else {
                    return .error( error)
                }

                // 一定回数以上失敗したらリトライしない
                guard retryCount < MyAuth.maxRetryCount else {
                    return .error( error)
                }

                // 認証トークンを更新する、これも結果はSingleで受け取れる想定
                return MyAuth.default.updateToken() 
            }
    }
    .subscribe( onSuccess: { [unowned self] result in
        self.doSomethingOnSuccess( with: result)
    }, onError: { [unowned self] error in
        self.handle( error)
    })
    .disposed(by: disposeBag)
```
VScodeでautopep8が勝手に改行するのを見逃してほしい

breakして作業する際に

```
# autopep8 整形前

import pdb; pdb.set_trace();
```

とワンライナーで使い捨てコードを差し込みたいのだが、
autopep8が効いて勝手にセミコロン部分を改行してしまう。

```
# autopep8 整形後

import pdb
pdb.set_trace()
```

ルール「E70」を除外したら見逃してくれるようになった

ユーザーないしは、プロジェクト設定（⌘+,）で下記を追加

```
"python.formatting.autopep8Args": [

    # ... 中略

    　# セミコロンでの改行するのを見逃して
    "--ignore", "E70",

    # 1行80文字までとか無理です
    "--max-line-length", "120",

    # ... 中略

]
```
mailx で 日本語 + 変数 の件名を送信する

# 要件

`mailx` コマンドで、以下のような日本語件名を送信したい

```
固定件名 - <変数：本日日付> <変数：文字列>
```

# ソースコード

```SendMail.sh
#!/bin/sh
#set -x

# カレントディレクトリで作業する
cd `dirname $0`

# 連絡先アドレス
MAILRCPT="user@fuga.fuga"
# 連絡元
FROM="root@hoge.hoge"
# オリジナルの件名(日本語のままでOK)
MAIL_SUBJECT="固定件名 DATE - TEXT"
# メール本文ファイル
MAILFILE=mail.txt

# 日付を本日日付に変更
NOW_DATE=`date '+%Y/%m/%d'`
# オリジナル件名の日付項目を本日日付に変換して、新しい変数に格納する
MAIL_SUBJECT2=`echo ${MAIL_SUBJECT/DATE/"$NOW_DATE"}`
# テキスト項目を変数に変更
HOGE_TEXT=ほげほげ
MAIL_SUBJECT2=`echo ${MAIL_SUBJECT2/TEXT/"$HOGE_TEXT"}`

echo "MAIL_SUBJECT2: $MAIL_SUBJECT2"

# 生成した件名をbase64でエンコードして、件名のprefix, suffixを付ける
SUBJECT_ENCODE=`echo -n "$MAIL_SUBJECT2" | base64 | xargs printf '=?UTF-8?B?%s?='`

# メール送信
/bin/mailx -r ${FROM} -s ${SUBJECT_ENCODE} ${MAILRCPT} < ${MAILFILE}
```
ESXi6.0 で SSH公開鍵認証でのログイン

大変しょーもないことでハマってしまったので。

# 目的
ssh で公開鍵認証でログインしたいんや

# どこらへんがハマったか
クライアント側から `ssh-copy-id``してもパスワードログインできへんやないか！
**（そもそもssh-copy-idは使えない模様）**

# じゃあどうするのか
公開鍵のファイルの場所がホームディレクトリにない模様
`/etc/ssh/keys-root/authorized_keys ` `ここにある

## 番外編

```console
localhost% ssh-copy-id user@hogehoge.com
/usr/bin/ssh-copy-id: ERROR: No identities found
```

なんか怒られる。。。

## 解決策
サーバ側に.sshファイルがないんだって

参考
https://kb.vmware.com/s/article/2080948
uid/gid関連で便利なコマンド

先日サーバを結構たくさんリプレースしまして、
/etc/passwdとかshadowを手でがんばって移したんですけど
そのとき教えて頂いてuid/gid関連で便利だな～って思ったコマンド

## 1. マッピングのチェックにすごい便利だな～って思ったコマンド
##### コマンド
```bash
for x in `grep -v "/home/" /etc/passwd |sort|awk -F":" '{print $1}'`;do echo "### $x ###";id $x ;done
```
##### 結果サンプル
```
# for x in `grep -v "/home/" /etc/passwd |sort|awk -F":" '{print $1}'`;do echo "### $x ###";id $x ;done
### abrt ###
uid=173(abrt) gid=173(abrt) groups=173(abrt)
### adm ###
uid=3(adm) gid=4(adm) groups=4(adm),3(sys)
### alias ###
uid=900(alias) gid=900(nofiles) groups=900(nofiles)
### apache ###
uid=48(apache) gid=48(apache) groups=48(apache),912(nagios)
### authdb ###
uid=909(authdb) gid=902(vida) groups=902(vida)
### bin ###
uid=1(bin) gid=1(bin) groups=1(bin),2(daemon),3(sys)
### daemon ###
uid=2(daemon) gid=2(daemon) groups=2(daemon),1(bin),4(adm),7(lp)

(以下略) 
```
手で一生懸命移してから↑やると結構ミスってるんですよね･･･涙
↓みたいな感じで・・

```
ミスのイメージ
### apache ###
uid=48(apache) gid=49(hoge) groups=49(hoge)
```
※たとえばこれだとapacheの起動ユーザ/グループが
　apache.apacheだったらあがんないからね・・

##2. uid/gidでソートするコマンド

##### コマンド
```
# sort -t':' -k3 -n /etc/passwd
# sort -t':' -k3 -n /etc/group
```

##### 結果サンプル
```
# sort -t':' -k3 -n /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
(以下略)

# sort -t':' -k3 -n /etc/group
root:x:0:
bin:x:1:bin,daemon
daemon:x:2:bin,daemon
sys:x:3:bin,adm
adm:x:4:adm,daemon
(以下略)
```

うーん美しい
magento2 composerインストール時のマーケットのアカウント登録

# はじめに

magentoの開発環境を構築する際に、composerを使って、プロジェクトを立ち上げると、
マーケットプレイスのログイン認証を求められます。

※ magento2の環境構築手順は [こちら](https://qiita.com/kumanizm/items/67de430dda5c80088906)

ここに入力するID/PWが分かり難かかったので、備忘録として残しておきます。

```
$ composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition /var/www/html/ 
Do not run Composer as root/super user! See https://getcomposer.org/root for details
                                                                                    
    Authentication required (repo.magento.com):
      Username: *********
      Password: *********
```

上記の「Username」「Password」がわかりにくい。 **ログインIDとパスワードではない**。

`以下、アカウント登録手順`

# developer.magento.com アカウントの登録手順

https://developer.magento.com/ にアクセルする

![スクリーンショット 2018-06-13 18.08.33.png](https://qiita-image-store.s3.amazonaws.com/0/103/f1d457d3-7f16-9f4e-d4d9-b3845d731585.png)

**↑上記のボタンをクリックする**

![スクリーンショット 2018-06-13 18.09.05.png](https://qiita-image-store.s3.amazonaws.com/0/103/69494bc8-b3b2-5822-c355-2d26f2e83d71.png)

**↑上記のボタンから会員登録ページへ遷移する**

![スクリーンショット 2018-06-13 18.09.21.png](https://qiita-image-store.s3.amazonaws.com/0/103/8f5718a1-2527-63fa-4417-6a5a63866a07.png)

**必要情報を入力して、会員登録を行なってください**


![スクリーンショット 2018-06-13 18.09.56.png](https://qiita-image-store.s3.amazonaws.com/0/103/82e61c15-fbbe-b545-8e9e-116ed7bd4ae9.png)

**登録後、ログイン画面から「メアド」「パスワード」を入力しログインする**

![スクリーンショット 2018-06-13 18.10.43.png](https://qiita-image-store.s3.amazonaws.com/0/103/bd76a434-4fa1-9235-6286-344946a69c41.png)

**↑上記のボタンをクリックして、AccessKeyを発行してください**

![スクリーンショット 2018-06-13 18.11.49.png](https://qiita-image-store.s3.amazonaws.com/0/103/4984325c-d972-466f-e59d-762ed82f3e02.png)

**↑　今回は「Magento2」を使用するので、「Magento2」のタブを開き**
**「Create A New Access Key」のボタンをクリックしてください。**

登録が終わると、下のような一覧画面が表示されるので、その「Public Key」「Private Key」を保管しておきます。

ご想像の通り、
**「Username」=「Public Key」** 、**「Password」=「PrivateKey」** になります。

## composerのコマンド

```
$ composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition /var/www/html/ 
Do not run Composer as root/super user! See https://getcomposer.org/root for details
                                                                                    
    Authentication required (repo.magento.com):
      Username: *********
      Password: *********
```

保管しておいたKeyを入力すると、インストールが可能です。
StaticNATはアドレス変換後のACL設定がないとできなかったけどいらないはずなのになんでみたいな話

はまったので
# 要件
1. LinuxServerはグローバルIPを持たない
1. グローバルIPの1.1.1.1にポート22022でアクセスするとLinuxServerにsshできるようにする
1. グローバルIP1.1.1.1のポート22022は全開放する

```
[SRX]--------------------[LinuxServer]
1.1.1.1:22022            10.1.0.1:22
```

# こうなった
#### 1.22022ポートを指定するためのapplication設定を作成
```bash
set applications application SSH_22022 protocol tcp
set applications application SSH_22022 source-port 1-65535
set applications application SSH_22022 destination-port 22022
```

#### 2.StaticNATを設定
```bash
set security nat static rule-set NAT rule ssh_22022 match destination-address 1.1.1.1/32
set security nat static rule-set NAT rule ssh_22022 match destination-port 22022
set security nat static rule-set NAT rule ssh_22022 match then static-nat prefix 10.1.0.1/32
set security nat static rule-set NAT rule ssh_22022 match then static-nat prefix mapped-port 22
```

#### 3.source/destをanyにして1で作ったapplicationを許可
0.0.0.0:22022でLISTENなイメージ

```bash
set security policies from-zone Internet to-zone Internal policy Inernet-to-Internal match source-address any
set security policies from-zone Internet to-zone Internal policy Inernet-to-Internal match destination-address any
set security policies from-zone Internet to-zone Internal policy Inernet-to-Internal match application SSH_22022
set security policies from-zone Internet to-zone Internal policy Inernet-to-Internal then permit
```

# これだと接続できない

マッピングするポートでもACL判定してるらしいので、
22番を通す設定を追加。
applicationはあらかじめSRXにプリセットのjunos-sshをつかう。

```bash
set security policies from-zone Internet to-zone Internal policy Inernet-to-Internal match application SSH_22022 junos-ssh
```

これでOK！
なんか22も許可されてんじゃないかと心配になるけど、
22022からはSSHできて、22ははねてくれるので大丈夫。

## 追記
コメントいただきました！ありがとうございます。
そうなんだろうな～って感じなんですが周囲を相当巻き込んで検証して
実際これじゃないと動かなかったという備忘録ですのでケースの1例ってことでよろしくです。

>処理の順序がStatic NAT→Policyの順になるため、この例ではPolicyで22022を開ける必要はありません。
>SSH_22022のアプリケーション作成も不要になります。
>set security policies from-zone Internet to-zone Internal policy Inernet-to-Internal match junos-ssh
【gorm】数値のカラムを0で更新する

# はじめに

gormでintのカラムを0で更新しようと思ったらできなかったので、調べた内容をメモ。

# 現象

Usersテーブルの内容が以下だったとして

|id|num|
|---|---|
|1|1|


```go
type User struct {
	ID  int
	Num int
}

func test() {
	u := User{ID: 1, Num: 0}

	db, _ := gorm.Open(...)
	defer db.Close()

	savedData := []User{}
	db = db.Where("id = ?", u.ID)
	db.Find(&savedData)
	db = db.Model(&savedData[0]).Update(&u)
}
```

testを実行すれば、``id = 1``の行のnum列を``0``で更新して欲しいのですが、してくれません…

# やり方

gormでは、更新対象のオブジェクトの値が[ゼロ値だった場合更新対象から外れる](http://tapira.hatenablog.com/entry/2017/08/11/182249)ようです。なので、前述の記事と同様にゼロ値が入りうる項目をポインタにすればOKです。
この場合は``Num``なので、以下のように修正すれば0で更新できるようになります。

```go
type User struct {
	ID  int
	Num *int
}

func test() {
	num := 0
	u := User{ID: 1, Num: &num}

	db, _ := gorm.Open("")
	defer db.Close()

	savedData := []User{}
	db = db.Where("id = ?", u.ID)
	db.Find(&savedData)
	db = db.Model(&savedData[0]).Update(&u)
}
```
lscpuコマンドの使い方

最新記事は以下に作成しました。
https://hana-shin.hatenablog.com/entry/2023/07/02/223418

#1 lscpuコマンドとは?
CPUの情報を表示するコマンドです。

#2 環境
VMware Workstation 14 Player上の仮想マシンを使いました。
仮想マシンのOS版数は以下のとりです。

```console:OS版数
[root@server ~]# cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)

[root@server ~]# uname -r
3.10.0-693.el7.x86_64
```

#3 コマンドのインストール

```
[root@server ~]# yum -y install util-linux

[root@server ~]# lscpu -V
lscpu from util-linux 2.23.2
```

#4 オプション一覧

```
[root@server ~]# lscpu -h

Usage:
 lscpu [options]

Display information about the CPU architecture.

オプション:
 -a, --all               print both online and offline CPUs (default for -e)
 -b, --online            print online CPUs only (default for -p)
 -c, --offline           print offline CPUs only
 -e, --extended[=<list>] print out an extended readable format
 -p, --parse[=<list>]    print out a parsable format
 -s, --sysroot <dir>     use specified directory as system root
 -x, --hex               print hexadecimal masks rather than lists of CPUs
 -y, --physical          print physical instead of logical IDs

 -h, --help     display this help and exit
 -V, --version  output version information and exit

Available columns:
           CPU  logical CPU number
          CORE  logical core number
        SOCKET  logical socket number
          NODE  logical NUMA node number
          BOOK  logical book number
        DRAWER  logical drawer number
         CACHE  shows how caches are shared between CPUs
  POLARIZATION  CPU dispatching mode on virtual hardware
       ADDRESS  physical address of a CPU
    CONFIGURED  shows if the hypervisor has allocated the CPU
        ONLINE  shows if Linux currently makes use of the CPU
        MAXMHZ  shows the maximum MHz of the CPU
        MINMHZ  shows the minimum MHz of the CPU

For more details see lscpu(1).
```

#5 CPUの情報を表示する方法（オプション指定なし）

```
[root@server ~]# lscpu
アーキテクチャ: x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                8
On-line CPU(s) list:   0-7
コアあたりのスレッド数:1
ソケットあたりのコア数:1
Socket(s):             8
NUMAノード:         1
ベンダーID:        GenuineIntel
CPUファミリー:    6
モデル:             158
Model name:            Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
ステッピング:    9
CPU MHz:               2807.545
BogoMIPS:              5616.00
ハイパーバイザーベンダー:VMware
仮想化タイプ:    完全仮想化
L1d キャッシュ:   32K
L1i キャッシュ:   32K
L2 キャッシュ:    256K
L3 キャッシュ:    6144K
NUMAノード 0 CPU:   0-7
Flags:                 fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid mpx rdseed adx smap clflushopt xsaveopt xsavec arat
```


#Z 参考情報
G-Suiteのリジェクトをローカルでメールをリレーさせて回避する

あるEC2インスタンス+EIP運用のサーバ(以下サーバA)から
メールをとばしてたらG-Suiteからはじかれるようになって悲しかったときの話

# 前提というか状況

1. サーバAはpostfixを使っている
1. サーバAからあるG-Suite使用ドメイン(以下@company.com)宛に送信するとはじかれる
1. その他のメールアドレス宛の送信は可能
1. EIPのブラックリスト登録はされていない →　[mxtoolboxのブラックリストチェック](https://mxtoolbox.com/blacklists.aspx)
1. EIPのメール送信上限緩和申請＆逆引き申請は済んでいる  →　[AWS EC2 Eメール上限緩和 / 逆引き(rDNS)設定 申請手順](https://www.slideshare.net/AmazonWebServicesJapan/aws-42885668)
1. SPFレコードはPassしている　→ [mxtoolboxのSPFチェック](https://mxtoolbox.com/spf.aspx)
1. DKIMもDMARCもOK


# maillogのエラー
```bash:/var/log/maillog
May  8 15:07:28 mail01 postfix/smtp[21362]: 930CE4019A: to=<hoge@company.com>, relay=alt1.aspmx.l.google.com[*.*.*.*]:25, delay=433074, 
delays=433072/0.04/1.6/0.89, dsn=4.7.0, status=deferred (host alt1.aspmx.l.google.com[173.194.199.27]
 said: 421-4.7.0 [*.*.*.*      15] Our system has detected an unusual rate of 421-4.7.0 unsolicited mail originating from your IP address.
  To protect our 421-4.7.0 users from spam, mail sent from your IP address has been temporarily 421-4.7.0 rate limited.
   Please visit 421-4.7.0  https://support.google.com/mail/?p=UnsolicitedRateLimitError to 421 4.7.0 review our Bulk Email Senders Guidelines.
    4-v6si5777803oil.431 - gsmtp (in reply to end of DATA command))
```
そんなあ

# 対策の検討

もうGoogle側でリストされていて手出しができない・・・
対策として考えられるのは以下の２つ

1. サーバAのEIPを変更してトライ
1. 他のサーバをリレーさせる

１．はDNSのレコード切り替えしたくなかったし
　　次のEIPもだめだったら地獄なのでとりあえず却下

２．の方向で行くことに。

# 対策の実装

どのサーバにリレーさせるかですが、company.comのAレコードを持っている
サーバ(以下サーバB)にリレーさせることに決定。

全てのメールをリレーさせてもいいけど、
すでに配信できてる分は不用意にいじりたくないので
company.com宛のメールのみサーバBをリレーさせてあげることに。

## 1.サーバBのEIPで逆引き申請
[AWS EC2 Eメール上限緩和 / 逆引き(rDNS)設定 申請手順](https://www.slideshare.net/AmazonWebServicesJapan/aws-42885668)

## 2.サーバBでSPFとかDKIMとかそのへん全部パスできるようにレコード見直し
がんばる

## 3.サーバAのPostfixでcompany.comだけサーバB(192.168.0.1)をリレーするようにする
```bash:/etc/postfix/main.cf
transport_maps = hash:/etc/postfix/transport
```
```bash:/etc/postfix/transport
comapny.com  smtp:[192.168.0.1]
```
```
# postmap /etc/postfix/transport
# systemctl restart postfix or　# service postfix restart
```


## 4.サーバBのPostfixでローカルIPでリレーさせるのでメールヘッダのホストがIPアドレスでもOKにするのと
　メールヘッダからサーバAのローカルIP消したい

```bash:/etc/postfix/main.cf
enderesolve_numeric_domain = yes
header_checks = regexp:/etc/postfix/header_checks
```
```bash:/etc/postfix/header_checks
/^Received:.*192\.168\..*/ IGNORE
/^Received:.*127\.0\.0\.1.*/ IGNORE
```
```
# systemctl restart postfix or # service postfix restart
```
これでOK！
再帰関数を理解するための最もシンプルな例

# はじめに
再帰関数を理解するにあたり先輩社員に教えていただいたのですが、その時の再帰関数の例がとてもわかりやすかったので共有させていただきます。

この例のおかげもあり、はじめは再帰関数なにそれ状態から最後はしっかりと実装できるようになりました。
再帰関数はPythonで実装していますが特に難しいことは書いていません。適宜自分の得意な言語に置き換えて読んでいただければ幸いです。

# 再帰関数を実装する前に
再帰関数を実装する前に再帰関数を用いる **理由** と **ルール** に関して知っておくと、理解が早く進むのではないかと思います。

再帰関数を用いる理由とルールに関しては「[独学プログラマー](https://www.amazon.co.jp/dp/4822292274/)」がわかりやすいので引用させていただきます。

まず、再帰関数を用いる理由に関してはこう説明されています。

> 再帰は、大きな問題を小さな問題に分割して解決する分割統治法で使われる手法で、
小さな問題は比較的楽に解決できるだろう、という点に着目しています。
（中略）
反復法で解決できるどんな問題も、再帰法に置き換えられます。
その上、再帰法はより洗練された解決法となることがあります。


そして、再帰のルールに関してです。

> 1. 再帰法は、再帰終了条件を持たなければならない。
2. 再帰法は、状態を変えながら再帰終了条件に進んでいかなければならない。
3. 再帰法は、再帰的に関数自身を呼び出さなければならない。


これで **なぜ再帰関数を使うと良いのか**、 **どのように再帰関数を実装すれば良いか** がなんとなく理解できたでしょうか。

それでは実際の再帰関数を紹介します。
実際の再帰関数の例を見るとより理解が捗るかと思います。

# 再帰関数の最もシンプルな例

```python3
def sum(n):
    if n <= 0:
        return n
    return n + sum(n-1)
```

こちらが再帰関数を勉強していて個人的に一番シンプルでわかりやすいと感じた再帰関数の例です。

名前があまり良くないですが1からnまでの自然数の和を返す関数です。

例えばn=10だった場合、sum関数の戻り値は、

```python
10 + sum(10-1)
```
sum(10-1) = sum(9)の戻り値は、

```python
9 + sum(9-1)
```
sum(9-1) = sum(8)の戻り値は、、、、、

のようにsum関数は自分自身を呼び出し続けます。

そして、n=0のとき、

```python
if n <= 0:
    return 0
```

0を返します。 `nが0以下` がこの再帰関数の再帰終了条件にあたります。

> １. 再帰法は、再帰終了条件を持たなければならない。

以上からsum(10)の返り値は、

```python
10 + 9 + 8 + ... + 1 + 0 = 55
```

となります。このように再帰関数は状態を変えながら関数自身を再帰的に呼び続けることがわかります。

> ２. 再帰法は、状態を変えながら再帰終了条件に進んでいかなければならない。
３. 再帰法は、再帰的に関数自身を呼び出さなければならない。


# おわりに
> 再帰は、プログラミング入門者が把握するにはかなり厳しいことで悪名高い概念の1つです。はじめは混乱するかもしれませんが、心配せずに練習を続けましょう。

by [独学プログラマー](https://www.amazon.co.jp/dp/4822292274/)

なぜ再帰関数を使うと良いか、どのように再帰関数を実装すれば良いかという理由とルールを把握した上でとにかく実装してみることが再帰関数を理解する近道になると思います。

今回ご紹介させていただいた例はかなりシンプルな問題であるため再帰関数である恩恵が少ないですが、より複雑な問題のときその本領は発揮されます。

[複雑なJSONから特定のデータを取り出す](http://qiita.com/JumpeiYoshimura/items/3b138d3ebbdaa873eaa5)

こちらの記事で「複雑なJSONから特定のデータを取り出す」という処理を再帰関数で実装しています。より実践的な内容になっているかと思いますのでよろしければ参考にしてみてください。
はじめてのGAS - はじめのはじめ。新しいプロジェクトを作る

# まえがき

Google Apps Script(GAS)プロジェクトを作成し、実行するまでの手順を説明します。
これからGASを始める人に何かの助けになればうれしいです。

# やり方

### 1. [Googleドライブ](https://drive.google.com/)にアクセスします。

![1.PNG](https://qiita-image-store.s3.amazonaws.com/0/87995/a6e63fcd-7cd7-bfec-be8e-453a244d0987.png)

### 2. Google Apps Scriptを起動 or 追加します

新規 → その他 と選択して、「Google Apps Script」があれば開きます。
ない場合は、「+アプリを追加」を選択

![2.PNG](https://qiita-image-store.s3.amazonaws.com/0/87995/3c0a823d-f580-11cb-3287-35b620a7d551.png)

### 3. Google Apps Scriptアプリを追加します。

アプリ追加のダイアログが開くので、右上の検索枠に「Google Apps Script」と入力してそのままEnter
タイトルが「Google Apps Script」提供が「google.com」のアプリが出てくるので、青の「接続」ボタンを押し案内に従って追加します。
追加が終わり緑のボタンに変わったのを確認して、ダイアログを閉じます（右上の×）

![3.PNG](https://qiita-image-store.s3.amazonaws.com/0/87995/0d7831ab-8ed7-3f62-03b4-93c4c4eb8652.png)

### 4. Google Apps Scriptを起動

もう一度、新規 → その他 を選択すると、Google Apps Scriptが追加されているので選択します。

![4.PNG](https://qiita-image-store.s3.amazonaws.com/0/87995/b3ac98cb-dfdf-bf74-5ef9-a36d975b6d51.png)

### 5. Google Apps Scriptのプロジェクト画面を確認

プロジェクトが開きました！
試しに、メッセージをログに出力するコードを書いてみます。

```javascript
function myFunction() {
  Logger.log('hello world!!');
}

function myname() {
  Logger.log('I am world.');
}
```

![5.PNG](https://qiita-image-store.s3.amazonaws.com/0/87995/fddaba0e-5d6d-8a1e-1e37-9356bb05d4af.png)


### 5. プロジェクトの保存

キーボードの`Ctrl` を押しながら `S` を押してプロジェクトを保存します。（以後同じような操作を、`Ctrl + S`のように表記します）
初回だけプロジェクト名の入力が必要です。
プロジェクト名は後から変えることもできるので、自分にわかりやすい名前でOKです。

![6.PNG](https://qiita-image-store.s3.amazonaws.com/0/87995/225c08d7-5609-32db-44dc-0615ecd01861.png)

### 6. 実行

セレクトボックスから、実行する関数名(myFunction)を選び、左にある三角のボタンを押して実行します。

![8.PNG](https://qiita-image-store.s3.amazonaws.com/0/87995/98c578fb-3546-e4b9-6acd-75b6f04fe730.png)

![9.PNG](https://qiita-image-store.s3.amazonaws.com/0/87995/6193eb8f-869c-ffee-9599-9d45f385e450.png)


### 7. ログの確認

キーボードの`Ctrl + Enter`を押してログの確認ダイアログを開きます。
hello world!! の文字が出力されているのを確認しましょう。

![7.PNG](https://qiita-image-store.s3.amazonaws.com/0/87995/ad266372-0d1f-cefc-d2fd-b23ee2a018b0.png)

### 8. 他の関数の実行

myname関数に切り替えて実行して、ログが変わっているのを確認してみてください。

![8.PNG](https://qiita-image-store.s3.amazonaws.com/0/87995/90323eb2-0b23-9c3a-78b3-a5ad44bd8a2e.png)


# 参考リンク

- [Class Logger](https://developers.google.com/apps-script/reference/base/logger)