OmniAICreator/Qiita-1.07M huggingface dataset:
【UiPath】不要なリソースの削除

# はじめに

この投稿は **UiPathでワークフローを作る際に、不要になったもの削除する方法** について記載したものです。

意外と知らない人もいたので、展開します。

この投稿は「UiPathStudio：2020.10.3」バージョンを見て作成しています。
※ バージョンによっては、紹介する削除機能が機能が無いこともあります。

この投稿は、`UiPath Friends もくもく会 2021年1月開催 2021-01-23（土）08:45 - 12:00` で書きました。

https://uipath-friends.doorkeeper.jp/events/116284

# 不要な変数を削除

ほとんどの人が知っている機能です。

上部「デザイン」メニュータブの`未使用変数を削除`をクリックすると、ファイル内で使用していない変数が消えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/0030a888-7555-b4c4-8bb3-c67aedbf1021.png)

フローが完成したら、とりあえず全ファイルで押していきます。
不要な変数が消されたファイルは、ファイルタブに「＊」が付いて保存待ち状態になります。

# 不要なシーケンスを削除

これも、ほとんどの人が知っている機能です。

削除しても良いシーケンスがある場合、右クリックで`囲んでいるシーケンスを削除` をクリックすると、シーケンスが消えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/c0ae1a81-2baa-8282-9660-9e1db1279b17.png)

コードの可読性を高めるための「敢えて囲んだシーケンス」は残しますが、余計なシーケンスは見にくいだけなので消していきます。

# 不要なスクリーンショットを削除

ここから先は、意外と知らない人も出てくると思います。

プロジェクトメニューの `写真アイコン`をクリックすると、未使用のスクリーンショットファイルが「.screenshots」フォルダ消えます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/32a0377d-c79f-8b1d-f177-2e2e96019990.png)

削除されるとメッセージダイアログが表示されます。
他のプロジェクトをコピーして新規作成したり、セレクタの変更をしていると 意外と未使用のファイルが残っています。パブリッシュ後のnupkgファイルが異常に大きい場合は、未使用スクリーンショットが多いなんて可能性もあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/3ee90da9-397d-d111-b3ce-0c52ca401e27.png)

# 不要なインポートを削除

インポートタブの `不要なインポートを削除` でファイル内で使用していない 名前空間（ネームスペース）が削除されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/4bae38e9-aab2-1960-e13b-b351a6a11520.png)

.netで言う「未使用の参照を削除」です。削除するとインポートタブがスッキリしますが、今後使用したくなったら自分で追加する必要があります。不要なインポートを大量に追加することはあまり無いので、個人的にはやりません。（使いたい時にインポート追加する手間が面倒なので）

# 不要なパッケージの削除

プロジェクトツリーの依存関係でパッケージを選択して右クリックで`依存関係を削除`をクリックで、使用していないパッケージを削除できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/fdda091a-129d-b330-075f-61e50fd5e11d.png)

削除されると、プロジェクト全体を再読み込みし、画面がリロードします。
他のプロジェクトをコピーして新規作成した場合に、余計なパッケージが残っていることがあります。
パッケージが多いと「初回起動時にパッケージ復元で時間が掛かる」ので消したほうが良いですが、これも「後で追加するのが面倒」なので「絶対不要なもの」だけ消します。

# 不要なxamlの削除

この機能はUiPathStudioにはありません。たぶん。
ファイルGrepして、参照していないファイルを見つけ出す必要があります。

