OmniAICreator/Qiita-1.07M huggingface dataset:
初めて Hive を触ってみただけの記録

hadoop授業なう。Hiveを社内でも聞いたことがあるので試す。


ここに書いてあるまま。

https://hshirodkar.medium.com/apache-hive-on-docker-4d7280ac6f8e

それを git にあげときました

https://github.com/kujiy/docker-hive-hadoop



# setup
```Rb
git clone https://github.com/kujiy/docker-hive-hadoop

cd docker-hive-hadoop

docker-compose up

docker ps --format "{{.ID}}     {{.Names}}                      {{.Image}}                      {{.Ports}}"

e0b6a1e55ece    hive-server                     docker-hub-mirror.linecorp.com/bde2020/hive:2.3.2-postgresql-metastore                  0.0.0.0:10000->10000/tcp, 10002/tcp
6b77c2d26103    hive-metastore                  docker-hub-mirror.linecorp.com/bde2020/hive:2.3.2-postgresql-metastore                  10000/tcp, 0.0.0.0:9083->9083/tcp, 10002/tcp
5bd6f27a0977    hive-metastore-postgresql                       docker-hub-mirror.linecorp.com/bde2020/hive-metastore-postgresql:2.3.0                  5432/tcp
a1d6a26ff9d8    datanode                        docker-hub-mirror.linecorp.com/bde2020/hadoop-datanode:2.0.0-hadoop2.7.4-java8                  0.0.0.0:50075->50075/tcp
ca4a6e5d9b55    namenode                        docker-hub-mirror.linecorp.com/bde2020/hadoop-namenode:2.0.0-hadoop2.7.4-java8                  0.0.0.0:50070->50070/tcp


```


### hadoop dashboard

とりあえず hadoopが動いてることがわかる

http://localhost:50070/
http://localhost:50075/





# create DB table
```Rb
docker exec -it hive-server /bin/bash

root@dc86b2b9e566:/opt# ls
hadoop-2.7.4  hive

root@dc86b2b9e566:/opt# cd ..

root@dc86b2b9e566:/# ls
bin  boot  dev employee  entrypoint.sh  etc  hadoop-data  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

root@dc86b2b9e566:/# cd employee/

root@dc86b2b9e566:/employee# hive -f employee_table.hql

root@dc86b2b9e566:/employee# hadoop fs -put employee.csv hdfs://namenode:8020/user/hive/warehouse/testdb.db/employee

```


# DB Query
```Rb
root@df1ac619536c:/employee# hive

hive> show databases;
OK
default
testdb
Time taken: 2.363 seconds, Fetched: 2 row(s)

hive> use testdb;
OK
Time taken: 0.085 seconds

hive> select * from employee;
OK
1 Rudolf Bardin 30 cashier 100 New York 40000 5
2 Rob Trask 22 driver 100 New York 50000 4
3 Madie Nakamura 20 janitor 100 New York 30000 4
4 Alesha Huntley 40 cashier 101 Los Angeles 40000 10
5 Iva Moose 50 cashier 102 Phoenix 50000 20
Time taken: 4.237 seconds, Fetched: 5 row(s)

```

where, order by は普通に使えた。 select avg(age) もいけたけど、GROUP BY はエラー。なんかやり方があるんだろう

と思ったらimage nameに postgres って書いてた。何もわからん。


# persistence data

demoだとdocker downしてもdata消えないぜって言ってるけど、まぁdatanodeがvolumeされてるからそりゃそうだろ、くらいの感想しかなかった

```rb
docker-compose down
docker-compose up


docker exec -it hive-server /bin/bash

hive

hive> select * from testdb.employee;
```

これ、hiveとしては、dataがlocaldiskになくて、remoteでHDFSに通信して取ってるんだぜってことを言いたいんかな。たぶん、


感想



とりあえずなんとなく思ってること

HDFS がfile system. ファイルが保存される
hadoopはクラスターを作るモノ的な？ HDFSを分散させたりしてるんだと感じている

hadoop + HDFS はただの NAS 。（もちろんjarを走らせたりできるけど）

HIVEを使うと、MySQLみたいにqueryができるものと理解した。dataはたぶんHDFSの中に保存される。`/var/lib/mysql/` が分散配置される感じなのかな
Terrainの変な反射・テカリを消す方法

# はじめに
初めましてTRI(@Mit0ch0ndriaeve)といいます
いつのまにかTerrainでテクスチャを塗ったときに変なテカリが出るようになっていて、消す方法がわからなかったので対処法載せておきます。

![スクリーンショット 2022-09-11 231203.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1102473/f6997091-ea2e-aa39-c1d9-660e0f1eefef.png)
↑こういうの。テカリすぎィ

# 消すには
床のテクスチャのAlphaSourceをNoneに
![スクリーンショット 2022-09-11 230852.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1102473/ea582f43-eea9-472e-6716-e3f1eeaac079.png)

Window/Rendering/Lighting/EnvironmentにてEnvironmentReflectionsのSourceをCustomに
![スクリーンショット 2022-09-11 231106.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1102473/a0b78a6b-1618-63b4-a3cd-f4f9a7c8c734.png)

# 結果
![スクリーンショット 2022-09-11 231022.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1102473/9f4e2413-6d84-ecd6-6115-da84b91f0441.png)

たぶんマシになってるはず。あとはNormalMapで微調整しよう。なんでこんな仕様になったんだろうか
逆元と倍数判定

逆元を使うことで、与えられた数が特定の数の倍数かどうかを、1回の判定ごとに分岐や除算を使わずに判定することができます。

## 前提条件

以下では、特定のビット幅に収まる、符号なし整数の倍数判定を行います。

* 符号付き整数には応用可能ですが、煩雑となりますので割愛します。
* 無限に大きくなりうる値に対して適用することは不可能です。
* C言語の符号なし整数のような、「オーバーフローすれば黙って下位ビットを取り出す」環境なら実行がやりやすいですが、そうでない場合は下位ビットだけ取り出すようなマスクが必要となります。

つまり、倍数判定は $\mod 2^b$ の世界で行います（$b$はビット数です）。$0$ 以上 $2^b$ 未満である $x$ について、$d$ の倍数かを判定する、というように変数を置きます。また、$d$ は事前に決まっている前提です。

## 逆元とは

実数の演算で、$x$ に対して $1/x$ を「逆数」と呼びますが、それと同様に、$\mod 2^b$ の世界でも、ある数 $d$ に対して $d\overline{d} \equiv 1\pmod{2^b}$ となるような $\overline{d}$ を考えることができ、これを「逆元」と呼びます。

なお、逆元 $\overline{d}$ は、$d$ と $2^b$ が互いに素となる場合、つまり $d$ が奇数の場合のみ存在します。

## 奇数の場合

基本的なパターンである、$d$ が奇数の場合を先に考えます。この場合、逆元 $\overline{d}$ が存在して、もちろん奇数（$2^b$ とは互いに素）です。

$d$ の倍数である $x = kd$ を持ってきた場合、$ x\overline{d} = kd\overline{d} \equiv k\pmod{2^b}$ となり、$\mod 2^b$ の世界での $ x\overline{d}$ の演算結果は、$x$ を $d$ で割った商に一致します。

ここで、$\overline{d}$ と $2^b$ は互いに素なので、$0,\ \overline{d},\ 2\overline{d},\ \cdots\ (2^b-1)\overline{d}$ という $2^b$ 個の値は、$\mod 2^b$ の世界ですべて違う値（可能な $2^b$ 通りの値の全パターン）を取ります。

そのため、$d$ の倍数である $x$ について、$x\overline{d}$ は前述のように $0$ 以上 $(2^b-1)/d$ 以下の値を取るのに対して、$x$ が $d$ の倍数でない場合には残りの値である $(2^b-1)/d$ より大きなところとなります。これを利用して倍数の判別が可能です。

## 偶数の場合

$d$ が偶数の場合、2の冪を分けて $d = 2^sk$ （$k$ は奇数）としておきます。$k$ の$\mod 2^b$ の世界での逆元 $\overline{k}$ を用意して、$x\overline{k}$ を計算すれば、満たすべき条件は以下の2つです。

* 下位 $s$ ビットは全て0
* 全体が $(2^b-1)/k$ 以下

これを一気に評価するため、$x\overline{k}$ を $s$ ビットだけ右ローテートして、前者の条件を上位ビットで判定できるようにしておけば、「全体が $(2^b-1)/d$ 以下」という条件1つで片付くようになります。

## 逆元の算出方法

逆元があれば判定ができるようになったのはいいのですが、肝心の逆元はどうやって得ればいいのでしょうか。手早く済むのがニュートン法です。

