OmniAICreator/Qiita-1.07M huggingface dataset:
iPadの充電が遅いのはなぜですか？


基本的に、充電が遅い問題の背後には様々の理由があります。それでは、始めましょう。

１、偽/レプリカの充電ケーブルやコネクタ：
レプリカの充電ケーブルやコネクタの使用をやめさせるためにユーザーに認識するためにアップルが講じる手順はたくさんあります。最近の市場では、特にそのような高価な電子機器を使用する場合に非常に危険な、さまざまな偽またはレプリカの充電ケーブルが存在します。このような偽の充電ケーブルとコネクタは、iPadの充電が非常に遅くなる理由になります。

２、アダプターの問題：
ご存知の通り、アップルはiPhoneデバイスには基本的な5W充電器を提供していますが、iPadの場合、iPadの箱からはiPadをより速く充電できる12W充電器が付属しています。充電速度に関しては、アダプターが重要な役割を占めています。
USB充電 vs コンセント充電：パソコンやノートパソコンからiPadデバイスを充電していますか？はい？パソコンやノートパソコンからの充電は、コンセントに接続して直接充電する場合と比べて、デバイスへの出力が少ないため、充電が完了するまでに時間がかかります。

３、バックグラウンドアプリ：
充電が遅い問題に関しては、バックグラウンドアプリも一つの理由である可能性があります。バックグラウンドで実行されているアプリは、知らないうちにかなりの量のバッテリーを消費します。専門家は、バッテリー消費の使用を制限することを常に推奨しています。
バッテリーの状態：iPhoneのバッテリーのおおよその状態を確認するには、「設定」を起動して「バッテリー」を選択します。バッテリーの状態のパーセンテージが80％未満の場合は、物理的にバッテリーの交換を検討してください。

充電が遅い問題の原因がわかったので、これらの問題を修正する解決策はこちらへ：
https://jp.imyfone.com/ipad-issuse/ipad-howto-charging-slow/
Wordpressでログイン画面を表示させる方法についての考察

#WordpressサイトのURLからログイン画面を表示させる方法
https://hogehoge.com/
上記のようなURLのサイトがあった場合、基本はURL末尾に
・/login/
・/admin/
・/wp-admin/
・/wp-login.php

を追加する様子
実際/wp-admin/を入力したところログイン画面を表示することに成功した。
しかしその他３点の入力は上手くいかなかった。

参考：
https://www.idcf.jp/rentalserver/support/knowledge/wordpress/basic_admin.html
https://kinsta.com/jp/blog/wordpress-login-url/

##上記４種の方法はどう使い分けているのか？
[WordPressのログインURLを変更する方法！プラグインを使ってセキュリティ対策を](https://www.conoha.jp/lets-wp/wp-loginurl/)
上記サイトが本件についてわかりやすかった。

##結論**セキュリティ対策**だった。
ログイン画面のURLはデフォルトでは
・/wp-admin/
・/wp-login.php
になっていて、変更せずに使用していると、WordpressサイトのURLが分かれば誰でも上記ログインURLを末尾に追加することで、サイトの管理画面のログイン画面までたどり着ける。
これではデータの改ざんなどの心配がある。

###Wordpressでサイトを作った場合はログインURLを変更しよう
プラグインをインストールすることで簡単にログインURLは変えられる。
こういったことの積み重ねがセキュリティ対策になると学びました。
Hello Magento2.4.x - 必要な環境について -

# はじめに

PHPとMySQL(MariaDB含む)は門外漢なのでメモしながら概要をおさえる。ほぼ公式ドキュメントの写し。

# プロダクトの種類

1. Magento Open Source ・・・ 無償版
1. Magento Commerce ・・・ Adobe提供の有償パッケージ
1. Magento Commerce on Cloud ・・・ Adobe提供のSaaS

# アーキテクチャ

## OS

### 必要メモリ

2GB以上、Swap推奨? ※ OS領域のぞいて2GBなのか、自信がない

### ディストリビューション

Linux 系をサポート、WindowsとMacOSはサポートしていない

1. RedHat Enterprise Linux (RHEL)
1. CentOS
1. Ubuntu
1. Debian

### 稼働に必要なコマンド

| コマンド | 備考 |
| --- | --- |
| bash | 確かに必要ですね。明確に記載するドキュメントが珍しい。 |
| gzip | GNUプロジェクトメンテのzipコマンド、メンテナーまで意識したことなかった。 | 
| lsof | コメントなし | 
| mysql | mariadbのときはmysqlコマンド? |
| mysqldump | mariadbのときはmysqlコマンド?  |
| nice |  実行時の優先度を変更するコマンド |
| php | コメントなし |
| sed | コメントなし |
| tar | コメントなし | 

## メールサーバ

SMTPが喋れるMTAがあればよい。sendmail・postfix等。

## アプリケーションサーバ

| プロダクト | 必須 | 必要バージョン | 備考 |
| ---- | --- | --- | --- | --- | 
| PHP| 〇 | 8.1 |  | 
| Composer | 〇 | 2.x | PHPのパッケージ管理、Javaで言うとMavenやGradle | 
| Elasticsearch | 〇 | 7.x | 全文検索に使用 |
| MariaDB | 〇 | 10.4 | MySQLも可能 | 
| RabbitMQ | - | 3.8.x | 他システム連携で使用、ERPやロジ系のシステムとの連携で利用 | 
| Redis | - | 6.0 | ページキャッシュ、DBキャッシュをしている? 要確認 |
| Varnish | - | 6.51 | CDNを用いる場合は不要、PHP界隈ではよく使われる? | 
| Nginx | 〇 | 1.x | PHP稼働用?、Apacheで代替可能 | 

# PHP Extention

自分のためのメインコンテンツ

| プロダクト | 備考 |
| ---- | --- |
| ext-bcmath | 任意精度数学関数 | 
| ext-ctype | 文字タイプチェック |
| ext-curl | phpからcurlを使う? HttpClient的なサムシングがない???| 
| ext-dom | 調査中 |
| ext-gd | PHPの画像処理ライブラリ（GD) |
| ext-hash | メッセージダイジェストを利用するための拡張 | 
| ext-iconv | MIME ヘッダフィールドと文字列Utils ???? | 
| ext-intl | PHP7では非推奨になっている |
| ext-mbstring | |
| ext-openssl | PHPでOpenSSLの有効化、Ngix(apache)でレイヤきれない? |
| ext-pdo_mysql | MySQLのツール? |
| ext-simplexml | 名前の通り |
| ext-soap | 名前の通り |
| ext-xsl | 名前の通り |
| ext-zip | 名前の通り |
| ext-sockets | 調査中 |
| php_xdebug 2.5.x | 開発環境にだけいれるのかな? |


# サポートブラウザ

Safariって、複数種類があるんですね...

1. Microsoft Edage, latet-1
1. Firefox latest, latest-1(any operation system)
1. Chrome latest, latest-1(any operation system)
1. Safari latest, latest-1(Mac OS only)
1. Safari Mobile for iPad 2, iPad Mini, iPad with Retina Display (iOS 12 or later), for desktop storefront
1. Safari Mobile for iPhone 6 or later; iOS 12 or later, for mobile storefront
1. Chrome for mobile latest–1 (Android 4 or later) for mobile storefront

# ドキュメント