エディタインストール禁止の悲しいPCなどもあるので、そんなときは個人的に作成したツールで実施します。 [UiPath マーケットプレイス：Remove Unused Xaml](https://marketplace.uipath.com/ja/listings/hwkhcbx1ftun456bz9td6c)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/4e91612d-df12-e43b-9d66-186b0cdab942.png)

# 終わりに

以上です。

フローの実装が完了したら（テスト実施の前に）「不要なXXX」を削除して、クリーンなコードを実装できたら良いですね。
plunkerでplaycanvas その4

#概要

plunkerでplaycanvasやってみた。
shaderやってみた。

#参考にしたページ。

https://github.com/cx20/jsdo.it-archives/tree/master/tag/playcanvas

#写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/770c1ad3-8f98-66ad-0a3e-b6553e845976.png)


#サンプルコード


```
var canvas = document.getElementById("application-canvas");
var app = new pc.Application(canvas);
app.start();
app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);
app.setCanvasResolution(pc.RESOLUTION_AUTO);
var camera = new pc.Entity();
camera.addComponent("camera", { 
  clearColor: new pc.Color(1.0, 1.0, 1.0) 
});
app.root.addChild(camera);
camera.setPosition(0, 0, 3.0); 
var light = new pc.Entity();
light.addComponent('light');  
light.rotate(45, 0, 0);
app.root.addChild(light);
app.scene.ambientLight = new pc.Color(0.2, 0.2, 0.2);   
var plane = new pc.Entity();
plane.addComponent("model", { 
  type: "plane" 
});
plane.addComponent("script");
app.root.addChild(plane);
plane.rotate(90, 0, 0);
var vs = new pc.Asset("vs", "shader");
var fs = new pc.Asset("fs", "shader");
vs.resource = document.getElementById("vs").textContent;
fs.resource = document.getElementById("fs").textContent;
app.assets.loadFromUrl("AkwjW.jpg", "texture", function(err, asset) {
  plane.script.create("customShader", {
    attributes: {
      vs: vs,
      fs: fs,
      diffuseMap: asset,
      heightMap: asset
    }
  });
});
var CustomShader = pc.createScript('customShader');
CustomShader.attributes.add('vs', {
  type: 'asset',
  assetType: 'shader',
  title: 'Vertex Shader'
});
CustomShader.attributes.add('fs', {
  type: 'asset',
  assetType: 'shader',
  title: 'Fragment Shader'
});
CustomShader.attributes.add('diffuseMap', {
  type: 'asset',
  assetType: 'texture',
  title: 'Diffuse Map'
});
CustomShader.attributes.add('heightMap', {
  type: 'asset',
  assetType: 'texture',
  title: 'Height Map'
});
CustomShader.prototype.initialize = function() {
  this.time = 0;
  var app = this.app;
  var model = this.entity.model.model;
  var gd = app.graphicsDevice;
  var diffuseTexture = this.diffuseMap.resource;
  var heightTexture = this.heightMap.resource;
  var vertexShader = this.vs.resource;
  var fragmentShader = "precision " + gd.precision + " float;\n";
  fragmentShader = fragmentShader + this.fs.resource;
  var shaderDefinition = {
    attributes: {
      aPosition: pc.SEMANTIC_POSITION,
      aUv0: pc.SEMANTIC_TEXCOORD0
    },
    vshader: vertexShader,
    fshader: fragmentShader
  };
  this.shader = new pc.Shader(gd, shaderDefinition);
  this.material = new pc.Material();
  this.material.setShader(this.shader);
  this.material.setParameter('uTime', 0);
  this.material.setParameter('uDiffuseMap', diffuseTexture);
  this.material.setParameter('uHeightMap', heightTexture);
  model.meshInstances[0].material = this.material;
};
CustomShader.prototype.update = function(dt) {
  this.time += dt;
  var t = (this.time % 2);
  if (t > 1) 
  {
    t = 1 - (t - 1);
  }
  if (this.material) 
  {
    this.material.setParameter('uTime', t);
  }
};




```

#成果物

https://embed.plnkr.co/plunk/hZDx1f0B8wMUrdxm

以上。
【Slack】webhookを使って見た（備忘録）

どうもwebエンジニアなりたく勉強中です。
Qiita初投稿ということもあり使い方がいまいちわかってません。
色々教えて頂ければと思います。
今Reactを使ってchatbotを作成中で問い合わせがきた時にslackに通知する仕様が作りたいと思い、忘れないうちにアウトプットしていきたいと思います。

#通知文の作成

```
const payload = {
text : '新しい通知がきました'
}
```
textのvalue側に任意のコメントを挿入することで通知時にそのコメントが表示されます。
例えばstateに記載あるkeyを設定すればフォーム入力された値がslackに表示される！！

##fetchでwebhookを取得する
webhook取得方法は以下記事を参照しました
https://www.sejuku.net/blog/74471

ここでは取得方法は割愛します。

```
const url = '取得したURL'
const options = {
method : "POST",
body : JSON.stringify(payload)

fetch(url,options);
alert('送信が完了しました');
```
最後にはフォームの初期化をしてダイアログをfalseにすれば完了。



エンジニアになれるように引き続き頑張っていきたいと思います！
EC-CUBE4 お手軽にデータ削除


## SQLファイルを準備

↓の場合は、 `TRUNCATE` だけですが、カテゴリテーブルのインサート文や規格テーブルのインサート文などを追加して、いつでも初期状態に戻せると便利かもしれません。

```sql:app/Customize/Resource/sql/reset.sql
SET foreign_key_checks = 0;

TRUNCATE TABLE dtb_order_item;
TRUNCATE TABLE dtb_mail_history;
TRUNCATE TABLE dtb_shipping;
TRUNCATE TABLE dtb_order_pdf;
TRUNCATE TABLE dtb_order;

TRUNCATE TABLE dtb_cart_item;
TRUNCATE TABLE dtb_cart;

TRUNCATE TABLE dtb_product_tag;
TRUNCATE TABLE dtb_product_stock;
TRUNCATE TABLE dtb_product_image;
TRUNCATE TABLE dtb_product_class;
TRUNCATE TABLE dtb_product_category;
TRUNCATE TABLE dtb_product;

TRUNCATE TABLE dtb_class_category;
TRUNCATE TABLE dtb_class_name;
TRUNCATE TABLE dtb_category;
TRUNCATE TABLE dtb_tag;

TRUNCATE TABLE dtb_customer_favorite_product;
TRUNCATE TABLE dtb_customer_address;
TRUNCATE TABLE dtb_customer;

SET foreign_key_checks = 1;
```

## 専用コマンドを追加

SQLコメントアウトには対応していません。

```php:app/Customize/Command/ResetDataCommand.php
<?php

declare(strict_types=1);

namespace Customize\Command;

use Doctrine\ORM\EntityManagerInterface;
use Eccube\Command\PluginCommandTrait;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

use function array_map;
use function array_pop;
use function dirname;
use function explode;
use function file_exists;
use function file_get_contents;
use function strpos;

class ResetDataCommand extends Command
{
    use PluginCommandTrait;

    protected static $defaultName = 'customize:reset-data';

    /** @var EntityManagerInterface */
    private $entityManager;

    public function __construct(EntityManagerInterface $entityManager)
    {
        parent::__construct();
        $this->entityManager = $entityManager;
    }

    protected function configure(): void
    {
        $this->setDescription('Reset transaction data.');
    }

    protected function execute(InputInterface $input, OutputInterface $output): ?int
    {
        $io = new SymfonyStyle($input, $output);

        $connection = $this->entityManager->getConnection();
        $connection->beginTransaction();

        $filePath = dirname(__DIR__) . '/Resource/sql/reset.sql';
        if (! file_exists($filePath)) {
            $io->error('reset.sql not found.');

            return 1;
        }

        $content = file_get_contents($filePath);
         if (! strpos($content, ';')) {
             $content .= ';';
        }

        $queries = array_map(static function ($value) {
            return trim($value);
        }, explode(';', trim($content)));
        array_pop($queries);

        foreach ($queries as $query) {
            $io->text($query);
            $connection->exec($query);
        }

        $connection->commit();

        $io->success('success.');

        return 0;
    }
}
```

## 実行 :rocket: 

```bash
./bin/console customize:reset-data
```
約2年プログラマーやってきて実際によく使っているGitまとめ


約2年プログラマーやってきて実際によく使っているGitをまとめました。

ローカルとリモートって言われても未だにピンと来ないポンコツですが、originと開発環境で理解して何とかやってきました←
同じ様な人がいるかもしれないのでそのまま記載していきます。

## 開発環境のmasterを、強制的にoriginのmasterに合わせる

```
▼ originのmasterの最新を取ってきて
git fetch origin master
▼ originのmasterに強制的に合わせる！
git reset --hard origin/master
```

## 作業中だけどpullした状態で進めたい時
（下記ではmasterブランチを指定しています）

```
▼ 退避して
git stash
▼ pullして
git pull origin master
▼ 適応させる
git stash apply
```

## addしてしまったファイルを戻す
git add . で一気にaddした後で、上げたくないファイルがあること思い出した時。

```
git reset ファイル名
```

## 編集したファイルを編集前に戻す
（新しく作ったファイルは追跡されていないのでrmで削除する必要あり）

```
git checkout ファイル名
▼ 全て戻したい場合は「ファイル名」部分を「.」にします
git checkout .
```

## push前の、直前のコミットを取り消したいとき
（ファイルの編集内容は 保持 したい時）

```
git reset --soft HEAD^
```

## push前の、直前のコミットを取り消したいとき
（ファイルの編集内容も 破棄 したい時）

```
git reset --hard HEAD^
```

## ブランチにマージする
（下記ではmasterブランチにdevelopブランチをマージしています）

```
▼ マージしたいブランチに移動
git checkout master
▼ マージ
git merge develop
```

## originにあるブランチを開発環境に作りたいとき
（下記ではdevelopブランチをしています）

```
▼ originの最新を取ってきて
git fetch
▼ originのdevelopブランチを指定して、developブランチを作成
git checkout -b develop origin/develop

```

## 最後に言い訳
現在所属している会社では自宅勤務のこと「リモート」って呼んでいるので、「リモート」と聞くと 自分のところ 感があるんですよね。（知らんがな）
ダウンロード zip 中の exe や dll が実行できない原因と最も手軽な対処方法

# 要約

* ダウンロードした zip ファイルのプロパティで「セキュリティ： 許可する」をチェックしてから展開する。

# 詳細

Windows のセキュリティ機能により、外部ネットワークからダウンロードしたファイルには代替データストリーム情報(ZoneId)が付加される。（ただし、ダウンロードファイルの格納先ファイルシステムが NTFS の場合に限る。）
そして、この ZoneId が付加されている exe, dll ファイルは実行されないように Windows の OS 機能によってガードされている。

zip ファイルの場合、圧縮されているファイル自身に ZoneId は付加されていない。しかし、Windows 標準機能で展開・解凍すると、zip ファイルに付加されている ZoneId が解凍したファイルにも自動的に付加され、セキュリティが確保されている。

なお、Windows 標準ではない解凍ツールを使用して zip ファイルを解凍した場合、ZoneId が自動付加されないため、exe, dll がガードされることはない。

### 参考情報

* [dirやPowerShellでNTFSの代替データストリーム情報を表示する - @IT](https://www.atmarkit.co.jp/ait/articles/1407/11/news111.html)

* [streamsコマンドでNTFSの代替データストリーム情報を表示／削除する - @IT](https://www.atmarkit.co.jp/ait/articles/1001/14/news112.html)

    > ZoneIdが付いた.ZIPファイルを解凍すると、基本的には解凍された個別のファイルにもZoneIdが継承される 

## 最も手軽な対処方法

7-Zip などの解凍ツールを使わず、Windows 標準で対処する場合

* zip ファイルを解凍する前に、zip ファイルのプロパティで 「セキュリティ： 許可する」をチェックしてから展開。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239238/1ed4fbaf-76f4-a908-dc14-cb733c9c3031.png)

理由と対処方法を知っていれば、とても簡単。

以上
NeosVR内でのGAS(Google Apps Script)の使い方 (初心者用)

#【はじめに】
GAS(Google Apps Script)を使って、NeosVR内から
Googleのスプレッドシート(Google版エクセルみたいなもの)の
値の読み込みと書き込みを実施する方法を説明します。

これができるようになると、例えば
NeosVR内で作ったゲームのランキング表作成や挑戦数、クリア数の管理などに
応用することができます。

#【手順】
__①GoogleのスプレッドシートとGASの使い方を理解する__
以下リンク先ページの説明がとても分かりやすいので、
スプレッドシートへの書き込みまでやってみてください。

「GASをWebAppとして公開して初回実行(doPostとdoGet)」
https://uncle-atsushi.com/gas_first-execute_dopost-doget/

※説明は旧ページのものになるので、
Apps Scriptのページで「以前のエディタを使用」を選んでください

__②コードの作成__
まずは以下の「指定したセルの読み込み応答コード」を全てGASに貼り付けます。

```
//指定したセルの読み込み応答

function doGet(e) {
  // doPostから送られてきたパラメータを受け取る。
  var param1 = e.parameter.pParam1;
  var param2 = e.parameter.pParam2;
  var param3 = e.parameter.pParam3;
  // pParam2と3は予備変数
  
  // 読み込み動作readsheetvalueを実行する
  var rValue = readsheetvalue(param1, param2, param3);
  
  // 読み込んだ値を返す
  return rValue;
}
 
function readsheetvalue(param1, param2, param3) {
  //1. 現在のスプレッドシートを取得
  var spreadsheet = SpreadsheetApp.openById("スプレッドシートIDをここに入力");
  //2. 現在のシートを取得
  var sheet = spreadsheet.getSheetByName("シート1");
  //3. 指定するセルの範囲（param1）を取得
  var range = sheet.getRange(param1);
  //4. 値を取得する
  var value = range.getValue();
  //5. テキスト化して値を設定
  return ContentService.createTextOutput(value);
}
```

次に、プログラム内の
//1. 現在のスプレッドシートを取得
var spreadsheet = SpreadsheetApp.openById("スプレッドシートIDをここに入力");
へスプレッドシートIDを入力します。
(IDはスプレッドシートURLの右の場所です→~d/ここがID！/edit~)

__③NeosVRで使う準備__
ネオスで使うためには、外部アクセスを許可する必要があります。
以下の設定変更を行ってから、No.を更新してください。

「公開」→「ウェブアプリケーションとして導入」に記載されている
「Execute the app as」をme,「Who has access to the app」を「anyone～」にする。

次に、更新されたURLの一番後ろに「?pParam1=A1」を追加し、
そのURLにアクセスすることでスプレッドシートA1の値が出力されることを確認してください。

__④NeosVRで出力__
ノードを以下の図のようにつなぎます
![2021-01-23 11.30.30.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927736/91cd2f56-d50e-5f83-3ff6-35d474ddba5b.jpeg)


ノード「Get string」の入力側に③のURLを入力します。
あとはパルスを押して、スプレッドシートA1の値が出力されればOKです！


#【補足】
「指定したセルの書き込みコード」も同様の手順で使うことができます。
URLの一番後ろにつける文字を「?pParam1=B1&pParam2=5」とすることで
「B1」セルに「5」が入力されます。
スプレッドシートへの書き込みだけなのでNeos側への応答はないです


```
//指定したセルへの書き込み

function doGet(e) {
  // doPostから送られてきたパラメータを受け取る。
  var param1 = e.parameter.pParam1;
  var param2 = e.parameter.pParam2;
  var param3 = e.parameter.pParam3;
  // pParam3は予備変数

  // 書き込み動作Write~Spreadsheetを実行する
  WriteParamSpreadsheet(param1, param2, param3);

}
 
function WriteParamSpreadsheet(param1, param2, param3) {
  // スプレッドシートのIDを指定して変数に格納。
  var InfoSpreadsheet = SpreadsheetApp.openById("スプレッドシートIDをここに入力");
  
  // スプレッドシートの中のシート名を指定して変数に格納。
  var InfoSheet = InfoSpreadsheet.getSheetByName("シート1");
  
  // スプレッドシートへ書き込み。
  InfoSheet.getRange(param1).setValue(param2);

}
[Python] Outlookでメール作成

# 初めに
Pythonを用いたOutlookでのメール作成を実施する。
以下の環境で実施した。

|||
|---|---|
|os|windows|
|python|3.7.1|
|pywin32|227|
|anaconda|4.8.5|

# インストール

anaconda環境であれば、デフォルトでインストール済み。
インストールに関するメモを記載する。

```bash

conda install pywin32
```

# mailの作成

ライブラリを用いてメールを作成する。
Outlookを用いたMailItemオブジェクトは以下を参照する。
https://docs.microsoft.com/ja-jp/office/vba/api/outlook.mailitem

``` python
import win32com.client

# Outlookのmailオブジェクト設定
outlook = win32com.client.Dispatch('Outlook.Application')
objMail = outlook.CreateItem(0) # MailItemオブジェクトのID

# メールの設定
objMail.To = 'xxx@xxx.com; aaa@aaa.com' # 宛先 複数の場合は'; 'を間に挟む
objMail.cc = 'yyy@yyy.com' # CC
objMail.Bcc = 'zzz@zzz.com' # BCC
objMail.Subject = 'mail title' # Mailタイトル
objMail.BodyFormat = 0 # 3種の本文テキスト形式 (テキスト形式, リッチテキスト形式, HTML形式)
objMail.Body = 'mail body test + sign' # Mail本文

objMail.Attachments.Add('hogehoge.csv') # 送付ファイルがある場合はファイルパスで添付

objMail.Display(True) # MailItemオブジェクトを画面表示で確認する
# objMail.Send() # Mailを即時送信
```

# 参考
https://qiita.com/watyanabe164/items/e1c21af0127497b74b2a
Mapについて【Java】

#目次
* [特徴](https://qiita.com/drafts#%E7%89%B9%E5%BE%B4)
* [初期化① put(key, value)](https://qiita.com/drafts#%E5%88%9D%E6%9C%9F%E5%8C%96-putkey-value)
* [初期化② put(key, value)](https://qiita.com/drafts#%E5%88%9D%E6%9C%9F%E5%8C%96-putkey-value-1)
* [要素数を返す size()](https://qiita.com/drafts#%E8%A6%81%E7%B4%A0%E6%95%B0%E3%82%92%E8%BF%94%E3%81%99-size)
* [キーを指定して値を取得する get(key)](https://qiita.com/drafts#%E3%82%AD%E3%83%BC%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%97%E3%81%A6%E5%80%A4%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B-getkey)
* [KeyとValueをセットで取得する entrySet()](https://qiita.com/drafts#key%E3%81%A8value%E3%82%92%E3%82%BB%E3%83%83%E3%83%88%E3%81%A7%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B-entryset)
* [Keyのみを取得する keySet()](https://qiita.com/drafts#key%E3%81%AE%E3%81%BF%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B-keyset)
* [Valueのみを取得する values()](https://qiita.com/drafts#value%E3%81%AE%E3%81%BF%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B-values)
* [keyを指定して削除する remove(key)](https://qiita.com/drafts#key%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%97%E3%81%A6%E5%89%8A%E9%99%A4%E3%81%99%E3%82%8B-removekey)
* [マップの要素を全て削除する clear()](https://qiita.com/drafts#%E3%83%9E%E3%83%83%E3%83%97%E3%81%AE%E8%A6%81%E7%B4%A0%E3%82%92%E5%85%A8%E3%81%A6%E5%89%8A%E9%99%A4%E3%81%99%E3%82%8B-clear)

#特徴
__java.util.HashMap__
&emsp;　●　順番が保証されない
&emsp;　●　nullのキーを許容する

__java.util.LinkedHashMap__
&emsp;　●　追加した順

__java.util.TreeMap__
&emsp;　●　昇順

#初期化① put(key, value)
```java:Main.java
package com.test;

import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        Map<Integer, String> animalsMap = new HashMap<>();
        animalsMap.put(1, "dog");
        animalsMap.put(2, "cat");
        animalsMap.put(3, "pig");
        System.out.println(animalsMap); // {1=dog, 2=cat, 3=pig}
    }
}
```

#初期化② put(key, value)
```java:Main.java
package com.test;