初期値の $x_0$ を用意して、あとは $x_{n + 1} \equiv x_n(2 - dx_n)\pmod{2^b}$ を収束するまで繰り返すだけです。[こちら](https://math-koshimizu.hatenablog.jp/entry/2016/12/15/000000)にあるように、1ステップで正しい桁が2倍になっていくので、すぐ終わります。

初期値としては1でも構わないですが、奇数である任意の $x$ について $x^2 \equiv 1 \pmod{2^3}$ が成り立つので、$d$ をそのまま使うだけでも下位3ビットが正しい状態からのスタートとなり、1から始めるより計算を1ステップ以上減らせます。

## 参考文献

* ハッカーのたのしみ―本物のプログラマはいかにして問題を解くか オンデマンド版（ヘンリー・S. ウォーレン ジュニア著、エスアイビー・アクセス、2014年。ISBN 978-4-434-20159-2）§10-16 定数による除算後に剰余が0か調べる
!importantについて

## !importantとは

!importantとは、**CSSにおけるプロパティの優先順位を無視して、強制的に優先する命令**です。

```CSS:style.css
h1 {
    color: blue !important;
}
```
例えば、h1セレクタに対し!importantを使用する場合、他のCSSプロパティでh1のcolorプロパティを変更しようとしても、!importantを使用したプロパティを最優先にして使用することができる。

## セレクタの優先順位とは
1. テキストセレクタの優先順位は、セレクタ < class < id < style の順番
    ```html:index.html
    <div class="top" id="top" style="color:red;">サンプル</div>
    ```
    ```css:style.css
    div {
        color: yellow;
    }
    .top {
        color: green;
    }
    #top {
        color: blue;
    }
    ```
    上記の場合、colorはredが優先される。


2. 同じセレクタなら、後から書いた物が優先される
    ```css:style.css
    .top {
        color: red;
    }
    .top {
        color: blue;
    }
    ```
    上記の場合、blueが優先される。

## 参考にしたサイト
* [CSSの「!important」とは？CSSが適用されない時の対応方法](https://www.sejuku.net/blog/75524
)
Next.jsでpages配下のurlに紐づくファイルをindex.page.tsxにする方法

アプリが大規模になってくると、ファイルがかなり多くなってくるので、urlにひもづくファイルを一目で見分けたいときなんかに使える。

### 実装方法
とはいってもやることは簡単。

```next.config.js
/** @type {import('next').NextConfig} */
module.exports = {
  swcMinify: true,
  reactStrictMode: true,
  //pageExtensionsを追加
  pageExtensions: ['page.tsx', 'page.ts'],
};

```

あとは
```
_app.tsx → _app.page.tsx
index.tsx → indexs.page.tsx
```
などするだけ。

簡単な修正のだが、割と便利だと思う。
Dockerを使ってMariaDBを雑に起動する方法

以前、以下のような記事を書きました。

https://qiita.com/neko_the_shadow/items/c12d5968bf9c5b2b6d1e

Dockerを利用したDBMSの起動方法をまとめた記事なのですが、ここでMariaDBの起動方法が漏れていたので、この記事で補足して起きたいと思います。なおDBは`testdb`、ユーザは`testdb`、パスワードは`passw0rd`です。

```bash
docker run --rm -d \
  -p 3306:3306 \
  -e MARIADB_ROOT_PASSWORD=passw0rd \
  -e MARIADB_USER=testuser \
  -e MARIADB_PASSWORD=passw0rd  \
  -e MARIADB_DATABASE=testdb \
  mariadb:latest --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
```
Softbank Air で外部から自宅のパソコンなどへアクセスする方法

### 1. はじめに
Softbank AirはシェアードIPアドレスを使用しており双方向通信ができません。仕様にも「ポート開放やDMZの機能をご利用いただけません」と書かれています。これでは外出先のパソコンやスマホから自宅のサーバへアクセスできず不便です。
SoftetherVPNを使うことにより、自宅のパソコンへのアクセスが可能となります。

構成
インターネット---Softbank Air----VPN Server
　　　　　　　　　　　       　 　　+---自宅サーバ

### 2.必要ハードウエア
Nanopi NEO3　（NEO3以外でもOK）

### 3. VPNサーバの導入
下記からSofteter VPN Serverをダウンロードし、VPSサーバーへ手順に従いインストールする。
https://www.softether-download.com/ja.aspx?product=softether

### 4. SoftEther管理マネージャーの導入・設定
WindowsパソコンにSoftEther管理マネージャを下記からダウンロードしインストールする。
https://www.softether-download.com/ja.aspx?product=softether

SoftEther管理マネージャーを起動する。
「新しい接続設定」ボタン
　ホスト名：VPNサーバを導入したサーバのアドレス
　管理パスワード：（自分で決める）

接続設定名：（自分で決める）
　サーバーの種類：リモートアクセスVPNサーバー
　ホスト名：hoge.softetehr.net  （hogeのところを自分で決める）
  管理パスワード：（自分で決める）

作成できたら、「接続」ボタンでVPNサーバへ接続する。

仮想HUBを作成する
　仮想HUB名：（自分で決める）
　管理用パスワード；（自分で決める）

IPsec/L2TP/EtherIP/L2TP3サーバ機能の設定
　何も変更しない

VPN Azure サービスの設定
　有効

ユーザの作成
　　(ユーザID）/（パスワード）
認証方式：パスワード
　　ローカルブリッジ：
　　　名前：なんでもよい
　　　LANカード：eth0

### 5. リモート接続するPCの設定
コントロールパネル→ネットワークと共有センター
　新しい接続またはネットワークのセットアップ
　「職場に接続します」を選択
　「インターネット接続（VPN）」を選択
　　インターネットアドレス：(VPNサーバで設定したホスト名）
　　接続の名前：VPN接続　
　　ユーザ：（VPNサーバに設定したユーザID)
　　パスワード：（VPNサーバに設定したパスワード)
【EC2】DB作成時エラーのためにVimを使ってEC2内のファイルを編集

# エラー状況
railsによるアプリケーションの環境をdockerで構築し、以下のコードをEC2の中で実行し、データベースを作成しようとした。
```
docker-compose exec app rails db:create db:migrate RAILS_ENV=production
```
すると次のようにエラーが返ってくる。
```
/usr/local/bundle/gems/spring-4.0.0/lib/spring/application.rb:101:in `block in preload': Spring reloads, 
and therefore needs the application to have reloading enabled.
Please, set config.cache_classes to false in config/environments/production.rb.
 (RuntimeError)
```
要するにconfig/environments/production.rbに書かれてある、config.cache_classesの設定をfalseにしろやということなので言われた通りにしたいと思う。
ファイルの内容を編集するにあたって、EC2の中でVisual Studioなどのテキストエディタ（個人的にはAtom派です）を開くわけにもいかないので、コマンドラインで編集ができるVimを使っていく。
# Vim
Vimは古くからあるテキストエディタで、上述のように、コマンドラインを使ってファイルを編集するタイプのもの。何かの拍子でVimが開いてしまった時、その存在を知らない人はctrl+Cやexitを実行しても抜け出せない恐怖に焦ることになるだろう。早速触れていきたいと思う。
まず、ec2にログインし、```vim --version```を実行してみると、デフォルトでVim8.2がインストールされていることが分かる。
```
$ vim --version
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Jul 12 2022 21:26:30)
```
今回、編集したいファイルはアプリケーションの中のconfig/environments/production.rbなので、cdコマンドでアプリケーションのディレクトリに移動した上で以下を実行する。
```
vim config/environments/production.rb
```
vimが開き、ファイルの中身が表示される。ただしこの状態ではノーマルモードなので、編集はできない。まずは一旦、編集したい箇所にカーソルを合わせる。操作方法は「H」キーが左移動、「L」キーが右移動、「K」キーが上移動、「J」キーが下移動の操作になる。まあ、HとLはそれぞれキーボードの右と左に配置されているので分かりやすい。JとKについては「Jimenが下、Kamiが上」とでも覚えておく。
![スクリーンショット 2022-09-11 18.52.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2449886/a24a7863-aca0-fd39-008a-97ab0cf2a9b1.png)

編集したい箇所にカーソルを合わせたら、「I」キーを押す。これにより、インサートモードに切り替わり、編集を行えるようになる。今回は、エラーに書かれているように```config.cache_classes = true```の部分をfalseに変更する。
![スクリーンショット 2022-09-11 20.55.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2449886/cbf8e40a-1e15-a1c2-1dce-4216513c9ef5.png)
その後、escを押し、ノーマルモードに戻す。そして、```:wq!```と入力して保存・終了する。


ただし、現在のユーザーに編集の権限が与えられていない場合（写真のように読込専用で開いている場合）、```:wq```では保存・終了できない。
その場合は、```:w !sudo tee % > /dev/null```と入力してEnterを押す。質問が表示されるので最初の質問には「o」と入力しEnter。次にもう一度Enterを押す。これで編集内容の保存が完了する。
最後に```:q!```と入力しEnter。これでVimから抜け出すことができる。

改めて、最初のDB作成のコマンドを実行するとエラーは解消された。
buildifyとBlender-OSMを使って地図データから建物等を自動生成し、出力した物をneos(NeosVR)に読み込む

自分用の備忘録として残しておきます。
細かい操作は必要に応じて調べてください。


# 用意するもの
Blender 3.2以上
Buildify
https://paveloliva.gumroad.com/l/buildify
Blender-OSM
https://prochitecture.gumroad.com/l/blender-osm


# 解説動画
公式ページ内の動画か、下記の日本語動画を参照。

https://www.youtube.com/watch?v=prwmZkYOoXs&ab_channel=TheMovie%E3%80%903DCG%E8%A7%A3%E8%AA%AC%E3%80%91


# 手順

## アドオンの追加
Blenderを開いてプリファレンス>インストールを選択。
Blender-OSMからダウンロードした「blosm.zip」を選択。
「Directory to・・・」
の真下の箇所に好きなフォルダを設定する。(ダウンロードしてきた地図データの保存に使用するらしい)
![スクリーンショット 2022-09-11 212119.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/a2a8bc90-69c3-d949-c9f0-9f3689654d22.jpeg)

## 地図データの設定とモデルデータへの変換
画面右側あたりにあるメニューを開いて、Osmを選択すると画像のようなポップアップが出てくる。
![スクリーンショット 2022-09-11 212446.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/e7d51fae-c19e-c715-1840-32823cf6a4e6.jpeg)

selectボタンを押すとサイトがポップアップするので、
画像のようにマウス操作で取り込みたい地域まで移動・拡大させる。
![スクリーンショット 2022-09-11 212618.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/f3f2d8e5-d383-b1f6-deeb-6d52c2faa0eb.jpeg)

「Show selection rectangle」ボタンを押すと、画像のように暗転するので
取り込みたい範囲を調整して「Copy」ボタンを押す。
![スクリーンショット 2022-09-11 212905.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/aa5ad806-2b95-4096-46ce-c548ee4364fe.jpeg)

Blenderに戻ってPasteを押すとブラウザ上のCoordinatesの値が貼り付けられる。
貼り付けたら、その下の設定を画像のように変更する。
![スクリーンショット 2022-09-11 213151.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/ee9f6af4-5217-3660-feb9-759167b63fe0.jpeg)

次に[Geometry Nodes]の下のファイルに
Buildifyでダウンロードしてきた「buildify_1.0.blend」を指定する。
その真下の「名前」はbuildingに変更する。
![スクリーンショット 2022-09-11 213429.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/8e2d45e6-c8f8-d107-fbf4-db45cee6f533.jpeg)


importボタンを押すと地図データから自動的にモデルデータが読み込まれる。
![スクリーンショット 2022-09-11 213607.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/19b3c274-d167-12ee-d29f-5d573a0ea0c2.jpeg)


## ジオメトリーノードの編集

このままでは建物のデータが上手くFbxに出力されないため、少し手を加える。

Geometry Nodesタブを開き、「(自動生成された名前).osm_buildings」を選択。
![スクリーンショット 2022-09-11 213816.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/e0eda003-c2f9-6094-d4a3-76583f104128.jpeg)

ノードの画面を画像の箇所まで移動し、
「追加＞インスタンス＞インスタンスを実体化」を選択。
![スクリーンショット 2022-09-11 214017.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/2b4908f8-4ced-0f09-ca56-c6c4b51740aa.jpeg)

出てきたノードを下記のようにつなぎ変える。
繋ぎ変えたら、「(自動生成された名前).osm_buildings」の「ジオメトリノード」のモディファイアを適用する。
![スクリーンショット 2022-09-11 214140.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/ceaf6bc9-723a-0aa5-a21e-7215092f8999.jpeg)


## 出力
後は通常通りにFBXをエクスポート、neos(NeosVR)への読み込みを行えば
画像のようにマップのデータが読み込まれる。
ただし、衝突判定などはないのでそのあたりは自力での設定が必須となる。
![20220911205946_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2308792/7fad299a-5560-a8c4-b1b2-1bcc6e3902d0.jpeg)


以上。
Sample App of Flutter3 x MySQL8 with mysql_client  2

# select_pageを修正しました。　

　といっても、残念ながら懸案のListView化ではないのですが･･･。

[修正済みコードはこちら](https://github.com/dongri727/sample_app_flutter_mysql8)

[元の記事はこちら](https://qiita.com/dongri727/items/412b97eed4943006a0a0)



## 検索機能の強化　

　当初の設定ではcountryというcolumnについて、書き込んだ国名で絞り込む、という設定でした。　

　今回はどのcolumnについて絞り込むかを、複数、自由に記入でき、なおかつそれをand または or　で繋いでいます。変更箇所は次の通りです。　

```
 var result = await conn.execute(
        "SELECT * FROM timeline WHERE $targetColumn1 = '$searchTerm1' $logique $targetColumn2 = '$searchTerm2' ORDER BY year");