[Adobe Magneto System requirements](https://devdocs.magento.com/guides/v2.4/install-gde/system-requirements.html)
[composerでlaravelを導入しようとして発生したエラー「ext-mbstring」「ext-dom」](https://qiita.com/yamauchi_k/items/63e38ded0eb8571fabfd)
docker-compose build api  でエラー



```mac:terminal
docker-compose build api 

 => CACHED [5/9] WORKDIR /app                                                                                                     0.0s
 => CACHED [6/9] COPY package*.json ./                                                                                            0.0s
 => ERROR [7/9] RUN yarn install                                                                                                  1.0s
------                                                                                                                                 
 > [7/9] RUN yarn install:
#12 1.027 /bin/sh: yarn: not found
------
executor failed running [/bin/sh -c yarn install]: exit code: 127
ERROR: Service 'api' failed to build
```

yarn installするけどbin/sh配下にyarnが見つかりませんと。


原因そもそものDockerfileが間違ってapiようではなく
front用であったため

```docker:api>Dockerfile
FROM ruby:2.7.1-alpine

ARG WORKDIR

ENV RUNTIME_PACKAGES="linux-headers libxml2-dev make gcc libc-dev nodejs tzdata postgresql-dev postgresql git" \
    DEV_PACKAGES="build-base curl-dev" \
    HOME=/${WORKDIR} \
    LANG=C.UTF-8 \
    TZ=Asia/Tokyo

# ENV test（このRUN命令は確認のためなので無くても良い）
RUN echo ${HOME}

WORKDIR ${HOME}

COPY Gemfile* ./

RUN apk update && \
    apk upgrade && \
    apk add --no-cache ${RUNTIME_PACKAGES} && \
    apk add --virtual build-dependencies --no-cache ${DEV_PACKAGES} && \
    bundle install -j4 && \
    apk del build-dependencies

COPY . .

CMD ["rails", "server", "-b", "0.0.0.0"]
```

以上
PowerShell で関数から要素数1の配列を返す

PowerShell では、要素数1の配列の取り扱いが結構トラップになります。
例えば、`ls` コマンドに対応する `Get-ChildItem` コマンドレットは通常ファイルやフォルダのオブジェクト(`DirectoryInfo`や`FileInfo`)の配列を返しますが、対象となるフォルダ以下にファイルが1つしかない場合は `FileInfo` オブジェクトがそのまま返ってきます。

https://qiita.com/akira6592/items/5d677577e5b0f781b3a3

こちらは自作した関数から配列を返す際も同様の動作をします。

## 動作例

以下のようなスクリプトで動作を確認します。
それぞれの関数ではまず配列オブジェクトを作成してから、要素を追加して返却しているため、いずれの結果も配列型が返ってくることが期待されます。

```powershell:single_element_array.ps1
function Get-SingleElementArrayWrong() {
    $result = @()
    $result += 'one'
    return $result
}
function Get-DoubleElementArray() {
    $result = @()
    $result += 'one'
    $result += 'two'
    return $result
}

$shouldBeSingleElementArray = Get-SingleElementArrayWrong
Write-Host "Result from Get-SingleElementArrayWrong: $($shouldBeSingleElementArray)"
Write-Host "Type of the result from Get-SingleElementArrayWrong: $($shouldBeSingleElementArray.GetType())"
$doubleElementArray = Get-DoubleElementArray
Write-Host "Result of Get-DoubleElementArray: $($doubleElementArray)"
Write-Host "Type of the result from Get-DoubleElementArray: $($doubleElementArray.GetType())"
```

上記スクリプトを実行した結果が以下の通りです。
なお、PowerShell は v7.1.0 を使用しています。

```
PS C:\Projects\PowerShellSandbox\SingleElementArray> .\single_element_array.ps1
Result from Get-SingleElementArrayWrong: one
Type of the result from Get-SingleElementArrayWrong: string
Result of Get-DoubleElementArray: one two
Type of the result from Get-DoubleElementArray: System.Object[]
```

＿人人人人人＿
＞　string　＜
￣Y^Y^Y^Y^Y^￣

## 回避策

以下2種の回避策があります。

- `@()` で囲う（上で引用した記事の手法）
- コンマ演算子を使う

### `@()` で囲う

関数の実装を変更せず対応できる方法です。
以下のように記述することで、要素数に関わらず配列を受け取れます。

```powershell
$withArrayNotation = @(Get-SingleElementArrayWrong)
Write-Host "Result of @(Get-SingleElementArrayWrong): $($withArrayNotation.GetType())"
```

結果は以下の通り。

```
Result of @(Get-SingleElementArrayWrong): one
Type of the result from @(Get-SingleElementArrayWrong): System.Object[]
```

### コンマ演算子を使う

以下の記事で紹介されている方法です。

https://blog.tyang.org/2011/02/24/powershell-functions-do-not-return-single-element-arrays/

[コンマ演算子](https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_operators?view=powershell-7.1#comma-operator-)は配列を作る演算子で、よく `$array = 1,2,3` のように使用されます。
これは単項演算子としても機能し、1要素の配列を生成します。
これを使って、以下のように return 部分の記述を修正します。

```powershell
function Get-SingleElementArrayCorrect() {
    $result = @()
    $result += 'one'
    return ,$result
}
```

結果は以下の通り。

```
Result from Get-SingleElementArrayCorrect: one
Type of the result from Get-SingleElementArrayCorrect: System.Object[]
```
VScodeにおいてjsonファイルを自動整形するための設定方法

VScodeにおいてjsonファイルを自動整形するための設定方法を紹介します。

## 設定をsettings.jsonに追加する

以下の内容をsettings.jsonに追加してください。

```jsonc
  // vscodeの設定で使われるjsonファイル用
  "[jsonc]": {
    "editor.defaultFormatter": "vscode.json-language-features"
  },
  // 一般的なjsonファイル用
  "[json]": {
    "editor.defaultFormatter": "vscode.json-language-features"
  }
```

これだけでjsonファイルは常に自動整形されるようになります。

## 参考文献
- [【Visual Studio Code】JSONを整形する方法](https://qiita.com/westhouse_k/items/60c6afdb8cf6bc417bd3)
シェルスクリプトで採点を簡単に

### 必要な環境
+ bash
+ gcc

## 実現したいこと 

先生目線で学生の提出した(.c)ファイルの採点を効率化したい。
.cファイルをコンパイルして一つ一つ実行していたら日が暮れそうなので、少し効率化出来ないかと考えた。

## 方法
1. 学生の提出したファイルを一括ダウンロード(省略)
1. コンパイルして実行しテキストファイルにリダイレクト
1. 正しい出力が得られるテキストファイル（模範解答）と`diff`をと
1. `diff`したものを再びリダイレクトする
1. `diff`ファイルのバイト数を調べて`0バイト`でないものを確認

少しややこしいので次のような問題を考える.

## 問題設定

```txt:問題
"Hello World"と改行を出力する.cファイルを作成しなさい。
ただし、"は出力せず、ファイル名は [学籍番号].c としなさい。
例えば学籍番号9999の人は 9999.c とする。
```

この問題の模範解答となる出力は当然`Hello World`である。

## 目標
例えば,`Hello World!!!`と出力してしまった学生を簡単に検出できるようにしたい。

## 準備

### 模範回答の準備

模範解答のソースコードとして次を準備する。

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

int main(void)
{
	printf("Hello World\n");
	return 0;
}
```

これをコンパイルした後に実行してテキストファイルにリダイレクトする。
これをシェルスクリプトにすると、

```bash
$ gcc main.c
$ ./a.out > ans.txt
```

実際に`ans.txt`の中身は

```bash
$ cat ans.txt
Hello World
```

となる。

また授業履修者のリストをテキストファイルにしたものを用意する。

仮に,学籍番号`1111`,`2222`,`3333`の3人が履修していて課題の提出が確認できていたとする。

```bash
$ cat id_list.txt
1111
2222
3333
```

これを元に繰り返し処理を行う。

##　フォルダ構成

フォルダ構成を次のようにして実行してみる。

```
$ tree -a
.
├── diff         # diffをとったファイルを格納するフォルダ
├── id_list.txt  # 履修者のリスト
├── main.c       # 模範回答を出力するためのソースコード 
├── make_diff.sh # 採点するためのシェルスクリプト
└── src          # 学生の提出したソースコードを格納するフォルダ
    ├── 1111.c 
    ├── 2222.c
    └── 3333.c
```

##　実行

`make_diff.sh`の中身を次のようにする。

```bash:make_diff.sh
gcc main.c
./a.out > ans.txt # 模範解答をリダイレクト

for id in `cat id_list.txt` # 履修者リストを元に繰り返し処理
do
	cd src
	gcc $id.c -o $id
	./$id > $id.txt
	rm $id
	cd ..
	diff ./ans.txt ./src/$id.txt > ./diff/diff_$id.txt # 模範解答とdiffを取る
done
```

これを

```
./make_diff.sh
```

で実行してみる。

権限設定で怒られることがある。

```
permission denied: ./make_diff.sh
```

その時は,ターミナルで一度だけ

```bash
$ chmod 700 make_diff.sh
```

と実行してからもう一度`./make_diff.sh`と実行してください。

正しく実行できている場合,実行後は次のようになります。

```txt:result
$ tree -a
.
├── a.out
├── ans.txt
├── diff  # 欲しかった結果
│   ├── diff_1111.txt
│   ├── diff_2222.txt
│   └── diff_3333.txt
├── id_list.txt
├── main.c
├── make_diff.sh
└── src
    ├── 1111.c
    ├── 1111.txt
    ├── 2222.c
    ├── 2222.txt
    ├── 3333.c
    └── 3333.txt

2 directories, 14 files
```

ここで,`diff`ディレクトリで`ls -l`とかすると各ファイルのバイト数が一気に見れる。

```bash
$ ls -l
total 8                       # ここ
-rw-r--r--  1 kkml4220  staff   0  4 23 16:17 diff_1111.txt
-rw-r--r--  1 kkml4220  staff  39  4 23 16:17 diff_2222.txt # この人の出力が誤り?
-rw-r--r--  1 kkml4220  staff   0  4 23 16:17 diff_3333.txt
```

実行環境によってバイト数を表すカラムの場所が違うかもしれないが... 明らかに0でない数字がわかる箇所がある。

となり、学籍番号2222の学生の出力が誤りであると予想できる。

実際に`cat`で中身を見てみると、

```bash
$ cat diff_2222.txt
1c1
< Hello World
---
> Hello World!!!
```

となっている.よって学籍番号2222の方が`Hello World!!!`と出力しているで誤りということがわかった。

## 感想

もっと効率化する方法はあるかもしれない。
というかこれはブラックボックステストでしかないため、出力しか見ていないという観点で問題がある。

なので、この方法の問題点を理解した上で実行する分には問題ないかと思う。

より良い方法があればコメントしていただけるとありがたいです。
SQLインジェクションの危険性とその対策について

<h2>SQLインジェクションとは</h2>
Webアプリケーションでは様々な情報をデータベースに保存して管理します。このデータベースを操作するための言語としてSQLが使用されます。
SQLインジェクションは悪意あるユーザがサイトに不正な内容を入力し、データベース上で意図しないSQL文が実行されてしまうことです。
このままではイマイチわかりにくいので次に具体例を紹介します。
<h2>SQLインジェクションの具体例</h2>
userテーブルの中から名前が'tarou'というレコード取得するとき以下のSQL文を作成します。

```sql
SELCT * FROM user WHERE name = 'tarou';
```

'tarou'の部分はユーザからの入力値とします。
名前の入力欄に『tarou』と入力されたためこのようなSQL文が作成されたわけです。
では悪意あるユーザが名前の入力欄に『' OR 'A'='A'--』と入力したらどうなるでしょうか？

```sql
SELCT * FROM user WHERE name = '' OR 'A'='A'--';
```

当然このようなSQL文が作られます。

<b>WHERE以降の条件をOR演算子で無理やり条件をTRUE(真)にすることで、なんとuserテーブルの全てのレコードを取得できてしまいます！</b>

これはまずいですね。
ちなみに--はコメントアウトで以降の文字はコメントとして扱われます。
最後のシングルクォートが邪魔なのでコメントで消しているというわけです。


<h2>SQLインジェクションの対策</h2>

ユーザIDとパスワードを受け取ってログイン処理を行うとします。

<b>まずダメな例ですがこのようなSQL文は絶対に書いてはいけません。</b>

```php
// ユーザが入力した値を直接SQL文に組み込んでいる
$sqlStr = "SELECT * FROM user WHERE id = '". $param["id"] ."' AND password = '". $param["password"] ."'";

$stmt = $db->prepare($sqlStr);
$stmt->execute(); // SQLを実行

```

ユーザが入力した値を文字列連結して直接SQLを組み立てていますが、これだとSQLインジェクションの標的になります。
悪い人がパスワードに『``' OR 'A'='A'--``』を入力すればログインされてしまいます。
ユーザが入力した値で直接SQLを組み立てることは絶対にしてはなりません。


ではどうしたら良いのかといいますと<b>プレースホルダ</b>を使用します。
プレースホルダを使用したSQL文は以下のようなコードです。

```php
// プレースホルダを利用
$sqlStr = "SELECT * FROM user WHERE id = ? AND password = ?";
```

ユーザの入力値が入る予定の場所に``?``が入っていることが確認できます。
この``?``がプレースホルダです。
プレースホルダによるSQL文の組み立てはパラメータ部分をこの``?``のような記号で示しておき、後からデータベース上で実際の値を機械的な処理で割り当てます。
プレースホルダを使用してSQLを実行するには以下のコードのようにします。

```php
// プレースホルダを利用
$sqlStr = "SELECT * FROM user WHERE id = ? AND password = ?";

$stmt = $db->prepare($sqlStr);
$stmt->execute(array($param["id"], $param["password"])); // 値の配列を渡してSQLを実行
```

この割り当てる処理を「バインドする」と呼び、プレースホルダのことを「プレースホルダ変数」と呼ぶことがあります。

ちなみにプレースホルダには<b>静的プレースホルダ</b>と<b>動的プレースホルダ</b>があります。
それぞれ以下の違いがあります。

<ul>
<li>
<b>静的プレースホルダ(プリペアドステートメント)</b><br>
一般的には静的プレースホルダがよく使われ、プリペアドステートメントと呼ばれます。
プレースホルダのままのSQL文をデータベース側にあらかじめ送信して、実行前にSQL文の構造解析などの準備をしておく方式です。<br>
SQL実行の段階で実際のパラメータの値をデータベースに送信し、データベース側がバインド処理します。<br>
<b>先にSQL文を確定させることで入力データによってSQL文が変更されません。</b>
</li>
<br>
<li>
<b>動的プレースホルダ</b><br>
動的プレースホルダは静的プレースホルダと違い値のバインド処理をウェブアプリケーションのライブラリ内で実装する方式です。<br>
</li>
</ul>

この記事で紹介しているのは<b>静的プレースホルダ</b>です。
動的プレースホルダはライブラリの実装に問題があるとSQLインジェクションを許してしまう可能性があるため、データベースが静的プレースホルダをサポートしているのであれば静的プレースホルダを使いましょう！
<b>静的プレースホルダはSQLを準備する段階でSQL文の構文が確定し、後から構文が変化することがないので安全です。</b>

<h2>【おまけ】SQLインジェクションの脆弱性を持っているかの判定方法(悪用厳禁)</h2>
判定方法としてサイトのSQLに組み込まれるであろう入力欄にシングルクォーテーション『``'``』を入力して送信します。もし脆弱性があるとデータベースエラーが起こります。

例えば名前の欄に『``'``』を入力するとこのようなSQL文ができると予想されます。

```sql
SELECT * FROM user WHERE id = ''';
```
SQL文は文字列をシングルクォーテーションで囲むので、もしプリペアドステートメントを使用していない脆弱性のあるサイトだと入力した『``'``』がSQL文として認識されます。
つまりSQL文として『``'``』が1つ余分になりSQLの構文が誤りになりデータベースエラーが発生します。
しかし脆弱性がないと文字列として認識されるため『``'``』という文字を入力しただけとして扱われデータベースエラーは起こりません。

<b>なお、当然ですが間違っても悪用はしないでください。</b>
【個人的備忘】CocoaPodsを使用してRealmSwiftをインポートする

## 1. CocoaPodsインストール
ターミナル起動
`sudo gem update —system`
※ruby gemアップデート
`sudo gem install cocoapods`
`pod setup`

## 2. プロジェクトにPodfile作成

※Xcode閉じておく
`cd プロジェクトのディレクトリ`
※例
cd Desktop/xxx
cd Desktop→ls→cd xxx
`pod init`
※Podfile作成

## 3. RealmSwiftインストール
`vim Podfile`
`i`
※編集モード(insert)
\# Pods for XXの下に
`pod 'RealmSwift'`

※ # platform :ios, '9.0'などは
適宜アンコメントして記載すると警告が出なくて良い。

`esc`
※編集モード終了
`:wq` もしくは(Shift+z)×2
※保存して終了
`pod install`

※`pod update`はPodfile.lockを無視してアップデートを行うコマンド、`pod install`はPodfile.lockを参照するため勝手にアップデートはされない、インストールを行うコマンド

## 4. インポート文
```
import RealmSwift
```


## 5. 備考
下記とほぼ同工程です。
すでにPodfileが存在する場合など、適宜1, 2は省略してください。

https://qiita.com/chukurimu1202/items/555f521bdf6faaa020f1
他所様のサーバとSFTP接続

#1.はじめに
外部NWのサーバに対してSFTP叩いてるだけの記事です。

#2.先に結論
良い感じのコマンドでサーバにSFTP接続が可能。
オプションで秘密鍵とポートを指定しています。ポートはいらないかも。

```
$ sftp -i ./id_rsa -oPort=22 ユーザ名@外部NWサーバのIP
```

#3.おまけの読み物
###3-1.接続要件
今回は以下のお題でSFTPすることが目的でした。

・接続先は外部NW（プロジェクト的に前例なし）
・キーペアはこちらが作ってお渡し
・自分が外部とヒアリングして得た情報じゃないのでなんか全体的にふんわりしてる

言い訳がましいですが我々エンジニア的にはあまりやりたくないシチュエーションですね。
なんか人柱になってる気がしましたが頑張って突き進みます。

###3-2.外部NWとの経路
AWSを普通に利用していれば、アウトバウンドのルールはだいたい制限かかってないと思います。
今回も｀0.0.0.0/0｀だったので特に何もしてません。
送信用のユーザも特に新しく作ってない。普段利用のユーザです。否root。

送信側サーバのグローバルは調べて外部NW側に教える。

```
$ curl globalip.me
XXX.XXX.XXX.XXX/32
```

もし制限があるなら相手のグローバルIPを聞いて22とかで追加してあげる感じですかね。

###3-2.キーペアの作成

こちらの記事が大変参考になりました。
この場を借りてお礼申し上げます！！

https://qiita.com/wnoguchi/items/a72a042bb8159c35d056

かっこよいリンクがURL貼るだけで表示されるようになったのですね。
Qiitaやるじゃないか！

今回は2048bitで作成。
SFTP接続の成功が最優先だったので、秘密鍵のパスワードは設定していません。
セキュアはちょっと横に置きました:pray:

```
$ ssh-keygen -t rsa -b 2048 -f ファイル名
```

###3-3.ふんわりした情報と戦う
経路は完成したと仮定したなら後は気合いで検証です。
結果的には冒頭に記したコマンドで通りました。

```
$ sftp -i ./id_rsa -oPort=22 ユーザ名@サーバのIP
```

ユーザ名とサーバのIPは相手からのご教示。
今回はワンライナーですが、恐らく.ssh/configを書いてあげても通ると思います。

#4.おわりに
・ユーザは相手側のサーバで作る
・キーペアがあればユーザとかのパスワードは不要

この知識があればもう少しサッと対応できたかと。
書くとくっそシンプルですが複雑な条件があるとまあ迷いますね。
SSHとかの20 - 22接続系はいつも利用する側ゆえゼロから作ったことがなく、この辺の理解も浅かった。

まあ知らないことがあっても突き進むエネルギーが一番重要！

記事は以上になります。
この内容がどなたかのお役に立てますと幸いです:relaxed:
ローカルのDocker環境で静的なHTMLにWordpressで作成した記事を表示する

静的なHTMLで実装されたコーポレートサイトで、一部Wordpressを埋め込みたいという要件があったためメモ。

#■ Wordpressのローカル環境構築
今回はDockerで環境構築しました。
（参考：https://goworkship.com/magazine/wordpress-docker/）

#■ 手順
1. WPの投稿にカテゴリ「ニュース」（スラッグ：news）を作成し、記事を作成

2. WPを埋め込みたいhtmlファイルの1行目に下記追加

```php
<?php require_once('../wp-blog-header.php'); ?>
```

3. ニュースを読み込みたい位置に下記を記述（表示項目とhtml構造は例）

```html
<?php
　$newslist = get_posts( array(
　　'category_name' => 'news', // 特定のカテゴリースラッグを指定
　　'posts_per_page' => 4, // 取得記事件数
　　'order'=> 'ASC' // 表示順
　));
　foreach( $newslist as $post ):
　setup_postdata( $post );
?>
<dt>
　<?php the_time('Y年n月j日'); ?>・・・<a href="<?php the_permalink(); ?>"> <?php the_title(); ?></a>
</dd>
<?php
　endforeach;
　wp_reset_postdata();
?>
```

4. index.htmlと同じ階層に.htaccessファイルを追加し、下記を記入

```html
AddType application/x-httpd-php .php .html
```

5. Dockerのコンテナ内にアップすると、表示を確認できる

#■ 備考
- メモ書きのため後ほどアップデート予定
【Mosaic HAT】PCにつなげてみよう

このボードはRaspberry Piの子基板の形態ですが、MicroUSBでPCと接続して使うこともできます。
今回はPCで遊んでみましょう。

＜ハードウェアのセットアップ＞
ボード上に、３ピンのポストが２か所あります。
＃アンテナ端子とUSB端子の横
それぞれ、”3V3”と隣のピンをショートさせます。

PCと接続すると、やや間を置いて(数秒)認識され、ドライバが入ったフォルダが開くので、
USB_driver_x_x_x_Installer.exeを実行し、ドライバをインストールします。
※バスパワーがいるので、認識しない場合はケーブルを交換してみてください。

フォルダが開かないときは、SeptentrioのサイトからRxToolsをインストールすると、
ドライバーもインストールされます。
https://www.septentrio.com/en/supportresources/software/rxtools
＃このRxToolsも、いろいろ役立ちそうですが、その話はまた後日。

ブラウザを立ち上げ、http://192.168.3.1　にアクセスするとseptentrioの管理画面が開きます。
アンテナが接続され、衛星が見える範囲にいると、上部Position覧に緯度経度高度が表示され、
下部GNSS覧に衛星との接続状況が表示されます。
Positionの数値部分をクリックすると、Google Mapが開き、現在地を示すこともできます。
Lat/Lonだけでは、正しい位置を示しているかわからないので、便利です。

今回はここまで。
次は、管理画面の設定でRTK測位に挑戦してみます。
Railsのlabelで"CSVファイル"が"Csvファイル"になってしまう対応

- Railsをさわっていると、2年に一回くらいこの問題を調べる気がするのでメモを残しておきます

## 結論

第3引数に表示したい名前わたす

## 現象

単純にlabelの第2引数に文字列を渡すとCamelCaseになってしまいます。

```
<%= label :user, 'CSVファイル' %>
```

```
<label for="user_csv">Csvファイル</label>
```

## 解決策

本当は、第3引数の文字列がテキストで、第2引数はメソッドの定義のよう。

```
<%= label :user, 'csv', 'CSVファイル' %>
```

```
<label for="user_csv">CSVファイル</label>
```

## 参考

```
label(object_name, method, content_or_options = nil, options = nil, &block)
```
https://www.rubydoc.info/docs/rails/4.1.7/ActionView%2FHelpers%2FFormHelper:label
phpMyAdmin で 2M 以上の sql ファイルをインポートする方法

phpMyAdmin でインポートできるファイルサイズは、デフォールトで 2MB です。
それ以上のファイルをインポートすると次のメッセージが出ます。
![phpmyadmin_import.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/dff68cc3-f225-c0ff-f69c-755257efb013.png)

```text
インポートするデータを受信できませんでした。ファイル名が送信されていないか、フ>ァイルサイズが PHP の設定で許可された最大値を超えています。FAQ 1.16 をご覧くださ
い。
```

Ubuntu 21.04 の Nginx での対処方法です。

PHP の設定

```text:/etc/php/7.4/fpm/php.ini
upload_max_filesize = 4M
```

Nginx の設定

```text:/etc/nginx/sites-available/default
server {

        client_max_body_size 20M;
        fastcgi_read_timeout 120;
```

サーバー再起動

```bash
sudo systemctl restart php7.4-fpm
sudo systemctl restart nginx
```
Fixtureの自動生成について

以前、CakePHP2の案件を担当した時に、Bakeの使い方やFixtureの生成方法等を調査した時のメモです。
TDDを対応する場合に、テストデータの作成が簡略化出来るので、参考までに。

* [Bakeでコード生成](http://book.cakephp.org/2.0/ja/console-and-shells/code-generation-with-bake.html)
* [CakePHPでもテスト　～手を抜くためにする遠回り～](http://y-stream.blogspot.jp/2013/08/cakephp-phpunit.html)
* [[CakePHP2]fixture作成の省力化](http://d.hatena.ne.jp/squeera/20120725/1343228242)
* [CakePHP – bakeコマンドを使って10分でタスク管理アプリを開発してみる](http://locombox.com/posts/88)
* [自動テストのfixtureを効率的に管理する方法](http://www.ryuzee.com/contents/blog/3414)
K8sで使うECRアクセス用のSecretを自動更新する

ECRのアクセストークンは12時間で切れてしまう。なのでdocker-registryタイプのsecretを作成しても12時間後には使えない。このsecretを自動更新する。ちょうどいい感じのhelmチャートがあったのでそれを使用する。使用するhelmチャートはこちらの[aws-ecr-credential](https://artifacthub.io/packages/helm/architectminds/aws-ecr-credential)です。

ちなみにHelmはv3を使用しています。

helmレポジトリを追加

``` sh
$ helm repo add architectminds https://architectminds.github.io/helm-charts/
```

valueを確認したいので以下コマンド

``` sh
$ helm show values architectminds/aws-ecr-credential
# targetNamespace is where the aws-registry secret will be created and maintained
targetNamespace: default

# aws.account is the aws account number of the ECR (string)
# aws.region is the aws region where the ECR exists
# aws.accessKeyId is the credential of a read-only user for the ECR
# aws.secretAccessKey is the credential of a read-only user for the ECR
aws:
  account: ""
  region: ""
  accessKeyId: ""        # base64
  secretAccessKey: ""    # base64

jobImage: architectminds/aws-kubectl
jobImageTag: 1.1
```

上記の通り、AWS関連のアカウントIDやIAMユーザのアクセスキーが必要になる。そのため、事前にECRアクセス用のIAMユーザを作成しておく。また、secretを置きたいnamespaceも必要なら指定する。なお、アクセスキーなどをbase64エンコードする時は以下の様に改行コードを入れない様に注意する。

``` sh
$ echo -n "hoge" | base64
```

valueを指定しつつ以下コマンドでチャートからマニフェストを生成

``` sh
$ helm install aws-ecr-credential architectminds/aws-ecr-credential \
  --set-string aws.account=<aws account nubmer> \
  --set aws.region=<aws region> \
  --set aws.accessKeyId=<base64> \
  --set aws.secretAccessKey=<base64> \
  --set targetNamespace=default \
  --dry-run --debug
```

表示されたマニフェストを適当な名前のマニフェストファイルに保存する。マニフェストにはCronJobとJobが含まれている。ここで、`DOCKER_REGISTRY_SERVER`の指定に`https://`が含まれてしまっているため`https://`を削除する。削除したらマニフェストを`kubectl apply`でデプロイする。

上記デプロイするとnamespace:`aws-ecr-credential-ns`にcronjob:`aws-ecr-credential-cron`が作成される。8時間おきにsecretを更新してくれる

``` sh
$ kubectl get cronjob -n aws-ecr-credential-ns
NAME                      SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
aws-ecr-credential-cron   * */8 * * *   False     0        <none>          31m
```

指定したnamespaesにsecret:`aws-registry`ができていることを確認

``` sh
$ kubectl get secret -n default | grep aws-registry
aws-registry                              kubernetes.io/dockerconfigjson        1      20m
```
プログラマーになって初めて知ったこと

プログラマーの同僚と雑談するとき、プログラマーの辛さを深刻に了解しました。

##1.高い給料が残業で換えたのです。
ペースが加速し、競争が激化しているため、プログラマーの残業は避けられません。中国のプログラマーがずっと残業している、996通勤時間は当たり前だと言う印象を残っています。
##2.ハイテクかと思いましたが、実は繰り返しだけです。
この業界は人の創造力を消耗します。技術が熟練すると、毎日コピーしたり、貼り付けたり、技術を高めるのがかなり制限されます。
##3.健康に気をつけてください。
いくら忙しくしてもたまにサボっても大丈夫です。自分の体は自分のものであり、自分の仕事は他人のものであることを覚えておく必要があります。これら2つの対立がある場合は、体の警告に注意を払い、倦怠感を無視しないでください。健康状態が悪く、座りがちで、蓄積された病気は、自分が稼いだものに値しないと感じさせます。
![hand-4566706_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482909/19b68450-03c4-fa7e-5f5e-4569fa7e4b0e.jpeg)
##4.Bugには終わりがない。
バグを修正している、またはバグを修正に行くプログラマーは常にいます。実際の作業では、アルゴリズムとの接触はほとんどなく、コード編集も少ないです。ほとんどの場合、他の人のコードの保守と修正です。
##5.ベテランでさえ検索エンジンに切り離さない
全てのコードを記憶して、検索せずにすっかり書きますベテランは極めて珍しいです。メモリはエンジンに任せ、主に習得しているのは、ブロックの調整、作成、構築です。ですから、問題を解決する優れた能力を持っている人は本物のベテランです。
また、一つ面白い言葉があり：確率の問題です、再現されないなら、問題ではない！

最後、皆さんに毎日もっとお金を稼ぐことを願っています！
cakephp3のEntityについて

最近使い始めたのでメモ

#Entityとは
https://book.cakephp.org/3/ja/orm/entities.html

個々のレコードに対して処理を加えるためのもの。
これを定義しているとある一つのレコードのカラム同士を組み合わせて作るデータとかをひとまとめに管理できる。

#実装のメリット
上記の通り、レコードに対して処理を行うのでその気になればこれがなくても欲しい情報を作れる。
（文字列連結とかで）

だが、それだともし変更があった際に修正箇所が散らばってしまう。
ということで変更点をひとまとめにできるのがメリットの一つ。

#実装方法
・Model/Entity/以下にEntityファイルを作成
・対応させたいModelの初期化時にこのファイルを読み込ませる
・取り出したレコードに対して特定のプロパティでアクセスする

##Model/Entity/以下にEntityファイルを作成
例えばarticlesテーブルのentityのファイル名は`Article.php`になる。
基本的にはテーブル名の単数形のキャメルケース。

説明のために、記事ページのURLをentityから取得する場合を考える。
仕様としては、
・URLは一律「 https://hoge.com/articles/ 」の末尾に記事IDを加えたもの。
・記事IDで一意にURLが決まるため、テーブルには記事IDしか保存されていない。
とする。

```Model/Entity/Article.php
<?php
namespace App\Model\Entity;

use Cake\ORM\Entity;

class Article extends Entity
{

    /**
     * 記事URLを取得
     *
     * @return string
     */
    protected function _getArticleUrl()
    {
        if (array_key_exists('id', $this->_properties)) {
            return "";
        }

        return "https://hoge.com/articles/{$this->_properties['id']}";
    }
}
```

ポイントとしては二点
・レコードのデータは`$this->_properties['カラム名']`に入ってくる
・nullや空文字のカラムは上記配列のキーにも存在しなくなる

なのでもしnullになる可能性があるなら`array_key_exists`で判定してやる必要がある。
（上記の例だと主キーなので不要だが説明のため記述した。）

##対応させたいModelの初期化時にこのファイルを読み込ませる
Model/Table/Articles.phpのinitializeに下記を記述

```Model/Table/Articles.php
$this->setEntityClass('App\Model\Entity\FsArticle');
```

##取り出したレコードに対して特定のプロパティでアクセスする
ここまでやればあとは普通にアクセスできるようになる。
プロパティ名はEntityのメソッド名によって決まり、上記の例だと

```php5
$result = $this->find()->where(['id' => 1])->first();

//$url1も$url2も同じ値
$url1 = $result->articleUrl;
$url2 = $result->article_url;
```

でアクセスできる。

#仮想プロパティーに関して
上記の場合、findで引っ張ってきたタイミングでは結果にarticle_urlが含まれない

```php5
$result = $this->find()->where(['id' => 1])->first();
debug($result); //これをしてもarticle_urlは確認できない。
```

これを嫌うなら、仮想プロパティを使えばfindした時点で宣言したプロパティが含まれるようになる。
やり方はEntityファイル内でprotectedの`$_virtual`変数を定義し、このリストに含めたいプロパティを記述する。
（命名規則は仮想プロパティを使わない場合と同様）

```Model/Entity/Article.php
<?php
namespace App\Model\Entity;

use Cake\ORM\Entity;

class Article extends Entity
{
    protected $_virtual = ['article_url'];
    /**
     * 記事URLを取得
     *
     * @return string
     */
    protected function _getArticleUrl()
    {
        if (array_key_exists('id', $this->_properties)) {
            return "";
        }

        return "https://hoge.com/articles/{$this->_properties['id']}";
    }
}
```

```php5
$result = $this->find()->where(['id' => 1])->first();
debug($result); //この時点でarticle_urlが確認できる。
```

#entity内のメソッドが走るタイミング
基本的には定義したプロパティにアクセスした時点でメソッドが実行されるため、仮想プロパティを使ってるかどうかで実行タイミングが変わる。
（仮想プロパティはfindの裏側で指定したプロパティにアクセスしているため。）
仮に中の処理でエラーが起きている場合、

```php5
//仮想プロパティを使っている場合
$result = $this->find()->where(['id' => 1])->first(); //ここでエラー
$url = $result->article_url;

//仮想プロパティを使っていない場合
$result = $this->find()->where(['id' => 1])->first();
$url = $result->article_url; //ここでエラー
```

となる。
Vue.jsで簡単なリアルタイム検索

##はじめに
商品の検索をリアルタイムで検索できるほうがやっぱりかっこいいよなと思い
どんな感じかを試しに実装。


<p class="codepen" data-height="405" data-theme-id="light" data-default-tab="js,result" data-user="rm5912" data-slug-hash="NWdEooG" style="height: 405px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Vue.js リアルタイム検索">
  <span>See the Pen <a href="https://codepen.io/rm5912/pen/NWdEooG">
  Vue.js リアルタイム検索</a> by morioka (<a href="https://codepen.io/rm5912">@rm5912</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

打ち込むごとに表示が切り替わります。
検索にはindexOfを使っています。

##感想
computedを使って
これだと大文字と小文字が区別されているので
そこは検索のときにいらないので改善しよう。
v-modelは気持ちいい。


>参考サイト
[コピペでOK！Vue.jsでリアルタイム検索をつくる方法]("https://blog.capilano-fw.com/?p=648")
[JavaScriptでindexOfメソッドを使って文字列を検索する方法【初心者向け】]("https://techacademy.jp/magazine/14759")
Installation of Mayavi2 on Ubuntu on WSL

Matplotlibの3次元グラフ機能に不満があったので，MatplotlibがおすすめしていたMayavi2というものをインストールしてみることにした

基本的なインストール方法はMayaviのホームページに書いてあった

https://mayavi.readthedocs.io/ja/latest/installation.html

```
python3 -m pip install mayavi
python3 -m pip install PyQt5
```

で，起動の確認は

```
mayavi2
```

できるらしいが，ここでエラー．

```
qt.qpa.xcb: could not connect to display
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, wayland-egl, wayland, wayland-xcomposite-egl, wayland-xcomposite-glx, webgl, xcb.

Aborted (core dumped)
```

[この方](https://qiita.com/nishiys/items/3b8c1670891f745c5a81)の言うように別のパッケージをaptでインストールしてみてもだめだった．
そこで[このページ](https://qiita.com/momomo_rimoto/items/83917d3f9f5dd35457e1)を参考に`export QT_DEBUG_PLUGINS=1`と環境変数[^1]を設定してからもう一度

[^1]: これは今だけ必要なだけで設定ファイルとかに書き込まない方がいい




```
mayavi2
```

とすると色々さらにうわーって出てから，後の方に

```
QLibraryPrivate::loadPlugin failed on "/<hogehoge>/libqxcb.so" : "Cannot load library /<hogehoge>/libqxcb.so
```

みたいなのが出ると思う．

ので以下のように依存関係の中でnot foundなものを探す

```
ldd /<hogehoge>/libqxcb.so | grep "not found"
```

ちなみに自分のPyQtのインストール方法では`<hogehoge>`の部分は
`~/.local/lib/python3.8/site-packages/PyQt5/Qt5/plugins/platforms/`であった．

これでnot foundなものを上から順に`apt install`してく．
not foundと表示されているのはライブラリ名`<fugafuga>.so`みたな名前だと思うが，それを参考に

```
sudo apt install <fugafuga>#ここでTABキーを押すと似た名前のパッケージリストが出る
```

パッケージリストのうち，インストールしたいライブラリに最も近い名前のものをインストールする．たぶんパッケージには`-dev`がついてるのとついてないのがあって，ついてなくてもいいけど，`-dev`つきなら全部はいってるはず．

https://unix.stackexchange.com/questions/338519/how-to-install-libxcb

たぶん上から4つくらいインストールすれば依存関係があるのが一緒にインストールされてくれて解決すると思う．

で，またmayaviの起動確認

```
mayavi2
```

とこんどは一瞬X11が開くがすぐに落ちてOpenGL系のエラー

```
Unable to find a valid OpenGL 3.2 or later implementation. Please update your video card driver to the latest version. If you are using Mesa please make sure you have version 11.2 or later and make sure your driver in Mesa supports OpenGL 3.2 such as llvmpipe or openswr. If you are on windows and using Microsoft remote desktop note that it only supports OpenGL 3.2 with nvidia quadro cards. You can use other remoting software such as nomachine to avoid this issue
```

これはX11側を再起動してWGL（Windows側のOpenGLを使用）をOFFにすれば解決

https://discourse.vtk.org/t/does-vtk-support-wsl/3661

もう一度mayaviの起動確認


```
mayavi2
```

x11のウィンドウがforgroundで開き，落ちない！
UITableViewの基礎

#■UITableViewとは
TODOリストなのでつかわれているもの
メモ帳のように
1行づつ文字を記入できる。

難しくなると色々できる。


#■UIViewcontrollerにtableviewを置くCellを置く

![スクリーンショット 2021-04-23 14.53.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1099804/743f0963-a098-2033-3383-6b8871e0eaef.png)

■cellを追加する
TableViewを選択して
こちらのPrototype cellsの数字を変えるとその分追加される。
![スクリーンショット 2021-04-23 14.53.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1099804/96d6fb30-b90d-8adb-37cd-4bdec8e26968.png)


#■TableViewのDelegateとDatasourceをUIViewControllerで使えるように

TableViewをcontrolをおしながら選択viewcontrollerに持っていく一番左の青色で囲まれてる奴
![スクリーンショット 2021-04-23 14.59.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1099804/c443c660-0568-d820-24a6-21171a5ad6ec.png)

■dataSourceとdelegateがでてるので順番にどっちも選択する。
![スクリーンショット 2021-04-23 15.01.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1099804/8b919199-1964-6bfb-9276-225574fdea47.png)


#■dataSourceのメソッドとdelegateメソッドを使う

#■datasourceメソッド
見た目を整える

``` swift
 //セルの数を決める.
 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
       
    }
 //セルに値を設定する。　  
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
       
    }
```
■cellForRowAtメソッドの中身
まずcellのidentifireにIDを与える.
cellはこのcellやでと紐づける。
let cell = tableView.dequeueReusableCell(withIdentifier: "cellのidentifire名", for: indexPath)


#■delegateメソッド

``` swift
　//セルを選択したら何かする。
 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
    }
```

#■よく使う引数indexPath.rowは行の数分になる。

numberOfRowsInSectionの返り値に
Array.count配列の数を与えたとしたら
indexPathはその行を指しrowは数を示す.

:注意:
indexPath.rowはインデックス番号を取得するので
配列の中身が10個の場合
indexPath.rowは10個文のインデックス番号を取得している。
0.1.2.3.4.5.6.7.8.9
の10個分のインデックス番号が入る。

#■tableView.reloadData()　画面上で更新したい時に使う

例：TODOリストでやる事を追加するときにtableView.reloadData()を使用して更新で追加される。
textFieldを使用してやる事を追加するパターン

``` swift
//このメソッドをButtonなり使いたい場所に記載する。
 func textAdd() {
        if textField.text != nil {
         //textを配列に追加
            self.textArray.append(textField.text ?? "")
　　　　　//tableviewを更新
            self.tableView.reloadData()
            textField.text = ""
        }
        textField.endEditing(true)
    }
```

#■cellをスワイプして消去
cellの消去ボタンが押された時の処理

``` swift
 func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == UITableViewCell.EditingStyle.delete {
            textArray.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: .fade)
        }
    }
```
git commitで前のコミットへ戻し、変更をなかったことにする方法

##〜過去へ戻りたいそんなあなたへ〜
・過去への想いがたまらないあなたへ、操作方法を紹介したいと思います。
・git commit 取り消し操作を間違えてしまった、必要だったコミットが履歴に見当たらなくなってしまうことがあります。

・なんだか全部もう何もかも嫌になって「あの頃からすべてやり直せたら」という気もちになる時、そんなときは「git　reflog」が便利です。git reflog はHEADを含む「参照」の移動をすべて記録しています。過去の好きなタイミングに帰ることができます。

##いまのブランチのすべてのコミット歴史を表示
・過去の行いが見れます。

```
git reflog
```

・デフォルトではHEADの移動をすべて表示します。

```
d1ef3b2 (HEAD -> 投稿返信#37, origin/change#32, change#32) HEAD@{0}: reset: moving to HEAD@{4}
1ae45e2 (origin/投稿返信#37) HEAD@{1}: commit: 投稿返信機能途中#37
d57a169 (origin/main, password-reset#35, main) HEAD@{2}: checkout: moving from main to 投稿返信#37
d57a169 (origin/main, password-reset#35, main) HEAD@{3}: pull origin main: Fast-forward
02399c6 HEAD@{4}: checkout: moving from change#32 to main
d1ef3b2 (HEAD -> 投稿返信#37, origin/change#32, change#32) HEAD@{5}: commit: 変更を取り消す
83fa867 HEAD@{6}: commit: 変更取り消し
deb3e70 HEAD@{7}: checkout: moving from main to change#32
02399c6 HEAD@{8}: reset: moving to 02399c6f3a6ecf39ca2dc0587a8078bb2518df6f
fa03150 (origin/images#34, images#34) HEAD@{9}: reset: moving to HEAD
```

・HEAD@{xx}というのは、過去何番目のHEADの状態ということですかね？
・元に戻したいポイントがわかれば、git reset --hard で強制的に巻き戻します。

```
// 指定のコミットに、ブランチ状態を強制上書き。全部取り消し。
git reset --hard HEAD@{4}
```

以上です。
Bcar Auto Center

"Bcar Auto Center chuyên cung cấp phục kiện xe ô tô, các dịch vụ chăm sóc xe ô tô, nâng cấp xe ô tô
Bcar Auto In Social
Name: bcarauto.org
Phone: 1800 92 54
☞ Google Map: https://bit.ly/3ndxFGB
☞ Twitter:  https://bit.ly/3cfRYiZ
☞ Flickr: https://bit.ly/3vfH3N0
☞ Youtube:  https://bit.ly/3sL0NGi
☞ Linkedin: https://bit.ly/3lLeWl3
☞ Facebook: https://bit.ly/3vej4xG"
クレジットカード決済用JavaScript準備③ 特定された入力フォームの中身を取得


```rb:
const pay = () => {
  Payjp.setPublicKey("pk_test_******************"); // PAY.JPテスト公開鍵
  const form = document.getElementById("charge-form");
  form.addEventListener("submit", (e) => {
    e.preventDefault();

    const formResult = document.getElementById("charge-form");
    const formData = new FormData(formResult);

    const card = {
      number: formData.get("order[number]"),
      cvc: formData.get("order[cvc]"),
      exp_month: formData.get("order[exp_month]"),
      exp_year: `20${formData.get("order[exp_year]")}`,
    };
  });
};

window.addEventListener("load", pay);
```




formData
-

FormData のコンストラクタに、form 要素の DOM オブジェクトを渡すと自動的にフォームの内容を取り込みます。

```rb
const f1 = document.getElementById('f1');
const fd = new FormData(f1);
```

![20210423-133205.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/703c038c-8c3e-b5d1-f07f-99c34a11effa.png)


>JavaScript 入門(TechAcademy)
>https://javascript.keicode.com/newjs/how-to-use-formdata.php


formData.get("order[number]")
-

formDataで取得したデータの中でget()で引数にキー名を渡すと、値を返します[umberをgetする]
order[number]はネーム属性値になります。


式の挿入
-

通常の文字列に式を埋め込むには、以下のような構文を使用していると思います。

```javascript
`文字列${        }文字列`
```

${  }の中に変数や式を入れルト展開してくれます。

`20${formData.get("order[exp_year]")}`,
はname属性order[exp_year]に入った値を取得してくれるので
例えば２１が入っていれば２０と２１なので
###２０２１というようなことになります
コールバック関数

名前のない関数は、そのままでは使えません。

使うためには
①変数に入れる
②オブジェクトのプロパティに入れる▶メソッド
③関数の引数に入れる▶コールバック関数
④すぐに使う▶即時関数
このどちらかになります。

```index.html
<div class="center">
      <div>
        <img src="images/Aくん.jpg" id="big">
      </div>
      <ul>
        <li><img src="images/bくん.jpg" class="img"></li>
        <li><img src="images/cくん.jpg" class="img"></li>
      </ul>
    </div>
```

```index.js
const img = document.querySelectorAll('img');
    img.forEach(function(item,index) {
      item.onclick = function() {
       document.getElementById('big').src =this.dataset.imag;
      }
    });

```

反復メソッドを使った処理

コールバック関数をとり、配列のすべての要素に対して処理を行うメソッドです。
コールバック関数は引数に要素、位置、配列そのものを取ります。
コールバック関数に渡される値は、メソッド実行時の値になります。そして、コールバック関数が呼ばれるのは、値が代入済みの要素のみになります。
forEach(f)▶配列の各要素をコールバック関数functionで処理します。


また今回、クリックされたときにサムネイルを変更したいと思います。
イベント処理のため、item．onclickからコールバック関数を作ります！

クリックするとエラーnet::ERR_FILE_NOT_FOUND
Image (async)
item.onclick @ image.html:30

改修続ける。
初投稿　ポートフォリオづくりにあたって

エラーやパッケージをインストールするにあたってqiitaにたくさんお世話にあったので
自分のアウトプット、他社貢献としてマメに記事を投稿しようと思う。
（もっと早くから始めればよかったです、、）

私はスクールを受講しPHPを主に学習してきました。
PHPの理由は、web業界に入るにあたってPHPのほうが求人数が多いということでした。

去年の11月から仕事をしながらややゆっくりなスピードで受講していました。
（仕事の拘束時間が９：００〜２０：３０もしくは２１：００くらいだったので、退職してから本格的に始める）

去年の12月末に退職し今年の1月から本格的な学習をはじめました。
３月頃に教材としていたテキストが終わり、一ヶ月ほどポートフォリオのベース作りになります。


#実装（予定の機能）#

<dl>アカウント登録機能
<dl>投稿機能
<dl>お気に入り機能
<dl>自己紹介作成機能
<dl>投稿一覧機能
<dl>登録ユーザー一覧機能
<dl>ユーザーごとの投稿を取得する機能
<dl>お気に入りした投稿を取得する機能
<dl>ページネーション機能
<dl>アカウント削除機能
<dl>登録したユーザーの経歴を追加する機能（予定）
<dl>javascript apiを使ってgoogle mapと投稿内容に記載した位置を繋げる（予定）

レッスンでは、PHPとlaravelがほとんどだったためフロント側をほとんどやっていないので
html,css,javascriptに力を入れようと思います。
Chromaticのtokenをenv経由で使用する。

## 事前
[Chromatic](https://www.chromatic.com/docs/#what-is-chromatic)はStorybookを共有するツール。
共有するツールというのは語弊がありそうな気がするが、共有もできるツール、というイメージ。

共有するので、プロジェクトを共有している相手と一緒に更新ができるように
tokenを直接package.jsonに登録するか聞かれる。

```
⚠ No 'chromatic' script found in your package.json
Would you like me to add it for you? [y/N] y

✔ Added script 'chromatic' to package.json
```

登録すると、下記のように追記される。

```
"scripts": {
  "chromatic": "npx chromatic --project-token 3u91u401"
}
```
`3u91u401`はサンプル。

```
ℹ No problem. You can add it to your package.json yourself like so:
"scripts": {
  "chromatic": "npx chromatic --project-token 3u91u401"
}
```

## 本題
①tokenをpackage.jsonに記述したくない場合には、下記のように記載する。

```
  "scripts": {
    "chromatic": "chromatic"
  },
```

②.envファイルを作成。

```.env
CHROMATIC_PROJECT_TOKEN=3u91u401
```

③実行
`yarn chromatic`

④実行結果サンプル

```
❯ yarn chromatic
yarn run v1.22.10
warning ../package.json: No license field
$ chromatic

Chromatic CLI v5.6.2
https://www.chromatic.com/docs/cli

  ✔ Authenticated with Chromatic
    → Using project token '********u401'
  ✔ Retrieved git information
    → Commit 'bd10a94' on branch 'main'; found 1 baseline commit
  ✔ Collected Storybook metadata
    → Storybook v6.2.8 for React; supported addons found: Actions, Backgrounds, Docs, Links, Viewp
ort
  ✔ Storybook built in 1 minute 25 seconds
    → View build log at /Users/xxxxx/Desktop/git/xxxxxxxxx/build-storybook.log
  ✔ Publish complete in 14 seconds
    → View your Storybook at https://xxxxxxxxxxxx.chromatic.com
  ✔ Started build 4
    → View build details at https://www.chromatic.com/build?appId=xxxxxxxxxx&number=
4
  ✔ Build 4 passed!
    → Took 30 snapshots (12 components, 30 stories) in 12 seconds; no changes found

ℹ Speed up Continuous Integration
Your project is linked to GitHub so Chromatic will report results there.
This means you can pass the --exit-once-uploaded flag to skip waiting for build results.
Read more here: https://www.chromatic.com/docs/cli#chromatic-options

✔ Build 4 passed!
No visual changes were found in this build.
ℹ View build details at https://www.chromatic.com/build?appId=xxxxxxxxxxxxxxxxxx&number=4

✨  Done in 119.44s.

```

### バージョン情報
```
    "@storybook/addon-actions": "^6.2.8",
    "@storybook/addon-essentials": "^6.2.8",
    "@storybook/addon-links": "^6.2.8",
    "@storybook/react": "^6.2.8",
    "chromatic": "^5.6.2",
```

### 参考
[chromatic config](https://www.chromatic.com/docs/cli#configuration)
vuexでdispatchするときにasync/awaitを利用しても待ってくれない場合[Firestore]

###説明

このような関数があったとします。Firestoreからでなくローカルのキャッシュ（IndexedDB）からデータを強制的に取るように命令するものです。実際の関数はもっと複雑でしたが簡略化させています。

```Javascript:store/firestore.js

export const actions = {
  getFromCache({ state, commit }, { coll, docID}) {
    let docRef = firebase
      .firestore()
      .collection(coll)
      .doc(docID);
      docRef
      .get({ source: "cache" })
      .then(doc => {
        //ゴニョゴニョ
      return true;
      }) 
//キャッシュが無い場合
      .catch(error => {
        console.log("no cache:", error);
        return false;
      });
  },
```
そこでこのactionを他のactionで呼ぶときにasync/awaitを使って処理が終わるまで待ちたいのです。（こんなかんじ↓）

```Javascript:store/firestore.js
async sampleFuncion(
    { state, commit, dispatch, rootState },
    { docID, something }
  ) {
    try {
      //...
      let cacheResult = await dispatch("getFromCache", {
        coll: "collName",
        docID: docID
      });
      console.log(cacheResult);
      if (cacheResult) {
        //...
      } else {
        //...
      }
      return true;
    } catch (e) {
      console.log(e);
      return false;
    }
  }

```

しかしdevtoolのconsoleを見ると期待通り待ってくれませんし、cacheResultもt/fではなくundefinedが返されます。
そこで以下のStackoverflowの質問を見つけました。
https://stackoverflow.com/questions/55700815/async-await-with-vuex-dispatch/55701084
どうやらFirestoreではget()するとPromiseを返すのでそれをreturnすれば待ってくれるらしいです。
なのでこう変えます↓

```Javascript:store/firestore.js
export const actions = {
  getFromCache({ state, commit }, { coll, docID}) {
    let docRef = firebase
      .firestore()
      .collection(coll)
      .doc(docID);
    return docRef //ここ変える
      .get({ source: "cache" })
      .then(doc => {

```
詳しい原理は正直わかりませんがとりあえずこれで行けました。
dockerのpostgresqlに直接接続する方法

dockerからpostgresqlに直接繋ぐ方法です。

コンテナ内に入ってpsqlコマンドを使うことができます。

##docker-compose ps (dbコンテナ把握)

```
$ docker-compose ps
         Name                       Command               State                 Ports              
---------------------------------------------------------------------------------------------------
my_project_mailhog_1     MailHog                          Up      1025/tcp, 0.0.0.0:18025->8025/tcp
my_project_memcached_1   docker-entrypoint.sh memcached   Up      11211/tcp                        
my_project_nginx_1       /docker-entrypoint.sh ngin ...   Up      0.0.0.0:10080->80/tcp            
my_project_php-fpm_1     docker-php-entrypoint php-fpm    Up      0.0.0.0:19000->9000/tcp          
my_project_postgres_1    docker-entrypoint.sh postg ...   Up      0.0.0.0:15432->5432/tcp          
```

postgres　っていうコンテナがありますね

#繋ぐ
```
$ docker-compose exec postgres /bin/bash
bash-5.0#
```

これで使えると思います〜

```
bash-5.0# psql --version
psql (PostgreSQL) 11.9
```

ま、環境によってできるできないあると思いますけど基本はこんな形でいけると思います
使ってるインフラの理解を深める　〜Amazon DynamoDB編〜

使っているサービスをエレベーターピッチにしてみることで説明できそうなのでやってみた

[ ニーズを満たしたりや課題を解決したり ]　したい
[ 対象顧客向け ] 向けの
[ プロダクト名 ] は
[ プロダクトのカテゴリー ] です
これは [ 重要な利点、大家にみある説得力のある理由 ] ができ
[ 代替手段 ] とは違って
[ 差別化の決定的な特徴 ] が備わっている

エレベータピッチについては下記を参照のこと

https://www.amazon.co.jp/exec/obidos/ASIN/4274068560/kab0e-22/

## Amazon DynamoDBとは
Amazon Web Serviceで提供されるNoSQLデータベース管理システムのこと 

###Amazon DynamoDB エレベータピッチ
[ NoSQLを気軽に運用 ]　したい
[ インフラエンジニア/フロントエンジニア ] 向けの
[ Amazon DynamoDB ] は
[ NoSQLデータベースマネジメントシステム ] です
これは [ 数ミリ秒台のレスポンス応答 ] ができ
[ 他のNoSQLデータベースマネジメントシステム ] とは違って
[ サーバー管理をアウトソースできる機能 ] が備わっている

###特徴
特徴的な機能として、以下の三つがあげられる

- `key-value`を持ち、拡張性が良い`NoSQLデータベース`
- リクエストに対する`レイテンシーが数ミリ秒台`で高速
- AWSのゴールデンパターンとして、`構築しやすい環境`が整っている

####Amazon DynamoDBのメリット

- NoSQLであるため、高速な処理が可能で広告やゲーム業界などで使用率が高い
- AWSのマネージドサービスであるため、サーバーの管理をアウトソースでき、高い可用性と信頼性を担保できる
- AWS Amplifyにより AWS AppSync -> Amazon DynamoDBの構築が容易に行える

https://aws.amazon.com/jp/amplify/


####Amazon DynamoDBのデメリット

- 同一パーティションーキーのデータが大量に存在するとパフォーマンス低下を招く
- RDBと異なり、`グローバルセカンダリインデックス`,`ローカルセカンダリインデックス`の個数が制限されているため表の結合に注意が必要


##補足
### パーティションーキー、ソートキーについて
DynamoDBではレコードを一意に特定するために`パーティションーキー`もしくは`パーティションキーとソートキー`を利用します。

データは下記の順で保存されます

- データはパーティションキー毎に`分散され`保存
- ソートキーがある場合はデータはパーティション内で`並べ替えられて`保存

下記記事にパーティションーキーやグローバルセカンダリインデックス,ローカルセカンダリインデックスが分かりやすく記載されています。

https://qiita.com/shibataka000/items/e3f3792201d6fcc397fd

###NoSQLについて

NoSQLは Not only SQL のことでRDBMS以外のデータベースを管理するシステムの`総称`である

NoSQLには大きく４種類ありAmazon DynamoDBはKey-Value Storeである

- Key-Value Store：主要製品 Redis , Riak
- Document Store:主要製品 MongoDB , CouchDB
- Columnar Database:主要製品 Cassandra , HBase
- Graph Database:主要製品 Neo4j

####RDBとの比較

RDBとNoSQLでは思想が大きく異なり、単純に賛否を定義することはできない
RDBではトランザクションの中で、`ずれを許容しない`特性があり
NoSQLではそのずれを許容する代わりに高速な応答`いつでも利用できる`特性がある。

#####RDBの特性（ACID特性）

- 原子性：全て実行したか、全て実行していないかどちらかを担保する
- 一貫性：開始、終了時に整合性を満たす
- 独立性：実行中に他からの操作を受け付けない
- 永続性：完了を返却した場合、永続的にデータへアクセスできる

#####NoSQLの特性（BASE特性）

- いつでも利用できる
- 常に整合性が保たれている必要はない
- 結果的に整合性が保証される
shopifyに無料で新着商品アイコン機能を追加

#はじめに

shopifyはウェブショップを運営する上で一通りの機能が網羅されていてとてもありがたいのですが、取り扱っている商材等によっては地味〜に欲しい機能がなかったりします。

[shopify app store](https://apps.shopify.com/collections/apps-for-japan?locale=ja&page=1)で目的にあったアプリを探すのもいいのですが、ちょっとした機能であれば自分で直接コードを編集して用意することができます。

## 今回やりたいこと
個人で運営している植物の販売サイトに新着商品を示すアイコンを用意したいと思います。

よく「NEW!」とかのバッジ等で表してるやつですね。もちろん商品リストを新着順で並び替えすることもできるのですが、それだけだといまいちリーチが弱い。やっぱり新着商品は視覚的に目立つようにしてあげたいところ。

また僕が扱っている植物という商材の場合は成長するので日々状態が変化します。なので現在の状態を伝えるために定期的に商品の写真と説明を更新しているのですが、それも商品リスト上でわかるようにしてあげたい。

ということで、商品リストと商品詳細画面に

* 登録日から一週間以内の商品には「新着」アイコン
* 更新日から一週間以内の商品には「更新」アイコン

を表示するようにしたいと思います。

# shopifyのカスタマイズ
shopifyは[Liquid](https://www.shopify.jp/blog/partner-shopify-template-language-liquid-overview)というテンプレートエンジンを使うことで自由に動的コンテンツをカスタマイズすることができます。
具体的なコード体系や使い方はそれに関する良コンテンツがたくさん公開されているのでここでは割愛！

※ チェックアウト画面のカスタマイズは「shopify Plus」でないとできないようです。


## 商品の登録日時と更新日時を取得

Shopifyの商品の情報を管理する[Productオブジェクト](https://shopify.dev/docs/themes/liquid/reference/objects/product)には二種類の日時プロパティがあるようです。

* created_at
* published_at

この`published_at`は、既に公開済み（アクティブ）の商品の内容（写真や説明文）を更新しても更新されなかったのですが、どうやら既にアクティブとしたものを一度下書きにしてから再度アクティブにすることでが更新されることがわかりました。これが使えそうです。

![スクリーンショット 2021-04-23 12.53.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/871869/6d52ce21-3ea6-ff9a-abcf-9855f3b571fa.png)

## コードの編集
実際にコードを編集していきます。
liquidファイルは採用したテーマによって構造が若干異なることがあるようですが、「Brooklyn」のテーマでコレクションをグリッドで表示している場合だと商品一覧は`Snipets/Snipets/product-grid-item.liquid`、商品詳細は`Sections/product-template.liquid`にありました。

```Snipets/Snipets/product-grid-item.liquid
{%- assign created_date = product.created_at | date: '%s' -%}
{%- assign published_date = product.published_at | date: '%s' -%}
{%- assign current_date = 'now' | date: '%s' -%}
{%- assign passed_days_from_create = current_date | minus: created_date | divided_by: 86400 -%}
{%- assign passed_days_from_publish = current_date | minus: published_date | divided_by: 86400 -%}

{%- if passed_days_from_create <= 7 -%}
<!-- 新着アイコン表示 -->
{%- elsif passed_days_from_publish <= 7 -%}
<!-- 更新アイコン表示 -->
{%- endif -%}
```

## 完成
![itemlist.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/871869/0b81c1cc-bf5c-e93a-d3c8-225ae752a207.png)

いい感じ。

# まとめ
Liquidを使うことによって簡単にshopifyに機能を追加することができました。
また暇を見つけていじってみたいと思います。
クロスサイトスクリプティング(XSS)の危険性とその対策について

<h2>クロスサイトスクリプティング(XSS)とは</h2>
一言で言うと脆弱性がある掲示板のようなウェブサイトに、悪意のある第三者がそこへ罠を仕掛け、サイト訪問者の個人情報を盗むなどの被害をもたらす攻撃です。
ある掲示板サイトがあったとして、そこに悪意を持ったユーザがJavaScript等で作成した不正なスクリプトを含んだリンクを投稿します。
もし掲示板に脆弱性があるとそのスクリプトが掲示板に埋め込まれ、他のユーザが投稿されたリンクをクリックしたりするとスクリプトが実行されてしまい以下のような被害が発生します。

<h2>スクリプトが実行されたときの具体的な被害について</h2>
<ul>
<li>本物のWebサイト上に偽のWebサイトが表示される</li>
<li>ブラウザが保存しているCookieを取得される</li>
<li>任意のCookieをブラウザに保存されられる</li>
</ul>

<h2>Webサイトの脆弱性のチェック方法(悪用厳禁)</h2>
HTMLのタグであるｈｒタグは知っていますか？
「hr」は「horizontal rule（水平方向の罫線）」の略で、水平の横線を引くためのタグです。
Webサイトのユーザが入力できる入力欄に&lt;hr&gt;のようなタグを投稿すると、もしユーザが入力した値に対してエスケープ処理していない脆弱性があるサイトだと『<hr>』
と投稿後このようにタグが長い横線に変換されます。
このようなサイトに&lt;script&gt;タグでJavaScriptを入力して送信するとそのスクリプトがサイト上で実行されてしまうためXSSの危険があります。
逆にちゃんとエスケープ処理しているサイトだときちんと&lt;hr&gt;として表示され、&lt;hr&gt;はタグではなく文字列として扱われます。
当然JavaScriptを投稿してもそれはただの文字列として扱われるのでスクリプトが実行されることはありません。

<h2>対策方法について</h2>
対策としてはユーザが入力して投稿する値は必ずエスケープ処理をすること。
PHPにはhtmlspecialcharsという便利な関数が用意されているので、それを使います。
使用方法は
``htmlspecialchars("エスケープしたい値", ENT_QUOTES, "UTF-8");``
です。
第2引数にENT_QUOTES を指定することで、ダブルクォートだけでなくシングルクォートも変換してくれます。
ユーザ名がPOST送信された場合は以下のようにします。


```php
$user_name = htmlspecialchars($_POST["name"], ENT_QUOTES, "UTF-8");
```

XSSを防ぐためにもユーザが送信した値は必ずこのようにエスケープ処理をしてください。
【備忘録】RASPIのイメージファイルの作成方法

# 準備
RaspiからmicroSDカードを取り出し、UbuntuのPCに接続

# パーティションを縮小
UbuntuのGpartedというアプリを使ってパーティションを圧縮する
ない場合は以下のコードでインストールする

```
sudo apt install gparted
```

gpartedを利用して、raspiのrootfs(2個目のパーティション)を縮小する
①を押しmicroSDカードを選択、②を右クリックしてリサイズ・移動を選択
最小サイズをもとに新しいサイズで縮小後のサイズを決めリサイズ移動を押す
③のチェックマーク（すべての操作を適用）を押す
![s_yamada_20210423.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1280725/0de9fb5a-810f-6020-15df-136a431b3207.png)

# イメージファイルの出力
以下のコマンドを押す．今回はsdbであったが，sda,sdcの場合もあるため，必要に応じて変える．

```
sudo fdisk –l /dev/sdb
```

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1280725/48cd8652-f84e-86cd-9085-9d278c6b9dc0.png)


赤丸の箇所が最終セクタ番号なので、以下のコマンドでディスクイメージを作成する．
<nm>は任意のファイル名．

```
sudo dd if=/dev/sdb of=~/<nm>.img count=29505536 bs=512
```

# RASPIのイメージファイルの焼き方
RASPIのイメージファイルを解凍する。
Raspberry Pi imagerを開く、ない場合は以下のリンクからインストールする。
https://www.raspberrypi.org/software/
choose OS -> Use custom ->　 RASPIのイメージファイルを選択
choose SD CARD -> イメージを焼くmicroSDカードを選択
WRITEを選択するとイメージファイルの書き込みが始まる（約10分かかった）

![s_yamada_20210423_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1280725/b1ce1aba-634b-caf5-7ae9-4cc20708416e.png)

焼いたmicroSDカードをraspiに差し込むだけ
圧縮したパーティションのサイズは自動的にmicroSDの最大サイズまで拡大される

以上．