import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        Map<Integer, String> animalsMap = new HashMap<Integer, String>() {
            {
                put(1, "dog");
                put(2, "cat");
                put(3, "pig");
            }
        };
        System.out.println(animalsMap); // {1=dog, 2=cat, 3=pig}
    }
}
```

#要素数を返す size()
```
System.out.println(animalsMap.size()); // 3
```

#キーを指定して値を取得する get(key)
```
for (int i = 1; i <= animalsMap.size(); i++) {
    System.out.print(animalsMap.get(i) + ","); // dog,cat,pig,
}
```

#KeyとValueをセットで取得する entrySet()
```
System.out.println(animalsMap.entrySet()); // [1=dog, 2=cat, 3=pig]
```

#Keyのみを取得する keySet()
```
System.out.println(animalsMap.keySet()); // [1, 2, 3]
```

#Valueのみを取得する values()
```
System.out.println(animalsMap.values()); // [dog, cat, pig]
```

#keyを指定して削除する remove(key)
```
animalsMap.remove(2);
System.out.println(animalsMap); // {1=dog, 3=pig}
```

#マップの要素を全て削除する clear()
```
animalsMap.clear();
System.out.println(animalsMap); // {}
```

#参考
https://style.potepan.com/articles/16280.html
CentOS7 Gitを導入する

# 目的

- CentOS7にGitを導入する方法をまとめる

# 方法

1. 下記コマンドを実行してリポジトリを追加する。

    ```terminal
    $ sudo yum install https://repo.ius.io/ius-release-el7.rpm
    ```

1. 下記コマンドを実行してリポジトリの設定ファイルを開く。

    ```terminal
    $ sudo vi /etc/yum.repos.d/ius.repo
    ```

1. 開いたファイルの`[ius]`の`enabled`の値を「0」に書き換える。

    ```/etc/yum.repos.d/ius.repo
    [ius]
    name = IUS for Enterprise Linux 7 - $basearch
    baseurl = https://repo.ius.io/7/$basearch/
    enabled = 0 
    repo_gpgcheck = 0
    gpgcheck = 1
    gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-IUS-7
    ```

1. 下記コマンドを実行してGitをインストールする。インストール確認時のパッケージのインストールもとリポジトリがiusになっていることを確認し「y」を入力してからEnterを押下する。

    ```terminal
    $ sudo yum install git --enablerepo=ius --disablerepo=base,epel,extras,updates
    ```

1. 下記コマンドを実行して`command not found`が出ないことを確認する。

    ```terminal
    $ git --version
    ```
PATHの通し方

## 概要

いつまでたってもPATHの通し方を忘れるので自分用にメモ。

### 現在通っているPATHの確認

下記のどれでもOK。

```shell
env $PATH
printenv $PATH
echo $PATH
```

### 一時的なPATHの追加

```shell
export PATH=$PATH:<PATH>
```
`$PATH:<PATH>`で、「現在のPATH」＋「新しいPATH」という意味。

うっかり`$PATH`を忘れて、他のPATHを通すのを忘れてしまったりしたことがあったり無かったり。。。。

### 恒久的なPATHの追加

上の`export`コマンドをTerminal立ち上げ時に毎回自動的に打てればいい。

シェルに関して、その設定をするのが、`.zshrc`のファイル。Terminal起動時に必ず読み込まれるファイル。

```shell
vi ~/.zshrc
```

で`.zshrc`を開き、`PATH`の部分を下記に変更。

```shell
export PATH=$PATH <PATH>
```

保存した後に`.zshrc`を読み出す下記コマンドを打てばPATHが通るはず。

```shell
source ~/.zshrc
```

## 参考
https://qiita.com/fuwamaki/items/3d8af42cf7abee760a81
Elasticsearchをソースからビルドして動かしてみる

# TL;DR
オープンソースの全文検索エンジンであるElasticsearchは、GitHubにソースコードが公開されています。
[Elasticsearch](https://github.com/elastic/elasticsearch)
今回は、このソースコードからElasticsearchをビルドし、動かしてみました。
また、Elasticsearchの可視化ツールである[elasticsearch-head](https://github.com/mobz/elasticsearch-head)の動かし方や設定も記載します。
（内容は、ほぼほぼ備忘録です）

# Elasticsearchをビルド
まず、GitHubからソースコードをクローンします。

```
git clone https://github.com/elastic/elasticsearch.git
```

そして、ビルドを実行。ビルドには、Gradleを使用します。Linuxユーザの場合、sdkmanなどでインストールしておきましょう。
また、JavaはJDK14以上が必要です。（JDK11ではビルドに失敗するので注意）
なお、ビルド手順はGitHubのREADMEにも記載されています。

```
cd elasticsearch
./gradlew localDistro
```

ビルドに成功すると、buildディレクトリ以下にモジュールが作成されます。

# Elasticsearchの実行
ビルドされたモジュールを実行します。

```
cd build/distribution/local/elasticsearch-8.0.0-SNAPSHOT/ # パスは環境によって異なります
./bin/elasticsearch
```

正常に実行できているかは、以下のようにHTTPリクエストを送信して確認します。

```
curl -X GET http://localhost:9200/
```

# elasticsearch-headの起動
elasticsearch-headを使い、ブラウザから可視化をしてみます。

まず、elasticsearch-headをダウンロード

```
git clone https://github.com/mobz/elasticsearch-head.git
```

`npm`コマンドでサーバを起動します。

```
cd elasticsearch-head
npm install
npm run start
```
サーバの起動後、`http://localhost:9100`にブラウザでアクセスします。