```

　例えば　
　
- targetColum1 を　country
- targetColum2 を　place
- logique を　and
- searchTerm1 を　Italy
- searchTerm2 を　Rome

　とすれば、イタリアの中でも、特にローマで起こった事件のみを選択できます。　
　また　

- targetColum1 を　country
- targetColum2 も　country
- logique を　or
- searchTerm1 を　Italy
- searchTerm2 を　Greece

　とすれば、イタリアかギリシアでの出来事が抽出されます。　

## 注意点　

　SELECT文全体を　" " でかこみ、$searchTermはさらにシングルクォートで囲みます。ただし、targetやlogiqueを囲むと、エラーになります。
　
## めざせListView
【Amazon Lightsail】LAMP環境構築チュートリアル②（DB編）

# 構築作業

[前回の①](https://qiita.com/LingmuSajun/items/76066a6ef43676041941)では、Webサーバの構築まで完了しました。ここからはDBを構築をしていきたいと思います。

## 1. MySQL接続

- [Amazon Lightsailのホーム画面](https://lightsail.aws.amazon.com/ls/webapp/home/instances)にアクセスし、「LAMP_TEST」インスタンスにSSH接続します。
![スクリーンショット 2022-09-11 20.05.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304307/6d600bca-9d93-f5f8-db3b-9f4da4c6406b.png)

- SSHクライアントのWindow上で下記コマンドを実行します。

```
$ cat $HOME/bitnami_application_password
$ （パスワードが表示されます）
$ mysql -u ユーザー -p'パスワード'
```

## 2. DB・テーブル作成

- SSHクライアントのWindow上で下記のSQLを実行します。

```SQL:dump_lamp_test.sql
BEGIN;

DROP DATABASE IF EXISTS `lamp_test`;

CREATE DATABASE lamp_test;

USE lamp_test;

DROP TABLE IF EXISTS `continents`;

CREATE TABLE `continents` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

INSERT INTO `continents` VALUES (1,'Asia'),(2,'Africa'),(3,'North America'),(4,'Europe'),(5,'South America'),(6,'Oceania'),(7,'Antarctic');

DROP TABLE IF EXISTS `countries`;

CREATE TABLE `countries` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `parent_id` int(11) NOT NULL,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;

INSERT INTO `countries` VALUES (1,1,'Japan'),(2,1,'China'),(3,1,'Vietnam'),(4,1,'Korea'),(5,2,'Kenya'),(6,2,'Tanzania'),(7,3,'America'),(8,3,'Canada'),(9,4,'Germany'),(10,4,'England'),(11,5,'Brazil'),(12,5,'Argentina'),(13,6,'Australia');

COMMIT;

SELECT countries.*, continents.name FROM countries INNER JOIN continents ON countries.parent_id = continents.id;
```

- 下記の通りテーブルの中身が表示されればOKです。

```
MariaDB [lamp_test]> SELECT countries.*, continents.name FROM countries INNER JOIN continents ON countries.parent_id = continents.id;
+----+-----------+-----------+---------------+
| id | parent_id | name      | name          |
+----+-----------+-----------+---------------+
|  1 |         1 | Japan     | Asia          |
|  2 |         1 | China     | Asia          |
|  3 |         1 | Vietnam   | Asia          |
|  4 |         1 | Korea     | Asia          |
|  5 |         2 | Kenya     | Africa        |
|  6 |         2 | Tanzania  | Africa        |
|  7 |         3 | America   | North America |
|  8 |         3 | Canada    | North America |
|  9 |         4 | Germany   | Europe        |
| 10 |         4 | England   | Europe        |
| 11 |         5 | Brazil    | South America |
| 12 |         5 | Argentina | South America |
| 13 |         6 | Australia | Oceania       |
+----+-----------+-----------+---------------+
13 rows in set (0.000 sec)
```
boston / iris の練習問題を供養する。

## 初めに
どうも、python歴6カ月で今年中に転職を夢見る者です。
以前からディープラーニング等の練習でbostonやirisのデータを扱い学習していたのですが、忘備録兼倉庫代わりにこの場を借りてシェア致します。
私の以前学習した内容が他の誰かの為になるならば何よりです。

## 本編
-  [iris分類問題。](https://github.com/Ken-huea/Time-series-analysis/blob/main/%E3%82%B1%E3%83%A9%E3%82%B9%E3%81%AE%E3%82%AF%E3%83%A9%E3%82%B9%E5%88%86%E9%A1%9E%E5%95%8F%E9%A1%8C_my_best.ipynb) 私自身が行ったものです。

- [iris分類問題。](https://github.com/Ken-huea/Time-series-analysis/blob/main/%E5%85%88%E7%94%9F%E3%81%AEiris%E5%88%86%E9%A1%9E.ipynb) 他の方の高精度なものをコピペして解釈したものです。

-  [Bostonの数値予測。まとめ。](https://github.com/Ken-huea/Time-series-analysis/blob/main/Deep_Learning%E6%95%B0%E5%80%A4%E4%BA%88%E6%B8%AC_My_Best.ipynb)
Kerasを用いたディープラーニングの数値予測問題でパラメータ等を調整し当時の私のベスト予測です。


## 終わりに
無事倉庫に眠っていたデータが皆様の目に触れる事で供養が出来ました。
因みにこの際にデータも確認し復習にもなりましたので。
ヘッドレスCMS Wordpress & Gatsby.js にてACF使用時の注意

# はじめに

Wordpressを構築する際にACF（Advanced Custom Fields）を使用する人は多いと思います。
Gatsby.jsと組み合わせてヘッドレスCMSにする場合、ACFが必須以外の場合には対応しないと空の時エラーになってしまいます。その解決方法です！


# 最初に

WordpressとGatsby.jsの組み合わせでのヘッドレスCMS化方法は他に書かれている方多いので、敢えて記述しません。


# やりたいこと

通常のWordPress構築する際に使用するACFを使用したい・・
入力値がない場合、Gatsby.js構築時にエラーになってしまうのを回避したい。


## エラー内容

>There was an error in your GraphQL query:
>Cannot query field "{acfの名前}" on type "{query名}".



# 結論

WordPressのfunctions.phpに以下を追記する。
以上です！！


```functions.php
function nullify_empty($value, $post_id, $field)
{
    if (empty($value)) {
        return null;
    }
  return $value;
}

add_filter('acf/format_value', 'nullify_empty', 10, 3);
```


参考サイト：

https://github.com/gatsbyjs/gatsby/issues/13931

https://github.com/gatsbyjs/gatsby/issues/4461
【C】初めてのC言語（17. 文字列リテラル）

# はじめに

* これまでの学習に続いて、今回は文字列の基本的なルールについて学んだ結果をまとめてみました。
  * [【C】初めてのC言語（1. Hello world）](https://qiita.com/nkojima/items/518c1a4ec06861d74b3c)
  * [【C】初めてのC言語（2. 四則演算とフォーマット指定子）](https://qiita.com/nkojima/items/36ea93b7296ce9e8a55b)
  * [【C】初めてのC言語（3. ポインタ）](https://qiita.com/nkojima/items/825bb9f931016faccd68)
  * [【C】初めてのC言語（4. 構造体）](https://qiita.com/nkojima/items/40a1101f2f6f5800bc2d)
  * [【C】初めてのC言語（5. 関数）](https://qiita.com/nkojima/items/1fa3317c04f25fe24276)
  * [【C】初めてのC言語（6. 配列）](https://qiita.com/nkojima/items/eda3ff6675b47e7ab5f0)
  * [【C】初めてのC言語（7. for文）](https://qiita.com/nkojima/items/a5659098f7e5275a96ec)
  * [【C】初めてのC言語（8. 2次元配列）](https://qiita.com/nkojima/items/f5eb25a4f8d1725faa89)
  * [【C】初めてのC言語（9. 関数のプロトタイプ宣言）](https://qiita.com/nkojima/items/57318d74bdfa670bf72e)
  * [【C】初めてのC言語（10. 構造体配列）](https://qiita.com/nkojima/items/75530a3ca63924a14397)
  * [【C】初めてのC言語（11. ヘッダファイル）](https://qiita.com/nkojima/items/a10cd943ed66e0cea7fd)
  * [【C】初めてのC言語（12. 3つのからくり構文＋ポインタ演算）](https://qiita.com/nkojima/items/83cb40ec01cd6a6e6a87)
  * [【C】初めてのC言語（13. メモリを扱う標準関数）](https://qiita.com/nkojima/items/13c8d942f282beb3c212)
  * [【C】初めてのC言語（14. ヒープの利用）](https://qiita.com/nkojima/items/837557cc86ce9697611a)
  * [【C】初めてのC言語（15. sizeofの注意点）](https://qiita.com/nkojima/items/6c9a3ba04c6348219578)
  * [【C】初めてのC言語（16. 文字列の基本）](https://qiita.com/nkojima/items/d87ce0cb15dd1a26f21a)

# 学習環境

* 今回は[paiza.io](https://paiza.io/ja/projects/new)のC言語のエディタを使いました。

# 文字列リテラルの機能

* ダブルクォーテーションで囲まれた文字列（文字列リテラル）は、自動的に末尾に「\0」を付ける処理が入っています。
  * ダブルクォーテーションを使わず、char型の配列として文字列を作る場合は終端文字として「\0」を入れます。
* 以下のコード中の3つの配列（str1～str3）は全く同じ内容の文字列（Hello）を表しています。

```c:Main.c
#include <stdio.h>

int main(void){
    const char str1[10] = "Hello";
    const char str2[10] = {'H', 'e', 'l', 'l', 'o', '\0'};
    const char str3[10] = {72, 101, 108, 108, 111, 0};
    
    printf("%s\n", str1);
    printf("%s\n", str2);
    printf("%s\n", str3);
    
    return 0;
}
```

```text:実行結果
Hello
Hello
Hello
```

# 文字列宣言でよくある誤り

* 以下のように、「n文字を格納するために用意する配列の要素数がn（＝nバイト）」だと、最後に「\0」を入れる要素が足りなくなってしまいます。

```c:Main.c
#include <stdio.h>

// よくある誤り
int main(void){
    const char str[5] = "Hello";  // 配列の要素数が「文字列の長さと等しい」と、終端文字を入れられない！
    printf("%s\n", str);
    return 0;
}
```

* そのため、次のように「配列の要素数を文字列の長さ（バイト数）＋1（＝n＋1バイト）」にする必要があります。

```c:Main.c
#include <stdio.h>

// 誤りを修正したコード
int main(void){
    const char str[6] = "Hello";  // 配列の要素数は「文字列の長さ（バイト数）＋1」
    printf("%s\n", str);
    return 0;
}
```

* あるいは要素数を省略して、`char 変数名[] = "初期値"`という形で宣言すれば、「\0」を含めた必要な要素数が自動的に確保されます。
* そのため、文字列宣言時のオーバーランを防ぐことができます。

```c:Main.c
#include <stdio.h>

int main(void){
    const char str[] = "Hello";
    printf("%s\n", str);
    return 0;
}
```

* 一方で、`char 変数名[] = "初期値"`という形で宣言して防げるのは「文字列宣言時のオーバーラン」だけなので、以下のように長い文字列で上書きするとオーバーランが発生してしまいます。
* そのため以下の例では、memcpyによるコピー先（※ここでは`str1`）で確保されているメモリ領域を確認しておく必要があります。

```c:Main.c
#include <stdio.h>

int main(void){
    char str1[] = "Hello";
    char str2[] = "Hello,world!";
    memcpy(str1, str2, 13);  // 長い文字列で上書きはNG
    return 0;
}
```

# 参考URL

* [スッキリわかるC言語入門 第2版](https://www.amazon.co.jp/dp/4295012785/)
  * p.403～p.405
Ectoで生のSQLを実行する（Elixir）

# はじめに

[Ecto](https://hexdocs.pm/ecto/Ecto.html)で生のSQLを実行してみたいとおもいます。
いつかそんな場面にでくわすことがあるかもしれません。

[Ecto.Adapters.SQL.query/4](https://hexdocs.pm/ecto_sql/Ecto.Adapters.SQL.html#query/4)のご紹介です。

`Users`テーブルから一覧を取得してみます。
この記事では、説明を簡単にするため、[Ecto](https://hexdocs.pm/ecto/Ecto.html)の構文でも簡単に書ける単純なものを例にします。

```mermaid
erDiagram
    Users {
        integer id
        string email
        string hashed_password
        datetime confirmed_at
        datetime inserted_at
        datetime updated_at
    }
```


以下、`Ezuka`はプロジェクトの名前です。



# ふつうに[Ecto](https://hexdocs.pm/ecto/Ecto.html)の構文で書く

```elixir
iex> Ezuka.Repo.all(Ezuka.Accounts.User)