## localhost以外からアクセスする時の設定
Elasticsearchは、デフォルトではlocalhost以外からのアクセスはできなくなっています。そのため、以下の設定をElasticsearch本体のconfig配下にある`elasticsearch.yml`に追加します。

```elasticsearch.yml
# CORSの有効化
http.cors.enabled: true
http.cors.allow-origin: "*"

# 外部からのアクセスの有効化
network.host: 0.0.0.0
http.port: 9200
transport.host: localhost
```


# 参考サイト
- [春の入門祭り🌸 #17 Elasticsearch入門](https://future-architect.github.io/articles/20200623/)
【Python】【エラー】ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

## 概要
* エラーが出たので対処をする

## 事象
* 抜粋

```
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
```

* 全体

```
$ pip3 install -r requirements.txt
～～
    ERROR: Command errored out with exit status 1:
     command: /home/sample/work/venv/bin/python3.6 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-pnhw5w4t/psycopg2_e6366d5cdcc146ac8944e7983c5fb5ca/setup.py'"'"'; __file__='"'"'/tmp/pip-install-pnhw5w4t/psycopg2_e6366d5cdcc146ac8944e7983c5fb5ca/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-gqfgm6ts
         cwd: /tmp/pip-install-pnhw5w4t/psycopg2_e6366d5cdcc146ac8944e7983c5fb5ca/
    Complete output (23 lines):
    running egg_info
    creating /tmp/pip-pip-egg-info-gqfgm6ts/psycopg2.egg-info
    writing /tmp/pip-pip-egg-info-gqfgm6ts/psycopg2.egg-info/PKG-INFO
    writing dependency_links to /tmp/pip-pip-egg-info-gqfgm6ts/psycopg2.egg-info/dependency_links.txt
    writing top-level names to /tmp/pip-pip-egg-info-gqfgm6ts/psycopg2.egg-info/top_level.txt
    writing manifest file '/tmp/pip-pip-egg-info-gqfgm6ts/psycopg2.egg-info/SOURCES.txt'
    
    Error: pg_config executable not found.
    
    pg_config is required to build psycopg2 from source.  Please add the directory
    containing pg_config to the $PATH or specify the full executable path with the
    option:
    
        python setup.py build_ext --pg-config /path/to/pg_config build ...
    
    or with the pg_config option in 'setup.cfg'.
    
    If you prefer to avoid building psycopg2 from source, please install the PyPI
    'psycopg2-binary' package instead.
    
    For further information please check the 'doc/src/install.rst' file (also at
    <https://www.psycopg.org/docs/install.html>).
    
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
```

## 対処
### pipの最新化
* 変化なし

```
$ pip3 install --upgrade pip
```

### setuptoolsの最新化
* 変化なし

```
$ pip3 install --upgrade pip setuptools
```

### ライブラリのインストール【私の場合はこれで解決】
* CentOS

```
$ yum install postgresql-devel
```

* Debian/Ubuntu

```
$ apt install libpq-dev
```

* MacOS

```
$ brew install postgresql
```

### 結果
* インストールできるようになりました。

```
$ pip3 install -r requirements.txt
～～
Successfully ～～
```

## 参考
* [www.ted027.com](https://www.ted027.com/post/python-psycopg2/)
Vue.js インスタンス生成後に実行したいメソッド

# 目的
開発中にページ読み込み時に実行したいメソッドがあった。 最初、window:onload を使ってみたがうまくいかなかった。

# うまくいかない例

以下のコードではページ読み込み時にメソッドは実行されているのだが、コンソールで確認したところ`title` に値が入っていなかった。

```html

  <div id="app">
    <h1>{{ title }}</h1>
  </div>
```


```js
var app = new Vue({
  el: '#app',
  data: {
    title: ''
  },
  method: {
    window:onload = function() {
    this.title = 'Welcome to my page!'
    }
  }
})
```


# 解決策

<strong>method</strong> ではなく<strong>created</strong>を使う

サンプルコード

```html
  <div id="app">
    <h1>{{ title }}</h1>
  </div>
```

```js
var app = new Vue({
  el: '#app',
  data: {
    title: ''
  },
  created: function() {
    this.title = 'Welcome to my page!'
  }
})

```

# 参考記事
https://jp.vuejs.org/v2/guide/instance.html
【メモ】Issueドリブン開発とブランチ命名規則ついて【Git】

こんにちわ=)

初学者の皆さんは「Issueドリブン開発」や、Gitのブランチ名にも命名規則があるのを知ってますでしょうか？

自分は「聞いたことあるな」くらいにしか考えていませんでしたが、最近は開発設計の勉強もしているところなのできっちり勉強しようと思います。

自分はgitでブランチを切るときに毎回、「ブランチ名なににしよっかなー？」とか毎回適当に決めちゃっていました。

クラス名やテーブル名にも命名規則があるように、ブランチにもルールがあるんじゃないかな？って調べたら案の定ありました。。

いつまでも知らないままにするのは良くないので、ちゃんと勉強と実践をしていきたいと自戒を込めてこの記事を書きました。

自分なりの解釈が多分に含まれますが、ぜひご覧ください。

# **issueドリブン開発のメリット・デメリット**

きちんと厳密にルールを守らせる必要はありますが、issueとブランチを1セットにすることの恩恵はかなりあると思っています。

### **メリット**

- 修正したissueを参考にしようとしたときにわかりやすい。
- 作成されたブランチがどのissueに関連したものかが明確になる
- コミットが大きくなりすぎないためコードレビューしやすくなる。

### **デメリット**

変数名の変更みたいな「これのためにissue立てるのか？！」みたいな細かな修正の際に個人の裁量が難しい。一言で言えば「少し面倒くさい」ｗ

# **issueとは**

Issueとは、Github上でタスク管理できるToDoリストみたいなものです。

issueを書くと、下記の画像の**#番号**のような番号が発行され、これは後にbranch作成の時に必要になってきます。

自分が必要な機能や気になるバグなどを見つけた時には、issueを書くことをクセ付け、相手に依頼された際は「isseuで書いてください」と伝えることで、当事者同士のふんわりとした依頼や修正が少なくなり、結果的に組織的な開発がしやすくなります。

# **issueの書き方**

issueはタイトルと詳細な内容を書くことが出来ます。

タイトルは簡潔に分かりやすく書き、内容は詳しく書きたいことがある際、画像を添付したりマークダウンで書くことで、より分かりやすいissueを作成することができます。

# **Issueドリブン開発の流れ**

以下は「Webサイトのメニューをハンバーガーメニューに変更したい」となった際の一例です。

1. Github上で、やりたいことを記載したIssueを立てる。(issue番号は#1と仮定)
2. 発行されたIssue番号を使い、`feature/#1_replace_to_hamburger_menu`というブランチを作成。
3. 開発進める。
4. 開発完了したらdevelopブランチにマージコミット。


この際、`close #12`などとコミットメッセージに記述すると、自動的にIssueが閉じられるので、覚えておきましょう。

# **ブランチの作成の仕方**

以下がブランチの命名の仕方です。

```
$ git branch ブランチ名/#issue番号_動詞_機能
```

ブランチの記述の手順は以下の流れになります。

1. **ブランチと関連する発行されたissue番号を記述**
2. **add, remove, updateなどの動詞を記述**
3. **追加する機能を簡潔に記述**

feature- と hotfix- の後には任意のわかり易い名前をつけてください。

# **ブランチ命名のサンプル**

**「すでに設置済みmenuをハンバーガーに変更する」**といった場合はこんな感じに記述します。

```
feature/#番号_replace_to_hamburger_menu
```

こちらは今自分が開発中のアプリで実際に立てたブランチで、「開発中のクイズ画面のUI」を置いておくためのブランチとして作成しました。

```
develop/#13_coding_quizUI
```

# **まとめ**

今回はissueドリブン開発について学習してみました。

現在個人開発で実践していますが、GitHubの使い方の非常に良い練習にもなります、現場に出ていない方も取り入れてみてはいかがでしょうか？

おつかれさまでした！ﾟ=)

# **参考文献**

- [gitのブランチの命名規則](https://qiita.com/luccafort/items/c91e817e78f1167221cc)
- [【Git】ブランチの命名規則を調べてたらIssueドリブン開発という存在を知った](https://qiita.com/c6tower/items/fe2aa4ecb78bef69928f)
- [公式ドキュメント](https://docs.github.com/ja)
不正アクセスの調査における観点

#はじめに
不正アクセスの原因や影響範囲を調査するためには、観点とツールの2つが必要です。
観点とは、何を調べれば良いかです。ツールはその名の通り、どのようなツールを使うかです。
本記事では、このうち観点について記載します。

#不正アクセスの種類
この分類は個人的に作成したもので、何かの基準にのっとったものではありません。
インシデントが起こる場所としては、クライアントPCかサーバのどちらかです。両方という場合もあります。
そして、不正アクセスの経路ですが、何らかの脆弱性を悪用されるか、不正にログインされるか、そもそもアクセス制限がかかっていないかのいずれかのパターンに当てはまるように思います。
ここでは便宜的に、Emotetに代表されるような細工されたOfficeファイルのマクロを実行してしまったことによりマルウェアに感染するというパターンは、脆弱性を悪用に分類しています。

上記分類をした上で、各パターンでどのような原因が想定されるかをまとめたものが以下の表です。

| 手法 | クライアントPC | サーバ |
|:-:|:-:|:-:|
| 脆弱性を悪用  | 主にメールの本文または添付ファイル  | 外部公開しているサービス  |
| 不正ログイン  | RDP  | SSHやCMSなどの外部公開しているサービスの認証  |
| アクセス制限の不備  | 認証なしのファイル共有  | 設定不備による意図しないファイル公開  |

注意点として、この表に記載した原因は代表的なものであり、これ以外のパターンも十分にあり得ます。
私の経験上はこれらが多かったというだけのものです。

#調査の観点
上記の表から、最初に調査すべき観点はある程度絞れてくると思います。

##クライアントPCの調査
クライアントPCで何かインシデントが発生した場合は、メール、RDP、ファイル共有を疑ってみるのが良いと思います。
メールであれば通常はクライアントに保存されているか、メールサーバ上に残っているでしょう。

RDPであればイベントログにログイン成功が記録されているはずです。ただし、デフォルトでは無効になっているので、
設定を変更していなければこの可能性は低いと言えます。

ファイル共有も自分で設定しなければ共有されないため、設定を変更していなければこの可能性は低いです。
共有フォルダの一覧は「コンピュータの管理」から確認できます。

##サーバの調査
サーバの場合は公開しているサービスの種類によってかなり変わってきます。
近年では、Webサーバやメールサーバといった外部公開サービスのアプリケーション自体の脆弱性は減っています。
そのため、例えばApacheの脆弱性を考慮するよりは、CMSなどのWebアプリケーション、もしくはWebアプリケーションのプラグインの脆弱性を疑う方が良いでしょう。

SSHやCMSへの不正ログインはたびたび目にします。SSHやCMSのログイン履歴をログから探せば、比較的容易に見つかると思います。IPアドレスだけをawkなどで抜き出し、geoiplookupで国外からのログインを調べるのが早いでしょう。国内からの不正ログインの可能性は低いですが、全くないというわけではないので、見慣れないIPアドレスが含まれていないか簡単に確認しておいた方が良いです。
なお、これらのサービスはそもそも外部に公開せず、アクセス制限を行うことが望ましいです。SSHであれば公開鍵認証に限定した方が良いです。

意図しないファイル公開は、Webサーバの設定不備だけでなく、Webストレージでも起こります。
Webサーバの設定不備は、ディレクトリ・リスティングが可能だったり、.htaccessの設定不備だったりと様々です。Webアプリケーションの実装に問題がある場合もあります。いずれもWebサーバのログから確認できますので、公開すべきではないファイルが外部から参照されていないか確認してください。（そもそもそういったファイルは公開サーバに置かないのが一番ですが）
Google DriveやOneDriveなどのWebストレージは設定を誤ると全世界に公開されてしまいます。URLを知っている人だけがアクセスできるようにする方法もありますが、これはURLが漏えいすると即座に情報漏洩につながります。URLをきちんと管理できるなら良いですが、不特定多数と共有する場合は、面倒でもアカウントによるアクセス制限を行ったほうが安全です。
なお、基本的には外部にファイルを送る際は、専用のサービスを使う方が安全でしょう。また、Webストレージは設定により、組織内のみの利用に限定できる場合があります。

#まとめ
調査の観点について整理してみましたが、意外と長くなってしまいました。
実際には本記事に記載していないパターンも多々ありますが、基本は抑えられているはずですので、インシデント対応でお困りの方の参考になれば幸いです。
skip-GANomalyで異常検知#2

# 1. 目的
オリジナルデータセットでskipGANomalyによる異常検知を行う。
引用元リポジトリ[[1]](https://github.com/samet-akcay/skip-ganomaly)

# 2. 仮定
環境構築は完了済み（[参考](https://qiita.com/hamukawa/items/b197b674a6408d905f91))

# 3. データセット
### 3.1 データセットの概要


正常画像（キャップが締まっている）
![20200717_094111_002_32.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469182/a22fcb48-8886-db0e-a425-adf1e5998532.jpeg) ![20200717_094910_016_32.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469182/1c6499a2-eee2-4443-59c8-4ba70e910579.jpeg) ![20200717_095212_045_32.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469182/4f3e4567-4543-91a4-1a67-29f6e4ad098e.jpeg) ![20200717_095406_025_32.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469182/fdb52274-ebb7-2f13-f8d0-c868e48aedd5.jpeg)

異常画像（キャップが開いている）
![20200717_093648_32 - コピー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469182/40583f35-8fb6-aea1-69b5-f1dff0942344.jpeg) ![20200717_093808_32.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469182/cfe3fca5-cb83-e5f4-c47f-6a489c7fc782.jpeg)


### 3.2 データセットのディレクトリ構成

```
./data/
├── caps #データセット名
│     ├──train
│     │   ├──0.normal
│     │   │    └──正常画像1
│     │   │    └──正常画像2
│     │   │    └──正常画像3
│     │   │    ...
│     ├──test
│     │   ├──0.normal
│     │   │    └──正常画像1
│     │   │    └──正常画像2
│     │   │    └──正常画像3
│     │   │    ...
│     │   ├──1.abnormal
│     │   │    └──異常画像1
│     │   │    └──異常画像2
│     │   │    └──異常画像3
│     │   │    ...
```

# 4. 学習
### 4.1 Visdomの起動
可視化ツールであるVisdomを別のコマンドプロンプトで起動 

```
python -m visdom.server
```

### 4.2 学習
以下のコマンドで学習

```
 python train.py --model skipganomaly --dataset caps --abnormal_class open --display --isize 128 --device cpu --gpu_ids -1 --name capsIsOpen0123 --niter 15
```

# 5　学習結果確認
学習結果を確認する
以下のテストコードを実行する。
ディレクトリはtrain.pyと同じ。

```test.py
# LIBRARIES

from options import Options
from lib.data.dataloader import load_data
from lib.models import load_model

def main():
    opt = Options().parse()
    data = load_data(opt)
    model = load_model(opt, data)
    model.test(plot_hist=True)

if __name__ == '__main__':
    main()
```
Raspberry PiのUbuntu 20.10でスリープ解除後にキーボード・マウスを認識しない不具合

先日[Raspberry Pi 4BでUbuntuをSSDブートする記事](https://qiita.com/SogoK/items/76bc2891c72eff938157)を書きましたが、数日使っていて、スリープ解除後、ログイン画面でキーボードやマウスを認識しないバグに遭遇したので、対処法をメモ。

## 症状
スリープ解除後、（ほぼ必ず）キーボード・マウスを認識しなくなる。SSHでログインして`sudo reboot`もしくは強制的に電源を落として再起動すると復活する。
LogitechのUnifyingのせいかとも思ったが、普通のUSBキーボードも認識しなかった。

## 対処法
参考文献にある方法の通り、`/etc/gdm3/custom.conf`の`#WaylandEnable=false`を`WaylandEnable=false`にする（コメントアウトを外す）。

```conf:custom.conf（変更前）
# GDM configuration storage
#
# See /usr/share/gdm/gdm.schemas for a list of available options.

[daemon]
# Uncomment the line below to force the login screen to use Xorg
#WaylandEnable=false

（以下略）
```

```conf:custom.conf（変更後）
# GDM configuration storage
#
# See /usr/share/gdm/gdm.schemas for a list of available options.

[daemon]
# Uncomment the line below to force the login screen to use Xorg
WaylandEnable=false

（以下略）
```

そのうち直るといいですね。

## 参考文献
[Problem with USB Keyboard and Mouse on Raspberry Pi 4B with Ubuntu 20.10](https://askubuntu.com/questions/1300689/problem-with-usb-keyboard-and-mouse-on-raspberry-pi-4b-with-ubuntu-20-10)
[Ubuntu 20.10 Desktop on Pi4B - screen-freeze after idling at login-screen](https://bugs.launchpad.net/ubuntu/+source/linux-raspi/+bug/1909678)
[Oracle Cloud] Block Volumeの差分バックアップを観察してみた

# はじめに

OCIのBlock Volumeのバックアップの種類には、フル・バックアップと増分バックアップがあります。マニュアルにあるとおり、フルバックアップは、ボリューム作成以降のすべての変更が取得され、増分バックアップでは、前回バックアップ以降の変更のみが含まれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/f264e9db-67ac-84aa-d78b-f3efbadcda4a.png)

フル・増分バックアップは、削除時の動作がややこしく、[マニュアル](https://docs.oracle.com/ja-jp/iaas/Content/Block/Concepts/blockvolumebackups.htm)の記載によれば、以下のような動作をするようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/574555a1-b85d-bb41-23e4-153d15cef5f8.png)

絵にするとこんな感じでしょうか

□ バックアップ保持期限内
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/bf25b502-8ee9-3c69-f5e3-9278ec21628f.png)
□ バックアップ保持期限切後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/90327196-250e-40c7-3fcd-5801619612a4.png)

この動作が実際どうなるかがきになったため、ポリシーベース自動バックアップを設定して検証してみました。

# やったこと
Block VolumeをアタッチしたComputeを毎日起動して、ddコマンドで1GB分のファイルを作成して終了するという処理を3週間程度繰り回しました。

ddコマンド作成時に、以下のoci bv backup list コマンドを利用してバックアップ情報も一緒に出力しました。

## バックアップ・ポリシーの設定
ComputeインスタンスにアタッチしたBlock Volumeに自動バックアップを設定にして、昨年12月後半から翌月半ばまで繰り回しました。

適用したポリシーは、Oracle定義ポリシーのGoldです。このポリシーでは、以下のスケジュールでバックアップが実行されます

* 毎日 0:00 に差分バックアップが取得され1週間保持される
* 毎週月曜 0:00 に差分バックアップが取得され、4週間保持される
* 毎月1日 0:00 に差分バックアップが取得され、約1年間保持される
* 毎年1月1日 0:00 にフルバックアップが取得され、5年間保持される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/5ff6b49b-20b6-8758-819d-b5d96ec4cc74.png)

なお、日本語マニュアルにはまだ記載が反映されていないようですが、Oracle定義ポリシーのフル・バックアップは2021/11/3からスケジュールされなくなり、すべて差分になるそうです。まぁ、フルバックアップを5年間保存されても、容量食うだけで使いどころないケースの方が多そうですからね。。
[英語マニュアル](https://docs.oracle.com/en-us/iaas/Content/Block/Tasks/schedulingvolumebackups.htm)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/aad83a49-be8d-5f8d-7ca0-434027f3add5.png)

## 結果
以下のような結果になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/b63ef9d3-a5db-2f56-7ec8-d4821ba4dfb7.png)

* セル内の数値は、oci bv backup list から取得した"unique-size-in-mbs"の値です。バックアップ・サイズ(MB)です
* セル中の黄色背景は、初めてバックアップが取得されたときのサイズです
* セル中の赤背景は、バックアップ・サイズが増えたタイミングです。古いバックアップの保持期限が切れて削除されるタイミングで、そのバックアップを参照しているバックアップのサイズが増えることがわかります
* 週次バックアップの保存期間は約1か月なので、観測期間中は削除を確認できませんでした。
* 日次・週次・年次でバックアップスケジュールが重なる場合は、保持期限が最も長いバックアップが優先され、他のバックアップは実行されていないようです
* 日次も週次も同じように差分バックアップが取得され、週次だからといって前回週次バックアップからの差分がとられるということはなく、前回バックアップからの差分が取得されています
* なお、Webコンソールからバックアップを参照すると、サイズがGB単位で表示されるのですが、"unique-size-in-mbs"の値が1027MBと、1GBに近い値でも繰り上がって2GBと表示されるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/adb54569-ad65-b87b-3c90-7190185a2706.png)
【Laravel5.5】キャッシュクリアコマンドと、まとめて実行する方法

Laravel5.5使用時の例です。
ファイルの変更を反映した後、実行しておきたいキャッシュクリアコマンド。

```
php artisan cache:clear
```
→「storage/framework/cache/data」内のキャッシュデータを削除する。

```
php artisan view:clear
```
→「storage/framework/views」内に全ビューのキャッシュデータを削除する。

```
php artisan config:clear
```
→「config」ディレクトリのファイルの更新内容が反映されるようになる。

```
php artisan route:clear
```
→「bootstrap/cache/routes.php」のRouteのキャッシュデータを削除する。

※ 各コマンドで何しているかは、
https://blog.capilano-fw.com/?p=768 より引用しました。
こちらのサイトにはとてもお世話になっております。感謝永遠に。。


## まとめて実行するには…

&&で繋げると順番に実行可能。

```
php artisan cache:clear && php artisan view:clear && php artisan config:clear && php artisan route:clear
```

systemディレクトリ直下にシェルスクリプトを作成する方法もある。

```ruby:clear_cache.sh
php artisan cache:clear
php artisan view:clear
php artisan config:clear
php artisan route:clear

//最後に改行を入れる
```
上記では「clear_cache.sh」というファイル名にしているので、
systemディレクトリにいる状態で、
下記のコマンドでまとめて実行することができる。

```
sh clear_cache.sh
```
楽。よき。
Synology NAS DS218J+　redmine 4へのバージョンアップ

##背景
+ SynologyのNASを使って、最新のREDMINE　V4をインストールする方法を示す。
+ DSMのパッケージセンタでは、古いバージョンしか入らなかった。
+ redmineはDOCKERパッケージ（sameersbn/docker-redmine）をGUIで立ち上げた。

##準備
先ずは別にDOCKERイメージを持ってくる。（ここまではググれば、出てくるので割愛します）

DSMのパッケージを使わないと、このまま立ち上げても環境設定されないのでエラーになる
（知らんかったけど、DOCKERって環境設定しないと動かないんですね・・・）

 ![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212914/56bc9b05-151f-e6a8-1e63-d15cd429e642.png)

##課題
+ VOLUME設定の.SOCKファイルは、DSMのGUIから変更できないところで、ハマりまくった
+ 
以下、参考にしたURL

https://github.com/sameersbn/docker-redmine/issues/399

###手順

1) 新しいコンテナを選んで　設定　→　エクスポート　→　適当な場所に保存
2) 落とした```redmine.sino.json```　→　テキストエディタで開く
3) 環境設定、VOLUME設定を入力する　→　元のREDMINEのコンテナの詳細を見ながら転記する。
4) 1)と同じ手順で、次はインポートする　（ここで名前を変えるよう要求される）
5) 新しくコンテナができる。　→　実行すると無事に起動できた。