[
  #Ezuka.Accounts.User<
    __meta__: #Ecto.Schema.Metadata<:loaded, "users">,
    confirmed_at: nil,
    email: "1",
    id: 1,
    inserted_at: ~N[2022-09-11 11:53:59],
    updated_at: ~N[2022-09-11 11:53:59],
    hashed_password: "...",
    ...
  >, 
  ...
]
```

# 生のSQLを実行する

```elixir
iex> query = "SELECT * from users;"
iex> {:ok, %{columns: columns, rows: rows}} = Ecto.Adapters.SQL.query(Ezuka.Repo, query)
iex> rows |> Enum.map(fn row -> Enum.zip(columns, row) |> Map.new() end)                  
[
  %{
    "confirmed_at" => nil,
    "email" => "1",
    "hashed_password" => "...",
    "id" => 1,
    "inserted_at" => ~N[2022-09-11 11:53:59.000000],
    "updated_at" => ~N[2022-09-11 11:53:59.000000]
  },
  ...
]
```

# おわりに

[Ecto](https://hexdocs.pm/ecto/Ecto.html)で生のSQLを実行してみました。

この記事の例は単純すぎるので、どこにも有り難みはありません。
たいていのものは、[Ecto](https://hexdocs.pm/ecto/Ecto.html)の構文で書けるのだとおもいますし、書けない場合にはどこかでテーブル設計を間違えている気がしないでもないですが、どうしても生のSQLを実行したいという場面が訪れるかもしれません。

[Ecto.Adapters.SQL.query/4](https://hexdocs.pm/ecto_sql/Ecto.Adapters.SQL.html#query/4)のご紹介でした。
将来はLINE botとGoogleSpreadsheetと社内SQLサーバーを連携したい


トラブルのときの対応方法をLINEに条件入力するだけで、過去にこんなことがことがあったよ
なんて返してくれたら現場は重宝すると思うんです。
社内にはSQLサーバーに詳しい方がいて、いろいろな可能性を生き生きと説明してくれます。
実際にその方が組んだSQLサーバーを使用していますが、ほしいデータがマッハにダウンロー
ドできてとても助かっています。これをどうにか現場の従業員が使える形になればいいと思
って今回Google Spreadb sheetを活用してみました。


:::note info
SQL Serverは正式名称「Microsoft SQL Server」と呼ばれます。
Microsoft SQL Server とは、マイクロソフトが開発しているリレーショナルデータベース管理システム (RDMS) です。
簡単にいうとマイクロソフトのデータベース製品となります。Windows環境でとても使いやすく、人気が高いです。
特徴としては「Microsoft SQL Server Management Studio」という管理ツールがあること。
そのためSQL Server の設定、管理、開発等をとても行いやすいです。
そしてクエリーを書くには、「T-SQL (Transact-SQL)」という SQL 言語を使用します。
:::
技術書典に初参加したら1時間で完売した話

### 良ければまずはこちらをご覧ください

https://qiita.com/choco_py3/items/2dc2204e651e8b592dc6

# 技術同人イベントに初参加した
上の記事に一通り書いてあるんですが、技術書典13という技術の同人イベントに初めてサークル参加しました。

https://twitter.com/choco_py3/status/1568782519428067329?s=20&t=lNmGcAJLhiKnZnybYEX1Lw

(なおワンオペのため、写真は心優しいお隣のサークルさんが撮ってくださいました)

# 部数の見積もり
今回一番難しかったのは何部印刷するかという問題です。
今まで、コミケやコミティアでオリジナルイラスト本頒布等の活動経験はあるのですが売れても十数冊とかだったので、30部刷れば程よく余るだろう、と考えていました。

事前にTwitterでアンケートを取ったところ、「オンラインで買う」が半数以上を占めていたため、結果を踏まえてもこんなもんだろう、と思っていました。

https://twitter.com/choco_py3/status/1562413867795628032?s=20&t=lNmGcAJLhiKnZnybYEX1Lw

# オフライン開催当日
お隣のサークルさんと雑談をしていたら、「何部用意したんですか？」という話になり
３０部ですと答えると「全然足りないと思いますよ、午前中で売り切れるんじゃないですか？」と言われてしまいました。

当の自分は間に受けず、そんなことはないだろうと呑気に構えていました。

# 結果
正確には午前を15分ほど過ぎてしまいましたが、開始（11時）から約1時間後に物理本が完売してしまいました。

# 会場（電子＋受注生産）という神
技術書典では**会場（電子＋受注生産）**という頒布形態があり、これはオンラインマーケットの**電子＋紙**と同様で、会場でこれを利用すると「後から印刷」を利用して後日まとまった部数を刷ることができます。
オフライン前日に保険のつもりで**会場（電子＋受注生産）** を設定していましたが、やっといて良かったです。。。

# まとめというか感想
見積もりって難しいよねって話でした。
オフライン会場には物理本を求めてやってくる方が多いと思うので、すぐにお渡しできなかったのは残念でした。次回参加の時はもっと余裕を持たせて刷りたいと思います。。

なお、技術書典が始まってからの2日間（つまりはオンライン含む）で頒布数は100を超えました！ありがたや。
とても熱量が高くて刺激的なイベントでした！まだ終わってないけど！！

もし良ければオンラインマーケットの方も覗いてみてください！

https://techbookfest.org/product/hMKMEetWAdaEGaGAmSt1u3?productVariantID=tUEvgrwy9nGWxBNFSV59uS
【Flutter】Health Kitで歩数を取得する(Android&iOS)

# 要件
FlutterのヘルスケアSDKを用いて、iOSまたはAndroidのユーザーの歩数を取得します。

# インストール
package:
https://pub.dev/packages/health
pubspec.yaml
```yaml
health: ^4.1.1
```

# セットアップ
## Apple Health (iOS)
1. info.plistに下記を追加
```plist
<key>NSHealthShareUsageDescription</key>
<string>We will sync your data with the Apple Health app to give you better insights</string>
<key>NSHealthUpdateUsageDescription</key>
<string>We will sync your data with the Apple Health app to give you better insights</string>
```
2.xcodeのtargetsのRunnerよりHealthKitのCapabilityを追加します

https://developer.apple.com/documentation/healthkit/setting_up_healthkit

## Google Fit (Android) 
- AndroidManifest.xml権限の追加
Android SDK 28 (Android 9.0) 以降は下記の権限追加は必要です。
```xml
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
```
運動距離が欲しい場合、さらに下記の権限が必要です。
```xml
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
```
- 歩数の場合、上記の権限だけでは足りません。特別に下記のパッケージを追加し、権限リクエストを追加します。
[permission_handler](https://pub.dev/packages/permission_handler)
```dart
await Permission.activityRecognition.request();
```
- Android Xの場合、android/gradle.propertiesに下記ものを追記します。
```properties
org.gradle.jvmargs=-Xmx1536M
android.enableJetifier=true
android.useAndroidX=true
```
- Google Cloudのセットアップ
    - APIの有効化
    アプリのGoogle Cloudのプロジェクタを作成した上で、APIを[有効化](https://console.developers.google.com/flows/enableapi?apiid=fitness)する
    - アプリの証明書情報を確認
    [SHA1証明書](https://developers.google.com/fit/android/get-api-key#find_your_apps_certificate_information)の作成方法ここでは紹介しないが、確認方法はリンク先のサイトを参照して確認する
    ※ストア証明書の作成方法は下記のコマンドにて作成する
    ```bash
    keytool -genkey -v -keystore release.jks -keyalg RSA -keysize 2048 -validity 10000 -alias release -storetype JKS
    ```
    -keystore release.jksはファイル名 -alias releaseはアリアス名

    - SHA1証明書を用いて、下記のリンクのサイトを参考し、OAuth2.0クライアントIDを作成
    [OAuth 2.0 クライアント ID](https://developers.google.com/fit/android/get-api-key#request_an_oauth_20_client_id_in_the)
    - 個人情報を取得しているため、OAuth同意画面の作成が必要
    Google Cloud Consoleの左側の画面から作成する
    ※公開すると、OAuth同意画面はGoogleへ審査してもらう必要がある
    OAuth同意画面審査について、ご参考できる記事のリンクを転記します。
    https://docs.sakai-sc.co.jp/article/programing/trial-google-api-ouath-verification.html

    <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2491433/14e04d3b-49b1-6c13-6e5c-16ab9c54db16.png"width=180>


# 使い方について
下記ページのExampleを確認してください。
https://pub.dev/packages/health
# トラブルシューティング
Androidで上記SHA1証明書はデバックmodeで生成した場合、証明書のPCしか機能しないです。その他の開発者にも使わせたい場合はkeystore証明書を使ってください。

# 参照

1. https://developers.google.com/fit/android/get-api-key

1. https://pub.dev/packages/health
【Unity】Source Generatorで自動生成されたコードをRiderで確認する方法

https://twitter.com/su10_dev/status/1568813610755051520?s=20&t=ONRhAM0xANufvQfyG8v3iQ

# はじめに
[UnitGenerator](https://github.com/Cysharp/UnitGenerator) を使ってみたらかなり体験が良かったのだけど、Rider上で自動生成されたソースコードを確認する方法がわかりにくかったのでやり方のメモ。

ちなみにVisual Studioの場合は以下のやり方でできるみたいです。

> Visual Studio を使用している場合は、ソースで生成されたファイルを確認できます。 [ソリューション エクスプローラー] ウィンドウで、[Dependencies]>[Analyzers]>[SourceGenerator]>[SourceGenerator.HelloSourceGenerator] を展開し、Program.g.cs ファイルをダブルクリックします。

<img src="https://docs.microsoft.com/ja-jp/dotnet/csharp/roslyn-sdk/media/source-generators/solution-explorer-program.png#lightbox">

https://docs.microsoft.com/ja-jp/dotnet/csharp/roslyn-sdk/source-generators-overview

# 方法１： `Go to Declaration or Usages` を使う

ソースジェネレータで生成されたメソッドなどに対して `Go to Declaration or Usages` を使用すると自動生成されたソースコードに飛べます。

![スクリーンショット 2022-09-11 20.39.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27863/331cbbd9-bf3f-6742-097d-09d15e15962a.png)

# 方法２： ソリューションエクスプローラーのSolutionビューから開く

実はVisual Studioとほぼ同じ方法で開けるのですが、UnityビューではなくてSolutionビューにする必要があります。

以下のスクリーンショットを参考に、生成されたソースコードを選択して開きます。

![スクリーンショット_2022_09_11_20_44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27863/0f0c27a3-661a-9879-d1a3-cb4f7e28b7c0.png)

# 参考リンク
https://neue.cc/2020/12/15_597.html

https://pleiades.io/help/rider/Project_Tool_Window.html
Atcoder解いてみた ABC 057 C - Digits in Multiplication

# ABC 057 C - Digits in Multiplication 解いてみた
問題は[こちら](https://atcoder.jp/contests/abc057/tasks/abc057_c)

## 回答
```C++
#include <iostream>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>

using namespace std;

int num_digit(long long x);
int F(long long a, long long b);

int main() {
	long long n;
	int a;
	long long b;

	int ans_f;

	cin >> n ;
	a = (long long)sqrt(n);
	long long min = 10000000000;

	for(int i=1; i <= a; i++) {
		if (n%i == 0) {
			b = n/i;
			ans_f = F(i,b);
			if(min > (long long) ans_f) min = ans_f;
		}
	}

	std::cout << min << std::endl;

}

int num_digit(long long x) {
	int count = 1;

	long long num = x;

	while (true)
	{
		num /= 10;
		if (num > 0) count++;
		else break;
	}

	return count;
}

int F(long long a, long long b) {

	int num_digit_a = num_digit(a);
	int num_digit_b = num_digit(b);
	
	if(num_digit_a > num_digit_b) return num_digit_a;
	if(num_digit_a < num_digit_b) return num_digit_b;
	else return num_digit_b;

}

```
app.json にAPI キーを書かねばならぬときに環境変数を利用して安全にgit pushしたい

# はじめに
調べてもなかなか答えに辿り着かなかったので書き残すことにしました。同じような悩みを持った誰かの一助になればと思います。

以下のように**Google Maps API** （[react-native-maps公式ドキュメント](https://docs.expo.dev/versions/latest/sdk/map-view/#deploying-to-a-standalone-app-on-android)）のAPIキーは「app.json」に書かなければなりません。
```json:app.json
{
  "expo": {
    "ios": {
      "config": {
        "googleMapsApiKey": [MY_API_KEY],
      },
}
```
でもこれじゃ怖くて、、、
```
$ git push
```
できない！
が事の発端です。

# react-native-dotenvを使って環境変数を設定
[react-native-dotenv公式ドキュメント](https://www.npmjs.com/package/react-native-dotenv)
まずはインストール。
```
$ npm install react-native-dotenv
```
ルート直下に「.env」を作成。環境変数を設定。
```.env
GOOGLE_API_KEY = [MY_API_KEY]
```
使い方は簡単。ただし、注意ポイントがあります。

```tsx:Screen.tsx
//react-native-dotenvから読み取るとエラーになるので注意！
import { GOOGLE_API_KEY } from "@env";

  <GooglePlacesAutocomplete
    query={{
          key: GOOGLE_API_KEY,
        }}
  />
    
```
環境変数の使用方法は分かりました。
ただ「app.json」はjsonファイルだから環境変数って使えなくない？
ここを乗り越えるために次の知識が必要になりました。

# app.jsonとapp.config.jsはマージされる！
[Expo公式ドキュメント](https://docs.expo.dev/workflow/configuration/#dynamic-configuration-with-appconfigjs)に記載があります。
つまり「app.json」にこだわる必要はない！

# app.config.jsなら環境変数を呼び出せる
ルート直下に「app.config.js」を作成。
```js:app.config.js
//注意！ こちらは「react-native-dotenv」から読み込む。
import { GOOGLE_API_KEY } from "react-native-dotenv";

export default ({ config }) => {
  return {
    ios: {
      config: {
        googleMapsApiKey: GOOGLE_API_KEY,
      },
    },
    ...config,
  };
};    
```
これで無事にマージされました。

もちろん「.gitignore」に以下を追加することを忘れずに。
```.gitignore
//追加
.env
```

# おまけ
もしもエラーが出た場合はキャッシュをクリアしてみてください。
```.gitignore
$ npx expo start -c
```
Gitの基本の「キ」 part2 gitクライアントとは？

# はじめに
エンジニアを志して皆さん勉強を始めていきますが、gitに関して知らない方、結構多い印象ですね。
わかってしまえば非常に便利なgitですが、概念が少し分かりづらいですよね。
いきなり触るとなった場合にも困る事がないよう、経験のない方向けにシリーズとしてまとめていこうと思います。

今回は[前回](https://qiita.com/YuukiYoshida/items/ed4f13e00312f53c2842)に続き、part2、gitクライアントについてご説明したいと思います。

# gitクライアントとは？
gitクライアントとは、一言でお伝えすると**gitを簡単に操作が可能なソフトウェア**の事を指します。
前回の記事でも述べましたが、gitは基本コマンドラインツールで操作をする事が多いので、操作に対してハードルが高い印象です。
そこで便利なのが、gitクライアントというわけです。

GUI(グラフィカルユーザーインターフェースの略、視覚的に操作可能なものを指す)で操作可能である事から、コマンドラインツールを普段使用しない方でも簡単にgit操作が可能になります。

また、gitクライアントは様々な種類があるので、基本的に現場で使用する際は皆さんそれぞれ好みに合ったもの使っている印象です。
私もこれまでに色々試していますので、その中からオススメなgitクライアントを以下3つほどご紹介したいと思います。

# オススメ１　SourceTree
https://www.sourcetreeapp.com/

オススメ１つ目は、SourceTreeです。
jiraやTrelloなどを運用しているatlassianが提供しているgitクライアントで、大体gitクライアント使用されている方はこちらを使っている方が多いんじゃないかと思います。

私もこちらのgitクライアントを長年使っていますが、後にご紹介するコミットや、プッシュ、タグ打ち、クローンなど非常にわかりやすく、総合的な使用しやすさという点ではこのツールが一押しかと思います。

デメリットとしては、atlassianのアカウントを作成する必要がある事と、動作が少々重い場合があるという点ですね。
上記を含めても使用しやすさという点が勝るので、迷ったらこちらを使ってみると良いと思います。

# オススメ2　GitHub Desktop
https://desktop.github.com/

オススメ2つ目は、前回ご紹介したGitHubが提供している、gitクライアントです。
こちらは比較的新しいgitクライアントですが、不動の人気を誇るGitHubが提供しているという事から、SourceTreeからこちらに移って使用される方も多い印象です。

私もこちらを一時期使っていた時期があったのですが、差分はご紹介のツールの中で一番見やすい印象ですね。
どちらかというとエンジニア向けな印象ですが、コミットやプッシュなどSourceTree同様に比較的わかりやすく、gitの基本操作はどなたでも問題なく使用できるかと思います。

# オススメ３ git fork
https://git-fork.com/

オススメ3つ目は、git forkです。
上記2つに比べると知名度は劣るものの、基本操作は問題なく可能で、何よりディレクトリの歴史が今回の3つの中で一番見やすい印象です。

また、rebaseというgit操作があるのですが、こちらに関しても随一の使用しやすさを誇っているのが、このツールですね。

※ちなみにこちらのツールは長期間利用する場合有料となるので、その点は注意いただければと思います。

# さいごに
gitクライアントは誰でも簡単にgitを使用する事が出来る素晴らしいツールです。
コマンドラインでの操作も便利な場合がありますが、gitを使い慣れていない方は是非gitクライアントの導入を検討してみると良いと思います。
SwiftUI Buttonタップ時にハイライトをさせないようにしたい

configuration.labelだけのButtonStyleを作り
```swift
struct NotHighlightButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
    }
}
```

buttonStyleに定義すればボタンタップ時にハイライトしないようにできる。
```swift
struct ContentView: View {
    var body: some View {
        Button {
            print("tap!")
        } label: {
            //~~省略
        }.buttonStyle(NotHighlightButtonStyle())
    }
}
```
終
Blender奮闘記②

# 初めに
前回Blenderにてyukiさんの動画を参考にクリームソーダを作りました。
今回は動画を置いといてもう一度クリームソーダを作成し、おさらいします。

# 前回からの変更点
今回はおさらいしつつ、以下の変更を加えます。
・メロンソーダからコーラに変更
・違うアイスクリームを2個載せる(片方はバニラ、片方はチョコ)
・サクランボのヘタの色を緑に変更する

# 結果
途中経過は前の記事を見ていただくとして、以下のようなものが作れました。
![作成結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782192/152f4da6-ec11-6c1c-e783-a351a08e95db.png)

前回はBlenderの使い方がわからず、ちょこちょこ戻して……と手探りで行っていました。結果的に前回は5時間くらい累計でかかってしまっていました。しかし、もう一度同じものを作るという工程であれ？っとなった個所は確認しましたが、基本的には自分でいじり、作成することができました。今回の作成時間は30分くらいでした。

# 終わりに
次は、これまでのことを活かした応用編を行います。
方向性は同じなのではないかと思います。

・ビールの入ったジョッキ

イメージ図![22974492.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782192/518a0203-b1ed-2cc3-6e86-467d9ad2b177.png)

理由は以下の通りです。
・炭酸飲料であること
・泡にシェーダーを使えそうなこと
・ジョッキグラスの作成はガラスの作成であること

以上の点からクリームソーダを作ろうの延長線上にあるものであると判断しました。
【シェルスクリプト】[y/n] で処理を分岐する方法

## デフォルトでYes
```sample.sh
#!/bin/bash

echo -n "実行しますか？ [Y/n]: "
read ANS