##redmine.sino.json
追加するものは、DBに関係するもの

```
  "env_variables" : [
      {
         "key" : "HOME",
         "value" : "/root"
      },
      {
         "key" : "DB_PASS",
         "value" : 転記する
      },
      {
         "key" : "DB_USER",
         "value" : "redmine_user"
      },
      {
         "key" : "DB_NAME",
         "value" : "redmine"
      },
      {
         "key" : "DB_HOST",
         "value" : "localhost"
      },
      {
         "key" : "DB_TYPE",
         "value" : "mysql"
      },
     
```

VOLUMSに関するもの

```
   "volume_bindings" : [
      {
         "host_volume_file" : "/docker/redmine",
         "mount_point" : "/home/redmine/data",
         "type" : "rw"
      },
      {
         "host_volume_file" : "/docker/mysqld/mysqld-redmine.sock",
         "mount_point" : "/var/run/mysqld/mysqld.sock",
         "type" : "rw"
      }
   ],
```


##pluginsのインストール

pluginsが入らない　→　下記参照
https://qiita.com/carbonss/items/9ec248c41df2f91cc0cc

何度やっても動かない・・・　断念かっ！

```log
2021-02-07 08:14:08,772 INFO gave up: unicorn entered FATAL state, too many start retries too quickly
```