case $ANS in
  "" | [Yy]* )
    # 「Yes」の場合の処理
    ;;
  * )
    # 「No」の場合の処理
    ;;
esac
```

## デフォルトでNo

```sample.sh
#!/bin/bash

echo -n "実行しますか？ [y/N]: "
read ANS

case $ANS in
  [Yy]* )
    # 「Yes」の場合の処理
    ;;
  * )
    # 「No」の場合の処理
    ;;
esac
```

## 必ず入力させる
```sample.sh
#!/bin/bash

function ask_yes_no {
  while true; do
    echo -n "$* [y/n]: "
    read ANS
    case $ANS in
      [Yy]*)
        return 0
        ;;  
      [Nn]*)
        return 1
        ;;
      *)
        echo "yまたはnを入力してください"
        ;;
    esac
  done
}

if ask_yes_no "実行しますか？"; then
    # 「Yes」の場合の処理
else
    # 「No」の場合の処理
fi
```
TOEIC超超超頻出単語10選

## この記事について
これからTOEICの勉強を始める人必見！今から挙げる10個の単語（または組み合わせ）を見るだけで毎回確実にとれる問題が増えます．なぜならTOEICが大大大好きな単語だからです．
筆者自身は程々の点数（公式問8で8割位）なのであくまで素人であることにご理解ください。

## Keynote speaker（基調演説者）
これはリスニングでもリーディングでも出てくる超超超頻出単語です．この単語が出てきたら誰かが講演するんだなと考えましょう．また，リスニングとかで選択肢中の答えとしても出現するので知っとかないと損です．リーディングの長文中ではこの単語は結構目立つのでいいヤツですよ．

## Real estate companey（不動産会社）　と　property（物件）
これはTOEICが超大好きな単語です．知ってないと意味わからない単語だけど，知ってたらその問題の難易度が一気に下がります．Real estate(不動産)とproperty(物件)はよくセットになって問題として出ます．物件(property)の話が本文中にあり，選択肢中のReal estate companey がある問題の答えとなるパターンがしょっちゅうです．

## Human resources department（人事部）
TOEICは会社の話がほとんどなため，人事にまつわる話が盛んにおこなわれます．例えば，ある人がresign(辞職)したり,hire(雇用)されたりといったお知らせがいろんなパートで出てきます.もしこの言葉が出てきたらすぐに，人事が関わるな！と想像できます．ついでに単語帳のコラムとかに載っている他の部署名(Accountant:会計士　など)も覚えておきましょう．CEO(Chief Executive Officer):最高経営責任者とかはよく耳にすると思いますが，こんな感じである登場人物がどんな人なのかが把握できると強いです．

## Board meeting　もしくは　Board of director(取締役会)
役職にまつわる単語としてこれも知っておかないとキツイ単語だと思います．なんか重要な経営方針を決める会議とかが開かれる場面で登場します．単に boardとだけ出てくることもあるので，これをボード？板？とか想像すると文脈が破綻し始めます．

## Catering（ケータリング：イベント用のフードデリバリーサービス）
TOEICの世界ではよくパーティーが行われます．こんな時にケータリングサービスの登場です，特にパーティに食事が付くときはめっちゃ利用されます．ケータリング会社がそのパーティの食事の手配をするためにe-mailか何かであれこれやり取りします．この単語が目に入ったらそのような状況を想像しましょう．Cateringはパーティや食事，食べ物のような単語と密接に関わります．～社は何の会社？という感じで選択肢中の答えとしても出ます．

## Patron(ひいき客)
TOEICでの"大事なお客さん"や"長年のお付き合いのお客さん"はPatronと呼びます．そして，Patronには特別なサービスやお知らせがよく届きます．例えばe-mailで登場する場合,このe-mailの目的は何でしょう？と聞かれたら大体選択肢にdiscount(割引)と書かれている選択肢があり，それが正解みたいなパターンが多いです．

## Ceiling(天井)
Part1で必須の単語です．part1では屋内や建物のある屋外の写真について聞かれることが多いため，家やその周辺のパーツはぜひ覚えておきましょう．

## Press conference(記者会見)
Part3,4とかで，意外とPress conference(記者会見)も登場します．和製英語にはないので知らないと意味が分からないですが，逆に知っていれば一瞬でその会話の状況が理解できます．
Journalistもセット登場することが多いです．

## Repave(再塗装)
TOEICの世界では、移転や改修工事が盛んに行われます。その話題でなぜかRepave（再塗装）がキーワードや選択肢として登場します。その他、Relocate（移転する）などの関連ワードは抑えておきましょう。

## Landscaping company(造園会社)
ぱっと見意味わからない単語でこれが目立って出てきます。惑わされないようにしましょう。

## おわりに
TOEIC特有かつTOEIC単語帳のコラム的なところに出てきて意外と気づかないものにターゲットを絞って書いてみました。ご参考になれば幸いです。
【bashスクリプト実装】mysqlのデータベースを別なデータベースに複製する

centos7からalmalinuxへの移行の冒頭でも記載した通り、
mysqlを家計分析・可視化に活用するようになってきました。
しかし、今までデータベースを誤って破損させてしまったときの考慮をしていなかったので、
バックアップファイルを定期取得するようにしました。

やりたいこととしては、下記の2つです。
## ①データベース（maindb）のバックアップ用として、backupmaindbを作成・リストア

### mysqlデータベース複製スクリプト

<pre>[root@homeserver ~]# cat mysql_dump_getter.sh
#!/bin/bash

echo `date`_backups_mysql_process_was_doing >> /var/log/mysql_watcher.log
datearg=`date +%Y%m%d%H%M`
mysqldump -u root --password=`cat /root/.pgpassword_for_maindb` -h 127.0.0.1 --default-character-set=binary mysql > /var/lib/mysql/backups/${datearg}_mysql_dumpfiles
mysqldump -u root --password=`cat /root/.pgpassword_for_maindb` -h 127.0.0.1 --default-character-set=binary maindb > /var/lib/mysql/backups/${datearg}_maindb_dumpfiles
mysqldump -u root --password=`cat /root/.pgpassword_for_maindb` -h 127.0.0.1 --default-character-set=binary homeserver_wpdb > /var/lib/mysql/backups/${datearg}_homeserver_wpdb_dumpfiles
cp -pv /var/lib/mysql/backups/${datearg}_mysql_dumpfiles /root/backups/ >> /var/log/mysql_watcher.log
cp -pv /var/lib/mysql/backups/${datearg}_maindb_dumpfiles /root/backups/ >> /var/log/mysql_watcher.log
cp -pv /var/lib/mysql/backups/${datearg}_homeserver_wpdb_dumpfiles /root/backups/ >> /var/log/mysql_watcher.log
mysql -u root --password=`cat /root/.pgpassword_for_maindb` -h 127.0.0.1 --database=mysql -e "drop database backupmaindb;show databases;create database backupmaindb;show databases;"
mysql -u root --password=`cat /root/.pgpassword_for_maindb` -h 127.0.0.1 --default-character-set=binary backupmaindb < /var/lib/mysql/backups/${datearg}_maindb_dumpfiles

echo `date`_backups_files_remove_was_doing >> /var/log/mysql_watcher.log
ls -1t /var/lib/mysql/backups/*_dumpfiles | xargs rm -fv >> /var/log/mysql_watcher.log
ls -1t ./backups/*_dumpfiles | tail -n+10 | xargs rm -fv >> /var/log/mysql_watcher.log
echo `date`_backups_files_removewas_completed >> /var/log/mysql_watcher.log
echo `date`_backups_mysql_process_was_completed >> /var/log/mysql_watcher.log
[root@homeserver ~]#
</pre>
※pgpassword_for_maindbはmysql時のパスワード認証で、パスワードを入力する必要があるのですが、
パスワードをファイル内容に記載することでノーパスログインを実現します。
* リストアで、バイナリでダンプを取っているので、下記の通りbinary指定します。
mysql -u root --password=パスワード -h ホスト名かipアドレス --default-character-set=binary backupmaindb < バックアップしたダンプファイル

## ②ダンプファイルも管理するbashスクリプトを作成し、cronに組み込む。

### ダンプファイルの管理
バックアップをし続けるとたまってしまうため、定期的に削除するスクリプトを作成する必要があります。

### Cronの設定
は下記のとおりです。
```
[root@homeserver ~]# crontab -l 
[root@homeserver ~]# 
[root@homeserver ~]# crontab -e
※「*/15 * * * * /root/mysql_dump_getter.sh」を追記
[root@homeserver ~]# crontab -l 
*/15 * * * * /root/mysql_dump_getter.sh
[root@homeserver ~]#
```

## 後書
同様にpostgresqlも同じようなバックアップ、リストアができます。
FlatGeobuf でウェブ地図

[![nagasaki](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102082/b0463bf3-4356-cf07-3f25-a21007fb5619.jpeg)](https://optgeo.github.io/flat47-r2ka/?42#7.31/33.397/129.415)

小規模なベクトルタイルをウェブ地図に載せるには、FlatGeobuf を使うと気軽なのではないかという仮説を検証してみました。

- [Demo](https://optgeo.github.io/flat47-r2ka/?42#7.31/33.397/129.415)
- [Repository](https://github.com/optgeo/flat47-r2ka)

ベクトルタイルにするべき規模でもないデータを扱う場合であって、ベクトルタイルにすることについての技術的障壁が大きい場合には、FlatGeobuf と使うことも現実ではないかと思いました。
cscの作法 その271

# 概要
cscの作法、調べてみた。
UnhookWindowsHookEx使ってみた。

# 参考にしたページ

https://qiita.com/kob58im/items/835d86a262923da2b2b7

# コンパイル手順

```
>set PATH=C:\Windows\Microsoft.NET\Framework\v4.0.30319;%PATH%

>cd csc2


>csc ShortcutKeyboard.cs

```


以上。
【Github Actions】Githubの草を自動で生やす

# はじめに
今回は、Github Actionsを使い自動で草を生やす方法をご紹介します。

-  [Contributions calendar](https://docs.github.com/ja/account-and-profile/setting-up-and-managing-your-github-profile/managing-contribution-settings-on-your-profile/viewing-contributions-on-your-profile#contributions-calendar)
- [GitHub 芝生入門/芝生応用](https://qiita.com/sta/items/2c1f0252a6a9ce5e2087)

# 作業の流れ
- [リポジトリ作成](#リポジトリ作成)
- [ymlファイル作成](#ymlファイル作成)
- [環境変数の設定](#環境変数の設定)
- [actions実行](#actions実行)

## リポジトリ作成
Githubにリポジトリを作ります。
**Add a README file** にチェックを入れてください。
![スクリーンショット 2022-09-11 19.38.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520484/6ef33892-e90a-f9db-8b21-b11f8031a1a2.png)




## ymlファイル作成
リポジトリを作成したら **Actions** のページを開き、**set up a workflow yourself** をクリック。

![スクリーンショット 2022-09-11 19.48.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520484/2cd3ebff-f882-35a5-e388-cfcccd3161d9.png)


以下のコードを貼り付けます。

```
name: www

on:
  workflow_dispatch:

  schedule:
    - cron:  "0 0 * * *"

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: "Run a generate www"
        run: |
          git config --global user.email ${{ secrets.USER_EMAIL }}
          git config --global user.name ${{ secrets.USER_NAME }}
          echo "w" >> README.md
          git add README.md
          git commit -m '[add] www'
          git push origin main
```

コードを変更できたら **Start commit** & **Commit new file** をクリック

![スクリーンショット 2022-09-11 19.53.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520484/8c608548-b84d-76bd-c6bb-cf0f5bed254d.png)




## 環境変数の設定
次に、作成したymlファイルの環境変数 **USER_EMAIL** と **USER_NAME** を設定します。
**Settings > Cecrets > Actions** に移動。
- ```USER_EMAIL``` ：Githubに登録しているメールアドレス
- ```USER_NAME``` ：Github ID

![スクリーンショット 2022-09-11 19.56.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520484/0c64083f-7dc2-43f3-36a7-c93eb00c32c6.png)

設定するとこんな感じです。

![スクリーンショット 2022-09-11 19.57.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520484/18f9750a-bc1e-415a-549c-81683b683636.png)


## actions実行

次に **Actions** に移動し、**All workflows** の **www** を選択し、**Run workflow** をクリックします。

![スクリーンショット 2022-09-11 19.54.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520484/da1104c9-2556-8b34-ba26-68977073ff19.png)



Actionsが実行され、成功すると緑のチェックマークがつきます。

![スクリーンショット 2022-09-11 20.02.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520484/b6878e56-bfe9-eb92-1726-f3ab4aea2895.png)


README に「w」がひとつ追加されていれば完成です！！！！

# 参考文献
- [ワークフローをトリガーするイベント](https://docs.github.com/ja/actions/using-workflows/events-that-trigger-workflows)
- [GitHubActionsで定期実行](https://qiita.com/cardene/items/67d31f13d27865a12ecf)
- [githubに自動で草を生やそう](https://qiita.com/kaba/items/027715c056e7c9a4a559)
- [GitHubの草を自動栽培する](https://qiita.com/tanjo/items/ce2cfc3456dfaf937991)
- [【Gitub Actions】Githubの草を自動で生やす](https://qiita.com/takatoshiinaoka/items/3e48ca8c82c2ebc91f46)
【SwiftUI】 UITest触ってみる。

簡単なUITestの書き方メモです。

ボタン(Button)、テキストラベル(Text)、テキストフィールド(Textfield)、
それぞれの表示内容を取得してチェックする簡単なテストを作成しました。

（ちょっとmacOSでアプリ作ってみたい欲があるので、
プロジェクトはmacOS用で作成しています。
下記コードはiOS用でもほぼ同じ内容で動作すると思いますが）

## 開発環境
MacOS Monterey 12.2.1
Xcode Version 13.4.1
Swift Version 5

## テスト用の画面
```swift
import SwiftUI

struct ContentView: View {
  @State private var buttonTitle = "Hello"
  @State private var textEditTest = ""
  @State private var textEditTest2 = ""
  var body: some View {
    VStack {
      HStack {
        Text("TEXT_1:")
          .padding()
        Text(buttonTitle)
          .accessibility(identifier: "TestText")
          .padding()
      }
      HStack {
        Text("TEXT_2:")
          .padding()
        Text(textEditTest2)
          .accessibility(identifier: "TestText2")
          .padding()
      }
      TextField(
        "testTextField",
        text: $textEditTest
      )
        .accessibility(identifier: "TestTextField")
        .frame(width: 200)
      Button(buttonTitle) {
        // ボタンの表示を変更
        buttonTitle = "World"
        // textFieldの値をtextに設定
        textEditTest2 = textEditTest
      }
        .accessibility(identifier: "TestButton")
        .padding()
    }
    .frame(
      width: 600,
      height: 600)
  }
}
```

### 画面レイアウト
![スクリーンショット 2022-09-11 19.03.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126315/f21a55ff-352e-0187-6206-9a35a56c3af7.png)


## UITestsのコード(追加部分のみ抜粋)
```swift
  override func setUpWithError() throws {
      super.setUp()
      // とりあえずテストを最後まで流す。
      continueAfterFailure = true
      XCUIApplication().launch()
  }

  func testButton() throws {
    // UI tests must launch the application that they test.
    let app = XCUIApplication()
    let button = app.buttons["TestButton"]
    let text = app.staticTexts["TestText"]
    let text2 = app.staticTexts["TestText2"]
    let textfield = app.textFields["TestTextField"]
    // (1)
    // Textの表示内容はvalueで取る
    XCTAssertEqual(text.value as! String, "Hello")
    // (2)
    // Buttonの表示内容はtitleで取る
    XCTAssertEqual(button.title, "Hello")
    // (3)
    textfield.typeText("テスト")
    // (4)
    button.tap()
    // (5)
    XCTAssertEqual(button.title, "World")
    // (6)
    // TextFieldの入力内容はvalueで取る
    XCTAssertEqual(textfield.value as! String, text2.value as! String)
  }
```

## 注意点
ネットで調べた関連の記事では `.label`で値が取得できるとなっているものがあったり、
書き方がちょっと変わっていってるのかな、という印象です。
今後のアップデートの注視が必要そう。

## コード全文

コード全文は以下を参照ください。

https://github.com/yuta-yama-1123/TryUnitTest.git
【bashスクリプト実装】OSを安全にシャットダウンするスクリプト

## 背景
SQLのトランザクション処理、アプリケーション処理中に、
うっかりシャットダウンしたり再起動したりしてしまうことってあるかと思います。
ミドルウェアが強制停止すると次回起動時にデータ不整合が出るので、
誤って停止しないようにする必要が出てきます。
このため、プロセス確認をしてからシャットダウンするようなスクリプトがあると便利です。

## 実施内容
プロセス確認をしてからシャットダウンするようなスクリプトを作成しました。
* 暫定でループ回数を1000回
* 問題なければシャットダウンする

という作りとなっているので、必要であればカスタマイズするのもありかと思います。

## OS停止スクリプト
<pre>[root@homeserver ~]# cat os_safetyshutdown.sh
#!/bin/bash
res=1
dup=0
while true
do
   statusNumber=`ps -ef | grep sh | egrep -v 'grep|kworker|kdmflush|sshd|os_safetyshutdown|pts|-bash|emerg_metabase_reload|online' | wc -l`
   if [ ${statusNumber} = 0 ]; then
      #res=0
      dup=$(($dup+1))
      echo $dup
      if [ ${dup} = 1000 ]; then
         res=0
         break
      fi
   fi
   #sleep 1
done
if [ ${res} = 0 ]; then
   shutdown -h now
fi
[root@homeserver ~]#
</pre>

## OS再起動スクリプト
<pre>
[root@homeserver ~]# cat os_safetyreboot.sh
#!/bin/bash
res=1
dup=0
while true
do
   statusNumber=`ps -ef | grep sh | egrep -v 'grep|kworker|kdmflush|sshd|os_safetyshutdown|pts|emerg_metabase_reload|online' | wc -l`
   if [ ${statusNumber} = 0 ]; then
      #res=0
      dup=$(($dup+1))
      echo $dup
      if [ ${dup} = 1000 ]; then
         res=0
         break
      fi
   fi
   #sleep 1
done
if [ ${res} = 0 ]; then
   shutdown -r now
fi
[root@homeserver ~]#
</pre>