##Theme のインストール

DSMにインストールしたDockerコンテナのREDMINEをカスタマイズする手順
（テーマやプラグインは、ZIPファイルになっている場合）

* ウィンドウズからDSMにSSH接続する。
* REMOTEマシンから、dockerコンテナ上のBASHシェルを起動する　

```
moto@pypy2:~$ pwd
/var/services/homes/moto
moto@pypy2:~$ sudo su
Password:
ash-4.3# docker ps
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS                                           NAMES
6b4cf96a2ca4        sameersbn/redmine:latest   "/sbin/entrypoint.sh…"   13 days ago         Up 8 days           0.0.0.0:32781->80/tcp, 0.0.0.0:32768->443/tcp   redmine1
ash-4.3# docker exec -it redmine1 bash
root@redmine1:/home/redmine/redmine#
```

* コンテナ上のシェルにはWGET,CURLが入っていない　→　唯一、GITは起動できる状態・・・

```
root@redmine1:/home/redmine/redmine# wget
bash: wget: command not found
root@redmine1:/home/redmine/redmine# curl
bash: curl: command not found
root@redmine1:/home/redmine/redmine# git --version
git version 2.27.0
root@redmine1:/home/redmine/redmine#
```

* 自分のGITリポジトリ上に、ZIPを解凍していれる。→　ここがミソ
* コンテナ上でgit cloneを行う

→　これでREDMINEのプラグインが自由に入れられる状態になった。
Eclipseでサーバを再起動しないでもソースの変更を反映できるようにする

デバック中に気がついたところを修正しちゃうことがよくあります。
修正したところをサーバで反映してもらうために再起動するのは面倒くさいです。
ちなみに「再起動しないでもソースの変更を反映」する方法と覚えていたのですが「ホットデプロイ(HotDeploy)」というそうです。


1. Eclipseを起動し、ローカル・ホストのサーバをダブルクリックして設定を開く![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/92bbd82e-3e7a-a3b1-cbb0-bfabd58dbc16.png)
1. [公開] > [リソースの変更時に自動的に公開] > ON > [公開間隔] > 1 か 0 に設定
1. [タイムアウト] > [開始] > 100以上の大きめの時間に設定![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/3c5fa161-bd32-2f4b-b855-5bf8eee1bfef.png)
1. server.xml(Tomcatの場合)にある`Context`の`reloadable`を「false」に変更する
    - server.xmlの場所 : [いろんなファイルの場所 - Qiita](https://qiita.com/ponsuke0531/items/ddde9c80360777a991fc)
    - またはサーバからアプリを削除して再度追加する
1. サーバをデバックモードで起動
    - Javaメソッド内部で行った変更が即座にサーバーへデプロイされるようになり、変更の度にサーバーを起動する時間が短縮:heart:

```xml:server.xml
<!--省略：下の方にある(はず)-->
  <Context ... reloadable="false" .../>
<!--省略-->
```
re:Invent 2020 ストレージ関連の新サービス、アップデートまとめ

re:Invent2020で発表されたEBS、EFS、S3等のストレージ関連サービスのアップデートをまとめてみました。

[re:Invent スペシャル企画 まだまだやるよ！宇宙一 回数の多い re:Cap week8](https://jawsug-yokohama.connpass.com/event/201083/)
でこのあたりをキャッチアップしますので是非ご参加ください！

# EBS
## gp3 volumes for EBS
- 3,000 IOPS、125MB/sのベースライン・パフォーマンス
- 最大16000IOPS

JAWS-UG横浜のre:Cap week1で発表した資料に詳しいことは残しています。
https://www.slideshare.net/akifuminiida/jawsug-yokohama-recapweek1gp3

https://aws.amazon.com/jp/blogs/news/new-amazon-ebs-gp3-volume-lets-you-provision-performance-separate-from-capacity-and-offers-20-lower-price/

## io2 Block Express
- 最大 256 K IOPS と 4000 MBps のスループット
- 最大 64 TiB のボリュームサイズ

https://aws.amazon.com/jp/blogs/news/now-in-preview-larger-faster-io2-ebs-volumes-with-higher-throughput/

## スループット最適化 HDD (ST1) とコールド HDD ボリューム (SC1) の最小ボリュームサイズを75%削減
- 最小ボリュームサイズ125GBから作成可能に（従来は500GB）
- 
https://aws.amazon.com/jp/about-aws/whats-new/2020/12/amazon-ebs-reduces-minimum-volume-size-throughput-optimized-hdd-cold-hdd-volumes/

# EFS
## Amazon EFS ストレージの使用状況がモニタリング可能に
- EFSコンソールからStorageBytes メトリクスが確認可能
- CloudWatch コンソール、その API、CLI、および AWS SDK からモニタリング可能

https://aws.amazon.com/jp/about-aws/whats-new/2021/01/monitor-your-amazon-efs-storage-usage-with-amazon-cloudwatch/

# S3
## Amazon S3が強力な書込み後の読み取り整合性
- S3 の GET、PUT、LIST 操作のすべて、およびオブジェクトタグ、ACL、またはメタデータを変更する操作に強力な整合性を適用
- 既存および新規の S3 オブジェクトすべてに適用

https://aws.amazon.com/jp/blogs/news/amazon-s3-update-strong-read-after-write-consistency/

## Amazon S3 Replication が複数の宛先バケットのサポートを開始
- 異なるストレージクラス、異なる暗号化タイプ、または異なるアカウント全体でデータの複数のコピーを保存
-  [レプリケーションステータス] を確認可能

https://aws.amazon.com/jp/blogs/news/new-amazon-s3-replication-adds-support-for-multiple-destination-buckets/

## Amazon S3 Replication 双方向レプリケーションのサポート
- オブジェクトアクセス制御リスト（ACL）、オブジェクトタグ、複製されたオブジェクトのオブジェクトロックなどのメタデータの変更を簡単に複製
- S3管理コンソールまたはAmazonCloudWatchでオブジェクトとオブジェクトメタデータのレプリケーションの進行状況を監視

https://aws.amazon.com/jp/about-aws/whats-new/2020/12/amazon-s3-replication-adds-support-two-way-replication/

## Amazon S3 Bucket Keys
- KMSで行っていたデータキーの生成、暗号化操作をS3バケットキーが実施
- SSE-KMSで暗号化する場合のコストが最大99%下がる

https://aws.amazon.com/jp/about-aws/whats-new/2020/12/amazon-s3-bucket-keys-reduce-the-costs-of-server-side-encryption-with-aws-key-management-service-sse-kms/

https://dev.classmethod.jp/articles/s3-bucket-keys/
AWSでproduction.logが肥大化した時の対処方法 & ログローテート方法

AWS初学者です。

Railsで個人的にアプリを作っておりまして、AWSにデプロイしています。
昨日も新しい機能を追加したため、変更内容をAWSにデプロイしようとしたところエラーが発生しました。

EC2にSSH接続し、「df -h」で容量を確認したところ、　
「/dev/xvda1」の使用率が100%に…

「どこの容量が多いのか」をさらに深掘りして調べてみたところ、

「/var/www/アプリのディレクトリ名/shared/log/production.log」

というログファイルがかなり多いことがわかりました。その容量はなんと3G！？
今まで放っておいた自分を反省しました😅

そして、何とかproduction.logを軽量化し、正常にデプロイさせることができたので、その方法をアウトプットしていきたいと思います。

（ちなみに、「どこの容量が多いか」を調べる方法については、こちらの記事で説明しています：<a href="https://qiita.com/H-Iida/items/ddb3c7e22edc806238ea">容量がいっぱいでAWSにデプロイできなかった時の対処方法</a>）

# production.logの軽量化
まずは、この肥大化したproduction.logを軽量化していきます。

「/var/www/アプリのディレクトリ名/shared/log」
まで移動したら次のコマンドを実行します。

```none:ターミナル
[log]$ echo '' > ./production.log
```

「echo 文字列 > ファイル名」とすることで、指定したファイルに文字列を出力（上書き）できるようです。
上記のコマンドを実行すれば、production.log内は''という空の文字で上書きされます。つまり、production.logの中身を一度空にすることができるわけです。

これを実行した後したところ、無事容量を約3Gまるまる減らすことに成功しました！

```none:ターミナル

①まず容量を確認
[log]$ sudo du -sm ./* | sort -rn | head -3
3162	./production.log
73	    ./unicorn.stderr.log
0	    ./unicorn.stdout.log

②空の文字で上書き
[log]$ echo ' ' > ./production.log

③prodction.logの容量を減らすことに成功！
[log]$ sudo du -sm ./* | sort -rn | head -3
73	./unicorn.stderr.log
1	./production.log
0	./unicorn.stdout.log
```

この後、無事デプロイすることができました！

# ログローテートの設定
しかし、安心するのはまだ早いです。
まだ、ログローテートの設定が残っています。

ログローテートとは、ログを定期的に削除することで、ログが肥大化することを防ぐことを言います。

僕が使用しているRails6の場合は、
「config/environments/production.rb」
に以下の設定を追加することで、ログローテートの設定をすることができました。

```ruby:production.rb
# production.rb内で、「一週間より前のログを切り捨てる」というログローテートを設定
  config.logger = Logger.new("log/production.log", 'weekly')
```

上記の場合ですと、「一週間より前のログを切り捨てる」というログローテートを設定していますが、weeklyの部分は、

「daily（一日で切り捨て）」
「monthly（一ヶ月で切り捨て）」

に変更することもできます。

# 参考にした記事
以下、参考にさせていただきました。
ありがとうございました。

<a href="https://qiita.com/yupsy/items/ac2e49770e5313f31ceb">Railsでログの設定＋ローテートを行う</a>

以上です。
もしご指摘などありましたら、教えていただけますと幸いです。

ここまで読んでくださりありがとうございました🙇‍♂️
変数の巻き上げ

## 内容
変数の巻き上げについて書く。

## 変数の巻き上げ
グローバルスコープ内で変数を宣言すると、宣言処理はグローバルスコープの先頭に巻き上げられる。

例えば、以下のようなコードがあったとする。

```javascript
console.log("1行目：" + x); // 変数の宣言前に変数xを使用
var x = "initialize"; // 変数xを宣言
console.log("3行目：" + x);
````

普通に考えると、1行目は変数の宣言前なのでReferenceErrorになる気がする。
が、実行してみるとこうなる。

```result
1行目：undefined
````

これは、変数の巻き上げによって、変数xの宣言処理がコードの先頭に巻き上げられたため。
イメージとしては、こんな感じになっている。

```javascript
var x; // 変数の宣言処理だけ、先頭に移動
console.log("1行目：" + x);
x = "initialize"; // 変数の初期化処理はそのままの位置
console.log("3行目：" + x);
````

## 関数内での変数の巻き上げ
関数内で変数が宣言されている場合も変数の巻き上げは発生する。
関数内で変数が宣言されている場合は、その関数の先頭に巻き上げられる。

例えば、こんなコードがあったとする。
これは関数内での巻き上げが発生しないやつ。

```javascript
var x = "A";
function testPrint(){
   console.log(x);
}
testPrint();
````

こいつの動作結果は、こんな感じ。イメージ通りの動きである。

```result
A
````

一方、これは関数内で変数を宣言して巻き上げが発生するやつ。

```javascript
var x = "A";
function testPrint(){
  console.log(x);
  var x = "B";
}
testPrint(); // undefined
````

この実行結果は、こうなる。

```result
undefined
````

何でそうなるかっていうと、巻き上げによってこんな感じの動作になっているから。
関数の先頭でxが再宣言されることで、console.log(x)がundefined（未定義）になるんすね。

```javascript
var x;
x = "A";
function testPrint(){
  var x;
  console.log(x);
  x = "B";
}
testPrint(); // undefined
````

## 関数の宣言も巻き上がるぞ
変数だけじゃなくて関数も巻き上がる。
関数の巻き上げは、割と自然に受け入れられる。
例えば、これは巻き上げの例。

```javascript
testPrint("Yamada");
function testPrint(item) {
  console.log(item);
}
````

こいつの実行結果は、こうなる

```result
Yamada
````

割と普通の動きに見える。
でも、よく考えるとtestPrint関数が定義される前にtestPrint関数を呼び出しているのに、普通に呼び出せてるのはなんでだろう。
理由は、巻き上げによってこんな感じの動作になってるから。

```javascript
function testPrint(item) { // 巻き上げで関数の定義処理が先頭に移動した
  console.log(item);
}
testPrint("Yamada");
````

つまり、巻き上げがあることによって、関数はどのタイミングでも呼び出せるようになってるってこと。

## でも、関数式は巻き上がらないぞ
ややこしいけど関数式を使うとまきあがらない
関数式は宣言じゃないからね。関数式を代入された変数の方は、もちろん巻き上がる。

これは、変数が巻き上がることを確認するコード。

```javascript
console.log(myFunction); // => undefined
var myFunction = function() {
  console.log('Hello');
};
````

こっちは、関数式でかかれた関数は巻き上がらないことを確認するコード。

```javascript
myFunction(); // => TypeError: myFunction は関数ではない
var myFunction= function() {
  console.log('Hello');
};
````

## 変数であっても定義を書かなければ巻き上がらない
変数であっても、定義処理を書かなかったら巻き上がらない。
例えば、これは巻き上がらない

```javascript
console.log(x); // => ReferenceError 例外が発生
x= “initialize”; // varを省略して初期化
````

## letやconstは、巻き上がらない（ようにふるまう）ので安心
letやconsotを使うと巻き上がりを無視して実装できる。
正確にはletもconsotも巻き上がるが、変数の初期化処理が行われるまでJavaScriptが一時的にプログラムから見えなくしてくれる。ので、巻き上がってないかのように使える。

こんなコードがあるとする。

```javascript
console.log(x); // => ReferenceErrorが発生。巻き上がってないように見える。
let x = “initialize”; // 変数xの宣言処理
````

実際は、こんな感じで巻き上がるけ。
けど、不思議な大地の力で他の処理から変数が見えなくなってなかったことにされる。

```javascript
let x; // 宣言処理は先頭に巻き上がる
console.log(x); // => ReferenceErrorが発生。不思議な力で変数xが隠される。
x = “initialize”; // 初期化
```

## 参考
https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Grammar_and_types
https://developer.mozilla.org/ja/docs/Glossary/Hoisting
Mew の補完を別のものに置き換える

# update 2022-02-19
- Emacs "28.0.91", "29.0.50" だと、エラーで Mew が起動しないので回避策を入れる.
- 管理法を変えたためソース区別用の Revision が大きく変わっています.

# mew-without-complete-mode
Mew でミニバッファからフォルダ指定する場面の補完器を `ido` や `helm` 等、普段使っているものに変更します。

[mew-without-complete-mode.el](https://github.com/s-fubuki/mew-without-complete-mode.el)をダウンロードし `load-path` の通った処にコピーして `.mew.el` 等に以下を書き加えます。

```emacs-lisp:source.el
(require 'mew-without-complete-mode)
(mew-without-complete-mode 1)
```

通常リファイル先はカンマで切って列挙できますが性質上それができなくなります。 一時的に不要なときは非アクティブにして回避してください。 コマンド実行するとオン/オフがトグルします。

```emacs-lisp:sample
M-x mew-without-complete-mode
```


# ido の場合
ido の場合 [ido-completing-read+](https://github.com/DarwinAwardWinner/ido-completing-read-plus) 等もいるので、[設定法](https://qiita.com/s-fubuki/items/d434d1503d126d9dcc40)を書いたのでよければ参考にしてください。

# 蛇足
win10 で `fiber.exe` が動かなくなって `C-c C-e` で外部ブラウザが起動できなくなったので fiber を介さず 外部ブラウザを起動するやつです。 現行の Mew では eww で表示されるようになってはいるのですが...
必要ならこれも `.mew.el` 等に書きます.

```emacs-lisp:source.el
(advice-add 'mew-mime-markup-language-ext :override 'mew-mime-markup-language-ext-new)
(defun mew-mime-markup-language-ext-new (program cache begin end params tag form)
  (let* ((file (format form (mew-make-temp-name))))
    (with-current-buffer cache
      (message "Displaying %s..." tag)
      (mew-frwlet mew-cs-dummy (mew-text/html-detect-cs begin end)
        (write-region begin end file nil 'no-msg)
        (w32-shell-execute "open" file))
      (message "Displaying %s...done" tag))))
```

# 更なる蛇足
これを書いて動作確認等のために Mew のマニュアルを読み直して、Mew の補完が結構高機能だったことを今頃知りました(ヒント: `C-s`)。
結構便利で知っていればこの拡張を書かなかったかもしれないと思いました。