Appbook

アプリケーション開発の関連事項に関するメモやgistのまとめ。

ドメイン

URL vs. URI

用語意味
URL (Uniform Resource Locator)位置(Location)を示す URLhttp://google.com
URI (Uniform Resource Identifier)URI には位置を示す URL と 名前を示す URN があるURL と URIの両方
URN (Uniform Resource Name)名前(Name)を示す URNurn:schemas-microsoft-com:asm.v1

用語

用語意味
Apexドメイン (ネイキッドドメイン)先頭に何も付かないドメイン名(example.comとか)
FQDN(Fully Qualified Domain Name)ドメイン名 + ホスト名
ドメイン名example.comなど
ホスト(サブドメイン)www.example.comなどドメイン名のwww
ポート8000など
schemehttp
プロトコルhttp: (※1)

※1:

JSではプロトコルは:まで入る

new URL("http://google.com").protocol
// http:

SchemeはRFCではとなっている

<scheme>:<scheme-specific-part>

REFERENCES:

  • https://www.kagoya.jp/howto/network/fqdn/
  • https://qiita.com/Zuishin/items/3bd56117ab08ec2ec818
  • http://var.blog.jp/archives/58464918.html

DNS

DNSの必要な理由

名前解決(IPアドレスとホスト名の解決)をするため

IPアドレスとホスト名の原始的な解決方法

ARPANETで使用されていた名前解決方法。 ホスト名が数百を超えてから破綻してきた。

$ cat /etc/hosts
127.0.0.1       localhost

つまり、ホスト名を分散して管理する必要があった。 また、ホスト名のユニーク性の問題もあった

⇒ ドメインツリーとDNS

ドメインツリーとDNS

ドメインツリー

  • そこでピリオドごとにドメイン名を階層構造にした
  • 仕組みはファイルシステムと似ているツリー構造
    • FSではルートは/だが、DNSではルートは.となる
  • 階層ごとに別々のDNSサーバーを用意して分散して管理した

DNSの持っている情報

  • 自身の下位ドメイン(サブドメイン)として何があるのか。そのサブドメインの情報を持っているDNSサーバは何か
  • 自身に所属するホストの情報(IPアドレスなど)

DNSの名前解決方法

  • ルートサーバー(.)からサブドメインのDNSサーバーを探索して、最終的なIPアドレス(ホスト)を探す
  • つまり、上位ドメインからサブドメインに対する「権限委譲(delegation)」がされている

FSとDNSのアナロジー

FSDNS
ディレクトリ、フォルダDNS
ファイルIPアドレス (ホスト名)
Absolute pathFQDN(Fully Qualified Domain Name)

FSの絶対パスの例: /home/mike/Workspace/test
DNSのFQDNの例: www.example.com.

DNSの持っている情報

  • 各ノードで管理されるDNS情報の単位を「ゾーン」
  • ゾーンに含まれるデータの単位が「レコード」

レコードの種類

Recordmeaning
SOA (Start Of a zone Of Authority)ゾーンのメタ情報
NSドメインのDNSサーバーを示す
AホストのIPアドレス
CNAMEホスト名のエイリアス(別名)
PTRIPアドレスに対するホスト名
MXメール

RDBとNDSのアナロジー

RDBDNS
TableZone
RecordRecord

正引きと逆引き

TermMeaning
正引きDomain -> IP addr (NSとAレコードを使用する)
逆引きIP addr -> Domain (PTRレコードを使用する)

リカーシブとイテレーティブ

  • DNSサーバーは2つの役割がある。
    • リゾルバの役割をするDNSサーバー(リカーシブな処理をする)
    • イテレーティブはいわゆるゾーン情報をリゾルバに返すDNSサーバー
DNSの処理意味
リカーシブDNSサーバはDNS解決が完結するまでドメイン・ツリーをたどり、(ほかのサーバに対して)検索を行い、最終結果を返す
イテレーティブ自身が管理しているゾーン情報にのみ返答し、ほかのサーバへ問い合わせを行うことはない

「逆引き」と「逆引き用ドメイン・ツリー」

  • 逆引きの場合用に、ドメインツリーが用意されている。
  • .in-addr.arpaがそのドメインとして割り当てられている
  • IPアドレスのオクテットごとにDNSサーバーが用意されている

例)

あるIPアドレス192.168.100.10の問い合わせは、10.100.168.192.in-addr.arpaのドメイン名として問い合わせられる

references:

  • https://www.atmarkit.co.jp/ait/articles/0112/18/news001.html
  • https://toshost.com/a/how-works-dns-server

DNSの例

$ dig appbook.org +trace

; <<>> DiG 9.16.6 <<>> appbook.org +trace
;; global options: +cmd
.                       485459  IN      NS      m.root-servers.net.
.                       485459  IN      NS      a.root-servers.net.
.                       485459  IN      NS      b.root-servers.net.
.                       485459  IN      NS      c.root-servers.net.
.                       485459  IN      NS      d.root-servers.net.
.                       485459  IN      NS      e.root-servers.net.
.                       485459  IN      NS      f.root-servers.net.
.                       485459  IN      NS      g.root-servers.net.
.                       485459  IN      NS      h.root-servers.net.
.                       485459  IN      NS      i.root-servers.net.
.                       485459  IN      NS      j.root-servers.net.
.                       485459  IN      NS      k.root-servers.net.
.                       485459  IN      NS      l.root-servers.net.
;; Received 811 bytes from 192.168.0.1#53(192.168.0.1) in 16 ms

org.                    172800  IN      NS      a2.org.afilias-nst.info.
org.                    172800  IN      NS      b2.org.afilias-nst.org.
org.                    172800  IN      NS      c0.org.afilias-nst.info.
org.                    172800  IN      NS      d0.org.afilias-nst.org.
org.                    172800  IN      NS      b0.org.afilias-nst.org.
org.                    172800  IN      NS      a0.org.afilias-nst.info.
org.                    86400   IN      DS      17883 7 1 38C5CF93B369C7557E0515FAAA57060F1BFB12C1
org.                    86400   IN      DS      17883 7 2 D889CAD790F01979E860D6627B58F85AB554E0E491FE06515F35548D 1EB4E6EE
org.                    86400   IN      RRSIG   DS 8 1 86400 20200922050000 20200909040000 46594 . JVQJLh5YWxjxbsQdRsY2QyAetomU6r/08Fj+BZWdnBo+d0iMhm4z6wAn nEZXz9n2BjyA36q/PRtPnNxyD9OdqsbZCGnM2zVeSnqC1hRdjRjKLFRN N3UndCutELQRnD5ufV3qIok0CDSAKkr2epjLzDwSWxLe5cZ/SFIY8RJA k4qGDl1ZNbeBKWWG6cHqfS49iEJtSuPhsLNkkHtQ63zy21PEvmsI4lkQ 9JGbZ6Hjcwa6tVYLWrCFkkWrUagfoYi/4IcBYGWwbflGsKZlH6oW7R7U 1PQWt2kvMJ3CCWfhrU5uWzEPyg2nomQO4HzB3fdC+eLvlm6H+4i6o+G8 xq3cTw==
;; Received 841 bytes from 2001:500:2::c#53(c.root-servers.net) in 120 ms

appbook.org.            86400   IN      NS      dns3.p07.nsone.net.
appbook.org.            86400   IN      NS      dns4.p07.nsone.net.
appbook.org.            86400   IN      NS      dns2.p07.nsone.net.
appbook.org.            86400   IN      NS      dns1.p07.nsone.net.
h9p7u7tr2u91d0v0ljs9l1gidnp90u3h.org. 86400 IN NSEC3 1 1 1 D399EAAB H9P94CHNCUOADBOKM57JBRIMA2O6J0IQ NS SOA RRSIG DNSKEY NSEC3PARAM
h9p7u7tr2u91d0v0ljs9l1gidnp90u3h.org. 86400 IN RRSIG NSEC3 7 2 86400 20200930065354 20200909055354 22064 org. BrNflnsAe4Xxf8ImPYqz0f1buZnrUbSSNdWtx1UMj/a6okEd6QmDad3W VrsqwH8cm3TRAsVbL60h9XUTKJux7nj5LQI3xGoBGI/tNJiF5CLx99Ae a8DIS2Z9m50GjawiSmA6aGMnGbUyf+4FZr9QF6NJbMxKnTHsrplV7/0y JR4=
mlmrq45pvhg1pk97h54t1fq132qb9iv9.org. 86400 IN NSEC3 1 1 1 D399EAAB MLMV6G5I4LBOGE70KMNSQ6CO5272QL0D NS DS RRSIG
mlmrq45pvhg1pk97h54t1fq132qb9iv9.org. 86400 IN RRSIG NSEC3 7 2 86400 20200924144652 20200903134652 22064 org. qqo/Z5TQyFDEb1oJRir1dW1qlyMdB+n1woHWrOTkqRZZImP4bj/YJi0g EtEj4fUbu848Gf5DzBIVpWt+/VoeTvbq4J5CNM4f4Oqgc4azJCTOebbs KZdhXRc6UAf2H3A4hDTw+9fq5KY05P2n04EqXPy2Qdlo33JCLwHZo4tM O5E=
;; Received 622 bytes from 2001:500:c::1#53(b0.org.afilias-nst.org) in 90 ms

appbook.org.            20      IN      A       134.209.106.40
appbook.org.            20      IN      A       128.199.185.38
;; Received 72 bytes from 198.51.44.71#53(dns3.p07.nsone.net) in 10 ms
$ whois appbook.org
Domain Name: APPBOOK.ORG
Registry Domain ID: D402200000014574835-LROR
Registrar WHOIS Server: whois.discount-domain.com
Registrar URL: www.onamae.com
Updated Date: 2020-09-06T08:19:52Z
Creation Date: 2020-09-06T02:46:49Z
Registry Expiry Date: 2021-09-06T02:46:49Z
Registrar Registration Expiration Date:
Registrar: GMO Internet, Inc. d/b/a Onamae.com
Registrar IANA ID: 49
Registrar Abuse Contact Email: abuse@gmo.jp
Registrar Abuse Contact Phone: +81.337709199
Reseller:
Domain Status: serverTransferProhibited https://icann.org/epp#serverTransferProhibited
Domain Status: addPeriod https://icann.org/epp#addPeriod
Registrant Organization: Whois Privacy Protection Service by onamae.com
Registrant State/Province: Tokyo
Registrant Country: JP
Name Server: DNS1.P07.NSONE.NET
Name Server: DNS2.P07.NSONE.NET
Name Server: DNS3.P07.NSONE.NET
Name Server: DNS4.P07.NSONE.NET
DNSSEC: unsigned
URL of the ICANN Whois Inaccuracy Complaint Form https://www.icann.org/wicf/)
>>> Last update of WHOIS database: 2020

DNS レコード

レコード意味
Aドメインを IP アドレスに関連付ける
cnameエイリアス名を実際の「正規」ドメイン名にリンクする
NSネームサーバー
MX受信用メールサーバー
TXT (SPF多目的。ドメインの所有権の確認やメールのセキュリティなど
SRV負荷分散サービスの提供/冗長性の確保/サービスポート番号の通知を可能

NOTE: ZONE APEXドメインの場合はNSレコードとSOAレコードは必須

Aレコード

$ dig appbook.org a +short
157.230.45.115
157.230.37.202

ネームサーバー探し

$ dig appbook.org ns +short
dns1.p07.nsone.net.
dns2.p07.nsone.net.
dns3.p07.nsone.net.
dns4.p07.nsone.net.

メール受信サーバー探し

$ dig gmail.com mx +short
20 alt2.gmail-smtp-in.l.google.com.
30 alt3.gmail-smtp-in.l.google.com.
10 alt1.gmail-smtp-in.l.google.com.
40 alt4.gmail-smtp-in.l.google.com.
5 gmail-smtp-in.l.google.com.

Txtレコード

$ dig google.com txt +short
"docusign=1b0a6754-49b1-4db5-8540-d2c12664b289"
"v=spf1 include:_spf.google.com ~all"
"docusign=05958488-4752-4ef2-95eb-aa7ba8a3bd0e"
"globalsign-smime-dv=CDYX+XFHUw2wml6/Gb8+59BsH31KzUr6c1l2BPvqKX8="
"facebook-domain-verification=22rm551cu4k0ab0bxsw536tlds4h95"

CNAME

  • ※ ZONE APEXに対しては、CNAMEが設定出来ない
  • なぜなら、ZONE APEXは「SOAレコードとNSレコードの設定が必須」なのに対し、
  • CNAMEを設定した場合「他のレコードの設定が不可」となり、両者が矛盾してしまうから
$ dig www.amazon.com cname +short
tp.47cf2c8c9-frontier.amazon.com.

CNAMEの特性

同じドメインやサブドメインはだめ。

  • www.example.com. CNAME aaa.example.com.
  • www.example.com. CNAME bbb.example.com.

別タイプのレコードもだめ。

  • www.example.com. CNAME aaa.example.com.
  • www.example.com. A 1.2.3.4

Zone ApexにはNSレコードが必要

  • example.com. NS example.content.jp.

how does the TLD name server know the address of the Authoritative Name server

The answer is simple: when you purchase any domain with the registrars like Godaddy or Namecheap, the registrars also communicate the domains to the TLD name server. So it is able to contact the Authoritative Name servers

REFERENCES:

  • https://support.google.com/a/topic/2716885?hl=ja&ref_topic=3540977
  • https://blog.serverworks.co.jp/tech/2016/07/07/zone-apex-cname/
  • https://tech.jstream.jp/blog/cdn/zone_apex_cdn/
  • https://serverfault.com/questions/588244/what-is-the-role-of-ns-records-at-the-apex-of-a-dns-domain
  • https://www.freecodecamp.org/news/understanding-the-domain-name-servers-46c6bcf9afa3/

A vs CNAME

Domain name is parent of ip address
domain name : ip addr = 1:N

$ dig yahoo.com

; <<>> DiG 9.14.8 <<>> yahoo.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46812
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;yahoo.com.                     IN      A

;; ANSWER SECTION:
yahoo.com.              953     IN      A       98.138.219.232
yahoo.com.              953     IN      A       98.138.219.231
yahoo.com.              953     IN      A       72.30.35.9
yahoo.com.              953     IN      A       98.137.246.8
yahoo.com.              953     IN      A       72.30.35.10
yahoo.com.              953     IN      A       98.137.246.7

;; Query time: 12 msec
;; SERVER: 192.168.0.1#53(192.168.0.1)
;; WHEN: 火 12月 31 22:21:38 JST 2019
;; MSG SIZE  rcvd: 134

Difference between A Record and CNAM

record typemeaning
A(Address)Domain Name to Ip Addr
CNAME (Canonical name)Domain Name to Domain name

https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/

IPアドレス

インタネットの住所

IPアドレスの構成

IPアドレスは次の2つのパーツから成る

IPアドレスのパーツ意味
ネットワーク部ネットワークを示す。具体的には、ルーターなどのネットワーク機器で区切られた範囲
ホスト部ネットワークに属するホストを識別するための情報

特別なIPアドレス

IPアドレスの中にも、特別な意味をもつIPアドレスがある。

IPアドレスの種類意味記法
ネットワークアドレスネットワーク自体を示すアドレスホスト部のビットが全て0
ブロードキャストアドレスそのネットワーク内の全てのホストにデータを送信するために使われるアドレスホスト部のビットが全て1
ループバックアドレス自分自身を示すIPアドレスIPv4では127.0.0.1が使われている(ホスト名はlocalhost)

IPアドレスの種類

IPアドレスはそのアドレスの値によって、2種類に分けられる。

IPアドレスの種類属するネットワークアドレスの範囲
グローバルIPアドレスWAN (Internet)クラスA~Eまでの範囲
ローカルIPアドレスLAN (Intranet)クラスA~E以外の範囲

IPアドレスのネットワーク部とホスト部の識別方法

歴史的に次の2種類が存在している

分類方法意味メタ
クラスクラスによる分類(クラスA,B,Cなど)クラスフルアドレス
サブネットマスクサブネットマスクによる分類(CIDRはこれを簡略化したもの)クラスレスアドレス

クラス

  • IPアドレスの範囲は0.0.0.0 ~ 255.255.255.255だが、
  • クラスとして定義されているアドレスの範囲が、プライベートアドレスの範囲
  • サブネットマスクは固定で決まっている
  • ネットワークを大雑把に決めるのには良い
クラスIPアドレスの範囲既定のサブネットマスク割当可能なホスト数
クラスA10.0.0.0 ~ 10.255.255.255255.0.0.016777214個
クラスB172.16.0.0 ~ 172.31.255.255255.255.0.064434個
クラスC192.168.0.0 ~ 192.168.255.255255.255.255.0254個

サブネットマスク

  • クレスレスアドレスの場合は、サブネットマスクを使ってネットワーク部とホスト部の範囲を指定する
  • プライベートIPアドレスを作りたい場合は、クラスとして定義されているアドレスの範囲が、プライベートアドレスの範囲となるので、その範囲内で作る必要がある

記法1

IPアドレス: 172.20.100.52
サブネットマスク: 255.255.255.0

記法2 (CIDR)

172.20.100.52 /24

サブネットマスクの例

例) IPアドレス=10.0.0.0で、サブネットマスク=255.255.0.0、CIDR=/24、の場合は次となる

属性
入力IP範囲10.0.0.0/16
ネットワーク(CIDR)10.0.0.0/16
サブネット表記10.0.0.0/255.255.0.0
IPアドレス範囲10.0.0.0 - 10.0.255.255
IPアドレス総数65,536
ネットワークIP10.0.0.0
ブロードキャストIP10.0.255.255
ホストアドレス範囲10.0.0.1 - 10.0.255.254 有効ホスト数( 65,534 台 )
サブネットマスク255.255.0.0
クラス属性クラスA

ref https://ipvx.info/ipv4/cidr2extip/#result

REFERENCES:

  • https://support.microsoft.com/ja-jp/help/164015/understanding-tcp-ip-addressing-and-subnetting-basics
  • https://qiita.com/mogulla3/items/efb4c9328d82d24d98e6

サブネット

サブネットとは、クラスA、B、Cのネットワークを複数の小さなネットワークに分割したネットワークのこと。

  • IPアドレスを構成するネットワーク部とホスト部のうち、ホスト部のビットをサブネット部として使用する
  • ことにより、ホスト部のビットをどれだけサブネット部として使用するのかは、NW管理者で自由に決めます。

NOTE:

  • サブネットは特定のルートテーブルと紐付けることができる
  • サブネット:ルートテーブル = 1:N

REFERENCES:

  • https://www.infraexpert.com/study/ip6.html

OSI参照モデル

CIDRブロック

  • VPCのIPアドレスの範囲を指定するのに使う
  • CIDRとSubnet Maskは同じ役割

サブネットの例

$ terraform console
> cidrsubnet("10.0.0.0/16", 8, 0) <= 8bit分(256個)のネットワークを作れる内の1番目のネットワーク。残りの8bit分(256個)をホストに指定できる
10.0.0.0/24
> cidrsubnet("10.0.0.0/16", 8, 1) <= 8bit分(256個)のネットワークを作れる内の2番目のネットワーク。残りの8bit分(256個)をホストに指定できる
10.0.1.0/24
> cidrsubnet("10.0.0.0/16", 8, 255) <===== 256番目のネットワーク
10.0.255.0/24
> cidrsubnet("10.0.0.0/16", 8, 256) <===== 0番目から始まるので257番目はエラー
Error: Error in function call

  on <console-input> line 1:
  (source code not available)

Call to function "cidrsubnet" failed: prefix extension of 8 does not
accommodate a subnet numbered 256.


cidrsubnet("10.0.0.0/16", 16, 65535) <== 16bit分(65536個)のネットワークを作れる内の65536番目のネットワーク。1個ホストに使える
10.0.255.255/32 
> cidrsubnet("10.0.0.0/16", 16, 65536) <===== 0番目から始まるので、65536番目のはエラー
Error: Error in function call

  on <console-input> line 1:
  (source code not available)

Call to function "cidrsubnet" failed: prefix extension of 16 does not
accommodate a subnet numbered 65536.

RFE

  • https://dev.classmethod.jp/cloud/aws/terraform-ipv6-subnet/

パケット

各フィールド英語表記ビット各フィールドの説明
バージョンversion4 bit IPヘッダのバージョン番号の情報。ここでは「4」の値が入る。
ヘッダ長IHL4 bit IPヘッダの長さの情報。単位は32ビットであることからオプションを使用しない。  IPパケットの場合ここでは「5」の値が入る。32bit×5 = 160bit = 20byte。
サービスタイプType of Service8 bit IPパケットの優先順位の情報。例えば音声トラフィックとデータトラフィック  とでは音声トラフィックのデータを優先して送出することができる。QoS処理用。
全長Total Length16 bit IPヘッダを含むパケットの全長。パケット長とも呼ばれる。
識別番号identification16 bit 個々のパケットを識別するための情報。パケットが分割された時に分割された  パケットには同じ識別番号にすることで、受信側で複数の分割されたパケット  を受信した場合においても、この識別番号に基づき正しく組み立て処理できる。
フラグFlags3 bit パケット分割における制御の情報。3ビットの内訳は以下の通り。詳細は別途。
フラグメント オフセットFragment Offset13 bit フラグメントされたパケットが元のパケットのどの位置であったかを示す情報。
生存時間Time to Live ( TTL )8 bit パケットの生存時間を示す情報。実際には、何台のルータ or L3スイッチを  通過することができるのかという情報。1台のルータを通過するごとにTTL値は  「 1 」つずつ減らされて、TTL値が「 0 」になると、パケットは破棄される。
プロトコルProtocol8 bit 上位層(トランスポート層)のプロトコルが何であるのかを示す情報。この値は  ICANNという組織により「プロトコル名」と「番号」が定義されている。例えば、  上位層プロトコルにTCPを使用する場合、このプロトコル番号は「6」になる。
ヘッダ チェックサムHeader Checksum16 bit IPヘッダのチェックサムを表す情報。IPヘッダにエラーがないかをチェック。
送信元IPアドレスSource Address32 bit 32ビット(4byte)で構成された、送信元のIPアドレスの情報
宛先IPアドレスDestination Address32 bit 32ビット(4byte)で構成された、宛先のIPアドレスの情報
オプションOptions可変長 通常は使用されないが、デバックやテストを行う際に使用される情報。
パディングPadding可変長 通常使用されないが、上記のオプションを使用した場合にはIPヘッダ長が  32ビットの整数倍にならない場合がある。32ビットの整数倍にするために  詰め物(Padding)として空データの 「 0 」 の値を入れることにより調整する。

REF

  • https://www.infraexpert.com/study/tcpip1.html

TCPコネクション

  • 四角が状態名
  • 矢印は可能な遷移の経路
  • 矢印のそばの文字はアクション

TCPの接続の原則

データを送信したら、それに対する応答(ACK)を必ず確認する

3way ハンドシェイク

用語意味
アクティブ・オープン先にオープン要求する(SYNパケット)を送信する方
パッシブ・オープンオープンを受信した方

ref

  • https://www.atmarkit.co.jp/ait/articles/0401/29/news080_3.html
  • https://www.atmarkit.co.jp/ait/articles/0402/13/news096_3.html
  • https://www.atmarkit.co.jp/fwin2k/network/baswinlan016/rfc793.txt

EGP/IGP

用語意味
AS (Autonomous System)1つのまとまったネットワーク群のことを指します。具体的には企業が構築しているネットワークや、プロバイダーのネットワークのこと
IGP (Interior Gateway Protocol)ルーター間で通信を行う際に、相手のルーターが自分と同じAS内にいる場合に用いるルーティングプロトコルの総称
EGP (Exterior Gateway Protocol)ASの垣根を超えて通信を行う際に用いられるルーティングプロトコルの総称

ルーティング

ルーティングとは正しい方向へパケットを転送するための処理

ルーティングテーブル (ルートテーブル)

ルーティングテーブルは複数のエントリから構成されていて、宛先のIPアドレス(Destination)をルーター(Target)に中継する役割を持っている

用語

用語意味
Next Hop (Target)次に中継するルーターのIPアドレス
Destination宛先(送信先)ネットワークアドレスと宛先ネットワークアドレスに対するサブネットマスクのビット長

ルーティングの仕組み

  • ルーターが郵便局のような役割をしており、
  • 個々のルーターはその宛先のパケット(郵便物)をどこ(target)に転送するかを知っている
  • 別のネットワーク(地域)の際にはTargetは次のルーター(郵便局)のアドレスにパケットを送る
  • そのバケツリレーの繰り返しで目的のネットワークまでパケットを運ぶ

特別な値

意味
0.0.0.0/0全てのIPv4アドレス
::/0全てのIPv6アドレス
localVPCを示す

VPCのCIDRを10.0.0.0/16と仮定する。
ルートテーブルが紐付けられたサブネットのCIDRを10.0.0.0/24と仮定する。

下のルートを持つルートテーブルの意味は、全てのアドレスが、igwにルーティングされることを示す。

送信先(Desitination)ターゲット
0.0.0.0/0igw-id

例2

このルートを持つルートテーブルの意味は、紐付けられたサブネット内の全ての送信アドレスが、VPCのルーターでルーティングされるということを示す。

送信先(Desitination)ターゲット
0.0.0.0/0ローカル

デフォルトゲートウェイ

ネットワークの出入り口となるルータの総称

REF

  • https://support.microsoft.com/ja-jp/help/164015/understanding-tcp-ip-addressing-and-subnetting-basics

NAT

グローバルIPとプライベートIPアドレスを1:1に変換する機能

ローカルホストとリモートホスト

Email

ヘッダ

Message ID	<479798586.1664704732.1599178606107.JavaMail.mktmail@xxxx.org>
Created at:	Fri, Sep 4, 2020 at 9:16 AM (Delivered after 1 second)
From:	Figma <community@xxx.com>
To:	mike@xxx.co.jp
Subject:	You will not be graded on this
SPF:	PASS with IP 192.28.158.138 Learn more
DKIM:	'PASS' with domain figma.com Learn more
DMARC:	'PASS' Learn more

送信の仕組み

REFERENCES:

  • https://sendgrid.kke.co.jp/blog/?p=12290
  • https://salt.iajapan.org/wpmu/anti_spam/universal/measure/another-address/
  • https://xtech.nikkei.com/it/article/COLUMN/20070706/276898/

SPF and DKIM

SPF (Sender Policy Framework)

一言で言うと、送信元がただしいか検証できる

  • 送信元IPアドレスをチェックすることができるプロトコル
  • 要は、メールのバケツリレーの時に、DNS側にTxtを指定しておいて、そのTxtを元に、メール送信元のIPアドレスは正しいかを確認する

目的:

  • SPFは、そもそもがスパマーが独自の勝手なSMTPサーバーをたてて、適当なメールアドレスを使って、配信するのを防ぐ意図がある
  • 確かにドメイン管理者が指定した情報(ネームサーバーに設定したSPF情報)を元に認証を行うので、送信者を偽装しているかどうか・・・を判断できる?かもしれ ない
  • ただ、このSPFが全てのメールサーバーに適用されているわけでもないので、それほどスパムを排除できないのが現状。
  • ただし、少なくともFailの判定は、スパムの可能性が高いと言える

https://server-setting.info/blog/sender-policy-framework.html

DKIM (Domain Keys Identified Mail)

一言で言うと、メールの内容がただしいか検証できる

  • 電子メールにおける送信ドメイン認証技術の一つであり、 メールを送信する際に送信元が電子署名を行い、 受信者がそれを検証することで、 送信者のなりすましやメールの改ざんを検知できるようにするもの

REFERENCES:

  • https://dev.classmethod.jp/articles/amazon-ses-production/

なぜEmailは偽装できるか?

なぜメールの偽装ができるか? ⇒ 一言で言うと、電子メールと郵便は全く同じ仕組みだから

郵便はいくらでも偽装可能

封筒(envelope)と便箋(Stationery paper)

  • 我々がメールで見ているのは、言うなれば封筒入りで届いた便箋の中身だけ。
  • 便箋の中に差出人として誰の名前を書こうと、封筒の情報が正しければ封筒は届くように、
  • メールも同じで、この差出人の表示は送る側が自由に決められる。
  • 送信元のメールアドレスが自動で表示されている訳ではなく、他人のメールアドレスを書くこともできてしまう。

封筒の差出人

  • メールのソースの中の”Return-Path”が封筒の差出人にあたる。
  • これは、メールが宛先に届かなかった場合にその旨を連絡する先のこと
  • つまり、リアルの郵便と同じ用に、メールでも宛先に届かなかった時ように、Return-Pathで自分のアドレスを指定している
  • そして、リアルの郵便と同じように、実はここを見ても本当の送信者はわからない。
    • 勝手に偽装して総理官邸からのメールともできる

では、どうやってなりすましの見破るのか?

消印(Postmark) としての、SPF (Sender Policy Framework)

  • メールソースの中に、嘘がつけない本当の情報はないのだろうか?
  • 郵便の場合で考えると、それは消印。
  • 誰が送ったかは騙せても、どこ(どの郵便局)から送ったかは騙せない。
  • メールの場合、これは送信元IPアドレスという形で記載されている。
  • この送信元IPアドレスを使ってスパムメールをあぶり出す方法として作られたのがSPF。
  • まず、送信者は自分がどこから(どのIPアドレスから)メールを送るかという情報を公開する。
  • 受信者は、メールの送信元IPアドレスをその情報と照らし合わせて正当性を見極める。
  • 例えるならば、中野に住む人の手紙が中野郵便局ではなくロンドンから来たら、なりすましだと判断するような具合。

封蝋(Wax seal)としての、DKIM (DomainKeys Identified Mail)

  • DKIMは、電子署名の技術を利用して、メールが正当な送信者から送られ、かつ改ざんされていないことを確認できる技術。
  • 郵便に例えると、「封蝋」をするイメージ。
  • 刻印されたオリジナルのスタンプは、差出人に偽りがないこと、手紙が開封されていないことを証明してくれる。

郵便物の取扱の決めごととしての、DMARC (Domain-based Message Authentication, Reporting, and Conformance)

  • DMARCは、SPF / DKIMの両方の認証に失敗したメールを受信側サーバでどう扱うかを、送信側であらかじめ決めておくための仕組み。
  • SPFおよびDKIMを用いて送信元ドメインを認証する際、 認証に失敗したメールをどのように取り扱うかは、受信者の判断に任せられている。
  • また、認証に失敗したことやそのメールがどのように処理されたかは、 送信者には把握することができない。
  • そういったSPFおよびDKIMの挙動を補強するために、DMARCが提案された。
  • DMARCでは、認証失敗時にどのようにメールを処理すればよいかを、
  • 送信者が受信者に対してポリシーと呼ばれるレコードをDNS上で公開することで表明する仕組みになっている。
  • 受信者は認証に失敗した場合に送信者のポリシーを参照し、それに基づいてメールをどのように取り扱うかを決定する。

REFERENCES:

  • https://sendgrid.kke.co.jp/blog/?p=12290
  • https://www.nic.ad.jp/ja/basics/terms/dmarc.html

Push通知

AppleとGoogleの通知の仕組みがある。

  • APNs(Apple Push Notification Service)
  • GCM(Google Cloud Messaging)

考え方は共通していて次の2つをする必要がある

  • デバイス情報の登録機能
  • プッシュ通知の配信機能

システム構成

REFERENCES:

  • https://www.atmarkit.co.jp/ait/articles/1412/18/news022_2.html

SSH, MOSH, SCP, SFTP, SSHFS

コマンド使いみち
SSHリモートシェル叩きたい
MOSH接続が切れないでリモートのシェル叩きたい
SCPリモートシェル叩かずにファイルの移動をしたい
FTPリモートのファイル操作
SFTPリモートとローカルのシェル叩いてに柔軟にファイルの操作をしたい
SSHFSリモートのFSをローカルにマウントしてローカルから操作したい

初期設定

Root user Settings

1. firstly, follow security status

https://console.aws.amazon.com/iam/home#/home

2. Delete Access key of root user

  • open https://console.aws.amazon.com/iam/home#/security_credentials
  • click Access keys (access key ID and secret access key)
  • delete access key

3. Enable Root User to login by MFA

  • open https://console.aws.amazon.com/iam/home
  • click Activate MFA on your root account
  • add Activate MFA on your root account
  • read QR-code by 1password
  • type passcode

4. Create Management group

  • open https://console.aws.amazon.com/iam/home
  • click group tab
  • Add group following that:
    • group name: mgmt-group
    • select AdministratorAccess

5. Create Management IAM usre

  • open IAM user list
  • Click Add button
  • Add user following below that:
    • user name: mgmt-user
    • access type: AWS management console access
      • NOTE: management user doesn't see a need programmatic access, i.e. access key
    • console password: custom
    • require password reset: no
    • group: mgmt-group
    • console access: enable
    • tag: none
    • MFA device: virtual MFA device

6. Change PW policy

  • minimum length is 8
  • need a large case
  • need small case
  • need number

7. update bill setting

defaultly, no one can not see the bill info withou root user. but i don't want to use root user so i'll allow IAM user to see bill info.

  • open https://console.aws.amazon.com/billing/home#/account
  • scroll until IAM User and Role Access to Billing Information
  • click edit
  • enable Activate IAM Access and update it

8. setting for cost management and bill information

  • open https://console.aws.amazon.com/billing/home#/preferences
  • check following and save them
    • Receive PDF Invoice By Email
    • Receive Billing Alerts
    • Receive Free Tier Usage Alerts

9. make a billing alerm by cloudwatch

  • open https://console.aws.amazon.com/cloudwatch/home?region=us-east-1
    • only us-east can do this operation
  • click billing
  • click create alarm by following cond
    • exceed: 100 USD
    • email: me@example.com
  • confirm email
  • click view alearm

IAM management user settings

change region

  • login IAM management user
  • change region to Tokyo

make CloudTrail

  • to leave a history or log of API call
  • open https://ap-northeast-1.console.aws.amazon.com/cloudtrail/home?region=ap-northeast-1#/subscribe
  • Create crowdtail by following info:
    • Trail name: mgmt-tail
    • Apply trail to all regions: yes
    • Create a new S3 bucket: yes
    • S3 Bucket: mgmt-tail

git-secrets

$ yay -S git-secrets # on arch
$ cd /path/to/ur/repo
$ git secrets --install # install git secrets to the repo
$ git secrets --register-aws # deny secret, if u want to enable globally, just add --global options at last
$ git secrets --list
secrets.providers git secrets --aws-provider
secrets.patterns [A-Z0-9]{20}
secrets.patterns ("|')?(AWS|aws|Aws)?_?(SECRET|secret|Secret)?_?(ACCESS|access|Access)?_?(KEY|key|Key)("|')?\s*(:|=>|=)\s*("|')?[A-Za-z0-9/\+=]{40}("|')?
...

References

  • https://qiita.com/tmknom/items/303db2d1d928db720888
  • https://www.slideshare.net/AmazonWebServicesJapan/awswebinar-aws-56260969

IAM

IAM タイプ意味
Policyできること/できないこと(Statement)を定義し、UserやRoleに紐づけて使うAdministratorAccessなど
GroupPolicyとUserを紐付けて、ユーザーグループができることを定義する自前のroot-groupなど
UserPolicyを紐付けて、ユーザーができることを定義する自前のmikeなど
RolePolicyを紐付けて、AWSのサービス(主にインスタンス)ができることを定義するAWSServiceRoleForECSなど

ER図

PolicyのStatementの例

        {
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole"
            ],
            "Resource": [
                "arn:aws:iam::xxxxxxxxxxxx:role/full_ec2_lambda"
            ]
        }

IAM UserとRoleの違い

IAM User(ヒト)、IAM Roleは(モノ)

IAM Policyの種類

用語意味
AWS管理ポリシーAWSが提供するIAMポリシーです。各サービスに対して大まかな制御ポリシーが可能EC2すべてに対して何でも操作可能
カスタマー管理ポリシーユーザがJSONファイルなどを利用して設定するポリシーです。IPアドレスの制御など、AWS管理ポリシーよりも細やかな制御が可能特定のS3バケットに対してPUTのみ可能
インラインポリシーインラインポリシーは特定のIAMユーザやIAMロール専用に作成されるポリシー。「ポリシー」単体では存在できない。IAMユーザーと1:1の関係で作成されるポリシー

REFERENCES:

  • https://dev.classmethod.jp/articles/iam-policy-evaluation-logic/
  • https://dev.classmethod.jp/articles/iam-role-accesskey/

CloudFormation

Route53

Certificate Manager

Region, VPC、AZ、Subnet

VPC

  • AWS内の利用者専用の仮想プライベートネットワーク
  • リージョンの中に作成する
  • CIDRブロックは/16〜/28の範囲で作成できる
  • (例:10.0.0.0/16)
  • 可能な限り大きなサイズ(/16)で作成する
  • アドレス不足を防ぐため

Subnet

  • VPCをさらに小さなネットワークに区切った単位
  • CIDRブロックは/16〜/28の範囲で作成できる
  • VPCよりも小さな範囲を指定する
  • (例:10.0.1.0/24)
  • インターネットと通信するサブネット(パブリックサブネット)、通信しないサブネット(プライベートサブネット)など、役割・ルーティングによって分割する
  • 同一の役割を持ったサブネット、リソース群を複数のAZに作成することで、耐障害性の向上に繋がる(マルチAZ)

Route Table

  • パケットが次にどこに向かうか、転送先を決める
  • 通信経路(送信先とターゲット)を設定する
  • エントリー:
    • 送信先(Destination):パケットに指定された宛先IP
    • ターゲット(Target):実際の転送先
  • ターゲットがlocalの場合はそのネットワーク内を意味する
  • サブネットとルートテーブルの関連付け:
    • 1つのサブネットに割り当てられるルートテーブルは1つ
    • 1つのルートテーブルを複数のサブネットで共有することができる

REF

  • https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/VPC_Route_Tables.html
  • https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-ug.pdf
  • https://qiita.com/MayForBlue/items/95562b1af16f74e44110

インターネットGW, 仮想プライベートGW, NAT GW

用語意味
仮想プライベートゲートウェイVPCとVPN、Direct Connectを接続するためのゲートウェイ
インターネットゲートウェイVPC とインターネットとの間の通信を可能にする VPC コンポーネント
NATゲートウェイ- インターネットからの通信は、リクエストした戻りの通信のみ許可する。
- パブリックサブネットに配置し、ElasticIPを割り当てる

REFERENCES:

  • https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/VPC_Internet_Gateway.html

VPCの例

  • VPC: 10.0.0.0/16
  • サブネットは1octet (8bit)分使う
    • VPCが/16なので、Subnetは/24でCIDRを指定する
    • なのでサブネットは256個作れる
  • Public
    • Public Subnet: 10.0.0.0/24
    • Public Route Table
      • 0.0.0.0/0宛のアドレスをigwへ
      • 10.0.0.0/16(VPC内への通信)をlocal(VPCのルーター)へ
  • Private
    • Private Subnet: 10.0.1.0/24
    • Private Route Table
      • 0.0.0.0/0宛のアドレスをnat-gwへ
      • 10.0.0.0/16(VPC内への通信)をlocal(VPCのルーター)へ

REF

  • https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/VPC_Route_Tables.html
  • https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-ug.pdf

Network

ネットワークリソースの関係

  • AZ ∈ Region 
  • Route ∈ Route Table ∈ Subnet ∈ VPC
  • Subnet <=> Route Table <=> Gateway <=> Internet

Range of Global IP address vs. Ragne of Private IP address

Global IP Address

Class A:	1.0.0.0 ~ 9.255.255.255
Class A:	11.0.0.0 ~ 126.255.255.255
Class B:	128.0.0.0 ~ 172.15.255.255
Class B:	172.32.0.0 ~ 191.255.255.255
Class C:	192.0.0.0 ~ 192.167.255.255
Class C:	192.169.0.0 ~ 223.255.255.255

Private Ip address

Class A	10.0.0.0 ~ 10.255.255.255
Class B	172.16.0.0 ~ 172.31.255.255
Class C	192.168.0.0 ~ 192.168.255.255

cidr_block

octet単位.で区切られる

10.0.0.0/24

CIDR Range	10.0.0.0/24
Netmask	255.255.255.0
Wildcard Bits	0.0.0.255
First IP	10.0.0.0
Last IP	10.0.0.255
Total Host	256

10.0.64.0/24

CIDR Range	10.0.64.0/24
Netmask	255.255.255.0
Wildcard Bits	0.0.0.255
First IP	10.0.64.0
Last IP	10.0.64.255
Total Host	256

https://www.ipaddressguide.com/cidr

VPC

resource "aws_vpc" "example" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_support   = true <=========== resolve name by DNS of AWS
  enable_dns_hostnames = true <=========== add public DNS hostname in VPC automatically 
}

Public Subnet

resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.example.id
  cidr_block              = "10.0.0.0/24"
  map_public_ip_on_launch = true <========= automatically attach public ip address to the instance in this subnet
  availability_zone       = "ap-northeast-1a" <====== subnetはAZをまたげない
}

Internet Gateway

  • VPCは隔離されたネットワークなので単体ではインターネットと接続できない。
  • そこで、インターネットとGWを作成して、VPC <=> Interneで津神できるようにする
  • VPCのIDを指定する
resource "aws_internet_gateway" "example" {
  vpc_id = aws_vpc.example.id
}

Public network

Route tableの定義 (Public)

  • VPCとInternet GWだけだと、インターネット通信ができない。
  • ネットワークにデータを流すために、ルーティング情報を管理するRoute tableが必要
  • VPCのIDを指定する
  • public用のroute table
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.example.id
}
  • VPC内の通信を有効にするために、ローカルルートが自動的に作成されるので注意
  • なお、このローカルルーとはTFから制御できないので注意!
Destination: 10.0.0.0/16
Target: local

Routeの作成

  • ルートはルートテーブルの1レコードに該当する
  • 下で作ったaws_routeaws_route_table_associationを使って関連付けしなかった場合は、デフォルトルートテーブルが自動的に選ばれる。
resource "aws_route" "public" {
  route_table_id         = aws_route_table.public.id
  gateway_id             = aws_internet_gateway.example.id
  destination_cidr_block = "0.0.0.0/0" <====== デフォルトルーと(0.0.0.0/0)を指定して、VPC以外への通信をインターネットゲートウェイ経由で流す
}

RouteとRoute tableとの関連付け

  • サブネットを指定してルーとを登録する
resource "aws_route_table_association" "public" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public.id
}

Private network

Private Subnet

resource "aws_subnet" "private" {
  vpc_id                  = aws_vpc.example.id
  cidr_block              = "10.0.64.0/24"
  availability_zone       = "ap-northeast-1a"
  map_public_ip_on_launch = false <================= public IPは不要なのでfalseに
}

Route tableの作成

resource "aws_route_table" "private" {
  vpc_id = aws_vpc.example.id
}

Route tableの関連付け

resource "aws_route_table_association" "private" {
  subnet_id      = aws_subnet.private.id
  route_table_id = aws_route_table.private.id
}

NATゲートウェイのためのEIP

  • NATゲートウェイにはEIP(Elastic IP Address)が必要
resource "aws_eip" "nat_gateway" {
  vpc        = true
  depends_on = [aws_internet_gateway.example]  <======== 暗黙的にIneternet GWに依存しているため
}

NATゲートウェイの作成

resource "aws_nat_gateway" "example" {
  allocation_id = aws_eip.nat_gateway.id
  subnet_id     = aws_subnet.public.idA <============= subnetはPublic Subnetを指定する
  depends_on    = [aws_internet_gateway.example] <======== 暗黙的にIneternet GWに依存しているため
}

ルートを作成

  • プライベートネットワークからインターネットへ通信するためのルートを作成
resource "aws_route" "private" {
  route_table_id         = aws_route_table.private.id <=========== Private SubnetのRoute Tableに追加する
  nat_gateway_id         = aws_nat_gateway.example.id <=========== GWはNAT GWを選択
  destination_cidr_block = "0.0.0.0/0" <=================== デフォルトルート(0.0.0.0/0)を指定して、VPC以外への通信をインターネットゲへ経由で流す
}

Network (multi AZ)

  • VPCとInternet GWは作成済みとする

Public subnets

  • AZごとにSubnetを作成する
resource "aws_subnet" "public_0" {
  vpc_id                  = aws_vpc.example.id
  cidr_block              = "10.0.1.0/24" <==== こっちは10.0.1.0/24のネットワーク
  availability_zone       = "ap-northeast-1a" <==== こっちはaのAZ
  map_public_ip_on_launch = true
}

resource "aws_subnet" "public_1" {
  vpc_id                  = aws_vpc.example.id
  cidr_block              = "10.0.2.0/24" <==== こっちは10.0.2.0/24のネットワーク
  availability_zone       = "ap-northeast-1c" <====== こっちはcのAZ
  map_public_ip_on_launch = true 
}

ルートテーブルの関連付け

resource "aws_route_table_association" "public_0" {
  subnet_id      = aws_subnet.public_0.id
  route_table_id = aws_route_table.public.id
}

resource "aws_route_table_association" "public_1" {
  subnet_id      = aws_subnet.public_1.id
  route_table_id = aws_route_table.public.id
}

Private subnets

  • AZごとにSubnetを作成する
resource "aws_subnet" "private_0" {
  vpc_id                  = aws_vpc.example.id
  cidr_block              = "10.0.65.0/24"
  availability_zone       = "ap-northeast-1a"
  map_public_ip_on_launch = false <============ public IPはいらない
}

resource "aws_subnet" "private_1" {
  vpc_id                  = aws_vpc.example.id
  cidr_block              = "10.0.66.0/24"
  availability_zone       = "ap-northeast-1c"
  map_public_ip_on_launch = false <============ public IPはいらない
}

NAT Gate Way

  • NAT GWも単一障害点にならないように、Multi AZにする
  • NATはAZごとに作成する
resource "aws_eip" "nat_gateway_0" {
  vpc        = true
  depends_on = [aws_internet_gateway.example]
}

resource "aws_eip" "nat_gateway_1" {
  vpc        = true
  depends_on = [aws_internet_gateway.example]
}

resource "aws_nat_gateway" "nat_gateway_0" {
  allocation_id = aws_eip.nat_gateway_0.id
  subnet_id     = aws_subnet.public_0.id
  depends_on    = [aws_internet_gateway.example]
}

resource "aws_nat_gateway" "nat_gateway_1" {
  allocation_id = aws_eip.nat_gateway_1.id
  subnet_id     = aws_subnet.public_1.id
  depends_on    = [aws_internet_gateway.example]
}

Route Table of Private Subnet

  • route tableとrouteもsubnetごとに作成する
resource "aws_route_table" "private_0" {
  vpc_id = aws_vpc.example.id
}

resource "aws_route_table" "private_1" {
  vpc_id = aws_vpc.example.id
}

resource "aws_route" "private_0" {
  route_table_id         = aws_route_table.private_0.id
  nat_gateway_id         = aws_nat_gateway.nat_gateway_0.id
  destination_cidr_block = "0.0.0.0/0"
}

resource "aws_route" "private_1" {
  route_table_id         = aws_route_table.private_1.id
  nat_gateway_id         = aws_nat_gateway.nat_gateway_1.id
  destination_cidr_block = "0.0.0.0/0"
}

resource "aws_route_table_association" "private_0" {
  subnet_id      = aws_subnet.private_0.id
  route_table_id = aws_route_table.private_0.id
}

resource "aws_route_table_association" "private_1" {
  subnet_id      = aws_subnet.private_1.id
  route_table_id = aws_route_table.private_1.id
}

Firewall

AWS Firewall

AWSのFirewallは2種類

  • Subnet単位で働くネットワークACL
  • インスタンスレベルのSecurity Group

Security Group

  • OSに到達する前に、ネットワークレベルでパケットをフィルタリング可能
  • EC2やRDSなどの様々なリソースに紐付けることが可能

Security groupの作成

resource "aws_security_group" "example" {
  name   = "example"
  vpc_id = aws_vpc.example.id <========== VPCを指定
}

インバウンドのSecurity Groupのルールの作成

resource "aws_security_group_rule" "ingress_example" {
  type              = "ingress" <============ ingressの場合はインバウンド
  from_port         = "80" <===== 80番の許可
  to_port           = "80" <===== 80番の許可
  protocol          = "tcp" <==== HTTPの許可
  cidr_blocks       = ["0.0.0.0/0"]  <=========== 通信を許可するCIDRブロック。0.0.0.0/0なので全部
  security_group_id = aws_security_group.example.id
}

アウトバウンドのSecurity Groupのルール作成

resource "aws_security_group_rule" "egress_example" {
  type              = "egress"  <============ egressの場合はインバウンド
  from_port         = 0
  to_port           = 0
  protocol          = "-1" <============ -1にすると全トラフィック。その場合はfrom_portとto_portを両方0にする
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.example.id
}

セキュリティグループのモジュール可

variable "name" {}
variable "vpc_id" {}
variable "port" {}

variable "cidr_blocks" {
  type = list(string) <================ 型を明示的に指定している。指定されない場合はany
}

resource "aws_security_group" "default" {
  name   = var.name
  vpc_id = var.vpc_id
}

resource "aws_security_group_rule" "ingress" {
  type              = "ingress"
  from_port         = var.port
  to_port           = var.port
  protocol          = "tcp"
  cidr_blocks       = var.cidr_blocks
  security_group_id = aws_security_group.default.id
}

resource "aws_security_group_rule" "egress" {
  type              = "egress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.default.id
}

output "security_group_id" {
  value = aws_security_group.default.id
}

module "example_sg" {
  source      = "./security_group"
  name        = "module-sg"
  vpc_id      = aws_vpc.example.id
  port        = 80
  cidr_blocks = ["0.0.0.0/0"]
}

ALB

ALB Ccomponents

  • Lister: ポートを定義、リクエストを受ける
  • Litener Rule: パスなどのルール
  • Target Group: アクセスを仕分けされるグループ

HTTP用のロードバランサの作成

resource "aws_lb" "example" {
  name                       = "example"
  load_balancer_type         = "application"  <========= "network"を指定して、NLB(Network load balancer)も作れる
  internal                   = false <===== internet向けなのか、VPC内部向けなのかの指定
  idle_timeout               = 60 <==== タイムアウト
  enable_deletion_protection = true <====== 削除保護。本番では有効にスべし。

  subnets = [ <=========== サブネット。複数のAZのサブネットを指定して、クロスゾーン負荷分散ができる
    aws_subnet.public_0.id,
    aws_subnet.public_1.id,
  ]

  access_logs { <================= アクセスログ
    bucket  = aws_s3_bucket.alb_log.id
    enabled = true
  }

  security_groups = [ <================ セキュリティグルー府
    module.http_sg.security_group_id,
    module.https_sg.security_group_id,
    module.http_redirect_sg.security_group_id,
  ]
}

output "alb_dns_name" {
  value = aws_lb.example.dns_name
}

セキュリティーグループ

module "http_sg" {
  source      = "./security_group"
  name        = "http-sg"
  vpc_id      = aws_vpc.example.id
  port        = 80
  cidr_blocks = ["0.0.0.0/0"]
}

module "https_sg" {
  source      = "./security_group"
  name        = "https-sg"
  vpc_id      = aws_vpc.example.id
  port        = 443
  cidr_blocks = ["0.0.0.0/0"]
}

module "http_redirect_sg" {
  source      = "./security_group"
  name        = "http-redirect-sg"
  vpc_id      = aws_vpc.example.id
  port        = 8080
  cidr_blocks = ["0.0.0.0/0"]
}

リスナー

resource "aws_lb_listener" "http" {
  load_balancer_arn = aws_lb.example.arn
  port              = "80" 
  protocol          = "HTTP" <=========== サポートしているのはHTTP/HTTPS

  default_action { <=============== リスナーのルールに合致しない場合のアクション
    type = "fixed-response" <========= 固定のレスポンスを返す

    fixed_response {
      content_type = "text/plain"
      message_body = "This is HTTP"
      status_code  = "200"
    }
  }
}

Route 53

  • ドメイン購入後にやる
  • ホストゾーンの設定
data "aws_route53_zone" "example" {
  name = "example.com"
}

DNSレコード

resource "aws_route53_record" "example" {
  zone_id = data.aws_route53_zone.example.zone_id
  name    = data.aws_route53_zone.example.name
  type    = "A" <========== AWSの独自拡張のALISAレコード(Aレコードと同じ)

  alias {
    name                   = aws_lb.example.dns_name
    zone_id                = aws_lb.example.zone_id
    evaluate_target_health = true
  }
}

ACM (AWS Certificate Manager)

  • SSL Certificateを作成するためのACMの作成
resource "aws_acm_certificate" "example" {
  domain_name               = data.aws_route53_zone.example.name
  subject_alternative_names = []  <========== ここにドメイン名を追加する
  validation_method         = "DNS" <====== ドメインの所有権の検証

  lifecycle { <======== 新しいSSL証明書を作ってから古いSSL証明書と差し替える挙動に変更する
    create_before_destroy = true <===== 基本的にTFはデリートインサートだが、この設定でインサートデリートになる。ダウンタイムを回避できる
  }
}

SSL証明書の検証用DNSレコードの定義

resource "aws_route53_record" "example_certificate" {
  name    = aws_acm_certificate.example.domain_validation_options[0].resource_record_name
  type    = aws_acm_certificate.example.domain_validation_options[0].resource_record_type
  records = [aws_acm_certificate.example.domain_validation_options[0].resource_record_value]
  zone_id = data.aws_route53_zone.example.id
  ttl     = 60
}

 
resource "aws_acm_certificate_validation" "example" {
  certificate_arn         = aws_acm_certificate.example.arn
  validation_record_fqdns = [aws_route53_record.example_certificate.fqdn]
}

HTTPSのリスナー

resource "aws_lb_listener" "https" {
  load_balancer_arn = aws_lb.example.arn
  port              = "443"
  protocol          = "HTTPS"
  certificate_arn   = aws_acm_certificate.example.arn <============= ここでcertificateを指定する
  ssl_policy        = "ELBSecurityPolicy-2016-08" <============= これが推奨されている

  default_action {
    type = "fixed-response"

    fixed_response {
      content_type = "text/plain"
      message_body = "This is HTTPS"
      status_code  = "200"
    }
  }
}

HTTPリダイレクトするListener

resource "aws_lb_listener" "redirect_http_to_https" {
  load_balancer_arn = aws_lb.example.arn
  port              = "8080"
  protocol          = "HTTP"

  default_action {
    type = "redirect" <========= ここにredirectを設定するだけ

    redirect {
      port        = "443"
      protocol    = "HTTPS"
      status_code = "HTTP_301"
    }
  }
}

LBのターゲットグループの作成

resource "aws_lb_target_group" "example" {
  name                 = "example"
  vpc_id               = aws_vpc.example.id <=== tareget_type==ipの時に必要
  target_type          = "ip" <================== EC2やIPアドレス、Lambda関数などを指定できる, ECS FargateではIPアドレスによるルーティング
  port                 = 80 <=== tareget_type==ipの時に必要
  protocol             = "HTTP" <=== tareget_type==ipの時に必要
  deregistration_delay = 300 <======= ターゲットを登録解除する前にALBが待機する時間, default=300

  health_check {
    path                = "/" <====== ヘルスチェックで使用するパス
    healthy_threshold   = 5 <========= 正常判定を行うまでの経するチェック実行回数
    unhealthy_threshold = 2 <========== 以上判定を行うまでのヘルスチェック実行回数
    timeout             = 5 <======= ヘルスチェックのタイムアウト時間(s)
    interval            = 30 <============ ヘルスチェックのインターバル(s)
    matcher             = 200 <====== 正常判定をするために使用するHTTPステータスコード
    port                = "traffic-port" <======= ヘルスチェックで使用するポート, traffic-portの場合は、上のprotocolが使用される
    protocol            = "HTTP" <======= ヘルスチェックで使用するプロトコル
  }

  depends_on = [aws_lb.example] <====== ECSサービスと同時起動でエラーになるため
}

リスナールールの作成

resource "aws_lb_listener_rule" "example" {
  listener_arn = aws_lb_listener.https.arn
  priority     = 100 <==== リスナールールの優先順位

  action { <===== フォワード先のターゲットグループを指定
    type             = "forward"
    target_group_arn = aws_lb_target_group.example.arn
  }

  condition { <========= これがルール
    field  = "path-pattern"
    values = ["/*"]
  }
}

ELB

ロードバランサー役割
Application Load Balancer (ALB)http, https レベルのロードバランス)
Network Load Balancer (NLB)TCP レベルのロードバランス
Classic Load Balancer (CLB)旧世代ロードバランス

REFERENCES:

  • https://milestone-of-se.nesuke.com/sv-advanced/aws/vpc-architect

Target Group

LoadBalancer

ELB

AMI

Amazon マシンイメージ (AMI) は、ソフトウェア構成 (オペレーティングシステム、アプリケーションサーバー、アプリケーションなど) を記録したテンプレート

REFERENCES:

  • https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instances-and-amis.html

EBS (Amazon Elastic Block Store)

  • EC2 にアタッチ可能なブロックレベルのストレージサービス
  • 一つのEC2インスタンスには複数のEBSボリュームをアタッチすることができる
  • 複数のEC2インスタンスから一つのEBSボリュームへアタッチすることはできない
  • 他のインスタンスにアタッチすることが可能
  • 別のAZにあるEC2インスタンスにアタッチすることはできない
  • 内部的に冗長化されているので、耐久性に優れている。
  • スナップショット機能(EBS Snapshot)でバックアップなどを撮っておくことができる(S3へ)。
  • 暗号化されている。
  • 後から容量を増やしたりなどすることができ、インスタンスを停止することなく実行可能

REFERENCES:

  • https://recipe.kc-cloud.jp/archives/7534

Security Group

  • インスタンスに適用される(EC2、RDSなど)
  • 一つのインスタンスに少なくとも一つのセキュリティグループを紐づける
  • デフォルトではインバウンドの通信は全て拒否
  • どの通信を許可するかを指定する
  • ソース(=送信元)にはIPアドレスの他に、セキュリティグループを指定することもできる
  • セキュリティグループを指定した場合、送信元のリソースがそのセキュリティグループに紐づいていたら通信を許可する
  • ステートフルでセッションを見ているため戻りの通信の許可は不要

ネットワークACL

  • サブネット単位で適用される
  • デフォルトでは全て許可
  • ステートレスなので、戻りの通信も明示的に許可する必要がある

踏台サーバー (Jumpbox/Bastion)

ECS

AWS Container

  • ECSは2種類
    • EC2起動タイプ
    • Fargate起動タイプ

ECSクラスタの定義

次で簡単にECSクラスターは定義可能

resource "aws_ecs_cluster" "example" {
  name = "example"
}

ECSタスクの定義

  • コンテナの実行単位をタスクと呼ぶ
  • 例) Djangoアプリの前段階にNGINXを配置する場合は、一つのタスクの中でDjangoコンテナとNGINXが実行される
  • タスクはタスク定義から生成される。タスク定義はクラスでタスクはインスタンス
resource "aws_ecs_task_definition" "example" {
  family                   = "example" <== タスク定義名のプレフィックス。この場合はexample:1となる。リビジョン番号はタスク定義更新時にインクリされる
  cpu                      = "256" <===== CPUとMeomoryは組み合わせがあるので注意
  memory                   = "512"
  network_mode             = "awsvpc" <======== FARGATEの場合は、AWSVPCにする
  requires_compatibilities = ["FARGATE"] <======= 起動タイプはFargateにする
  container_definitions    = file("./container_definitions.json") <============= 実行するコンテナを定義する
}

実行するコンテナを定義(コンテナ定義)は次のような(container_definitions.json)感じ。

[
  {
    "name": "example", <============ コンテナ名
    "image": "nginx:latest", <======== イメージ名
    "essential": true, <============ タスク実行に必須かどうか
    "portMappings": [ <============ マッピングするコンテナのポート番号
      {
        "protocol": "tcp",
        "containerPort": 80
      }
    ]
  }
]

ECSサービスの定義

  • 通常、コンテナを起動しても、処理が完了したら、終了する。
  • それは困るので、ECSサービスを利用する。
  • ECSサービスは起動するタスクを定義でき、指定した数のタスクを維持する。
  • 何らかの理由でタスクが終了してしまった場合は、自動的にタスクが起動する
  • また、ECSサービスはALBとの橋渡し役にもなる
  • インターネットからのリクエストをALBで受け、そのリクエストをコンテナにフォワードする
resource "aws_ecs_service" "example" {
  name                              = "example"
  cluster                           = aws_ecs_cluster.example.arn
  task_definition                   = aws_ecs_task_definition.example.arn <====== さっき作成したタスクを指定する
  desired_count                     = 2 <======= 維持するタスクの数
  launch_type                       = "FARGATE" <======= 起動タイプ
  platform_version                  = "1.3.0" <========== LATESTは最新じゃない場合もあるので、明示的に指定
  health_check_grace_period_seconds = 60 <========== タスク起動時のヘルスチェックの猶予期間(s)。タスクの起動に時間がかかる場合は、猶予がないと、ヘルスチェックに引っかかり、タスクの起動と終了が無限に続いてしまうため。

  network_configuration { <============== ネットワークの設定
    assign_public_ip = false <========プライベートで起動させるので、false
    security_groups  = [module.nginx_sg.security_group_id]

    subnets = [ <=============== 起動させたいサブネットを指定
      aws_subnet.private_0.id,
      aws_subnet.private_1.id,
    ]
  }

  load_balancer { <=========== ロードバランサ
    target_group_arn = aws_lb_target_group.example.arn <======== ターゲットグループの指定
    container_name   = "example" <======== コンテナ定義(container_definitions.json)のname。複数コンテナ定義がある場合は、最初にロードバランサーからリクエストを受けるコンテナを指定する
    container_port   = 80 <======= コンテナ定義(container_definitions.json)のportmappings.containerport
  }

  lifecycle { <================== Fargateの場合は、デプロイの対日にタスクが更新され、plan時に差分がでるので、変更を無視する。
    ignore_changes = [task_definition]
  }
}

module "nginx_sg" {  <===================== moduleでsgを定義
  source      = "./security_group"
  name        = "nginx-sg"
  vpc_id      = aws_vpc.example.id
  port        = 80
  cidr_blocks = [aws_vpc.example.cidr_block]
}

ECSのロギング

  • cloudwatch logsを使う
resource "aws_cloudwatch_log_group" "for_ecs" {
  name              = "/ecs/example"
  retention_in_days = 180 <================ ログ保存機関
}

ECSタスク実行IAMロール

ECSに権限を付与するための、ECSタスク実行IAMロールを作成する

data "aws_iam_policy" "ecs_task_execution_role_policy" {
  arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"  <== CloudWachやECRの操作権限を持っているPolicy
}

ポリシードキュメント

data "aws_iam_policy_document" "ecs_task_execution" {
  source_json = data.aws_iam_policy.ecs_task_execution_role_policy.policy <==== source_jsonを使うと、既存のポリシーを継承できる。

  statement { <============= 継承しているので、追加となる
    effect    = "Allow"
    actions   = ["ssm:GetParameters", "kms:Decrypt"]
    resources = ["*"]
  }
}

IAMロール

module "ecs_task_execution_role" {
  source     = "./iam_role"
  name       = "ecs-task-execution"
  identifier = "ecs-tasks.amazonaws.com"
  policy     = data.aws_iam_policy_document.ecs_task_execution.json
}

Dockerコンテナのロギングのためのタスク定義の修正

  • DockerコンテナがCloudWatch Logsにログを投げられるようにする
  • もともとのタスク定義にexecution_role_arnを追加する
resource "aws_ecs_task_definition" "example" {
  family                   = "example"
  cpu                      = "256"
  memory                   = "512"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  container_definitions    = file("./container_definitions.json")
  execution_role_arn       = module.ecs_task_execution_role.iam_role_arn <============== 追加分
}

コンテナ定義の修正

[
  {
    "name": "example",
    "image": "nginx:latest",
    "essential": true,
    "logConfiguration": { <=================== これが追加された。ログを投げるための設定
      "logDriver": "awslogs",
      "options": {
        "awslogs-region": "ap-northeast-1",
        "awslogs-stream-prefix": "nginx",
        "awslogs-group": "/ecs/example"
      }
    },
    "portMappings": [
      {
        "protocol": "tcp",
        "containerPort": 80
      }
    ]
  }
]

CloudWatch

SQS

シンプルなメッセージキュー
メッセージをキューに入れる、読む、削除する

用語

用語意味
SQSメッセージキューのサービス
SQSメッセージメッセージキューのメッセージ
SQSキューメッセージキューのキュー

REFERENCES:

  • https://www.slideshare.net/rs_wisteria/amazon-snssqs-fanout

SNS

  • いわゆるPub/Subのサービス。
  • サブスクライブしているエンドポイントまたはクライアントへのメッセージの配信または送信を、調整および管理するウェブサービス

用語

用語意味
Topic通信チャネルとして機能する論理アクセスポイント。通知を行いたいイベントが発生した場合は、Topicに対してメッセージを送る
メッセージ発行者がトピックに送信し、最終的にはサブスクライバーに配信されるデータ
発行者 (プロデューサー)論理アクセスポイントおよび通信チャネルであるトピックにメッセージを作成して送信することで、受信者と非同期的に通信する
SubscriptionTopicメッセージの送信先。Topicに登録することで、Topicにメッセージを送信した際に、Subscriberに送信される。
Subscriberウェブサーバー、E メールアドレス、Amazon SQS キュー、AWS Lambda 関数など
デッドレターキューAmazon SNS サブスクリプションが正常にサブスクライバーに配信されなかったメッセージをターゲットにできる Amazon SQS キュー
ファンアウト(Fanout)Fan(扇状の)-Out(出力)。つまり、1つの入力に対して複数の出力が接続されること

一般的な Amazon SNS シナリオ

  • ファンアウト
  • アプリケーションおよびシステムアラート
  • プッシュ E メールとテキストメッセージ
  • モバイルプッシュ通知
  • メッセージの耐久性

SNSのベクトプラクティス

  • トピックがパブリックアクセス可能でないようにする
  • 最小特権アクセスの実装
  • Amazon SNS アクセスを必要とするアプリケーションと AWS のサービスには IAM ロールを使用する。
  • サーバー側の暗号化を実装する
  • 転送時のデータの暗号化を強制する
  • VPC エンドポイントを使用して Amazon SNS にアクセスすることを検討する

REFERENCES:

  • https://www.unitrust.co.jp/6182
  • https://docs.aws.amazon.com/ja_jp/sns/latest/dg/sns-common-scenarios.html
  • https://docs.aws.amazon.com/ja_jp/sns/latest/dg/welcome.html
  • https://qiita.com/fjisdahgaiuerua/items/2f79042570903416d612
  • https://www.slideshare.net/rs_wisteria/amazon-snssqs-fanout
  • https://cloud.google.com/pubsub/docs/overview?hl=ja

SES

awsでemail使うときのメモ

  • sandbox modeでは、verifiedされたEmail Addressesでしか動かない
    • sandboxの場合は、fromとtoの両方でverified emailである必要がある
  • sandbox modeを解除するにはフォームを入力しなければならない
    • sandboxが解除された場合は、ドメイン認証済みのアドレスならOK
  • emailは仕組み上偽装が簡単なので、SPF DKIMの設定が必要

REFERENCES:

  • https://stackoverflow.com/questions/37528301/send-test-email-fails-with-email-address-is-not-verified

AWSのSESでメールを送るときは、スパムと間違われないためにメールの処理ではBounceとComplaintの処理が必要

  • 具体的には、次の2つを守る必要がある。
    • バウンスメールの割合を5%未満
    • 苦情が0.1%未満

Bounce

  • Bounceはメールが送れなかった時(送信先が存在しなかったときとか)に発生

Complaint

  • Complaintは送ったメールに対する苦情がきたときに発生

解決方法

  • Return-Pathでメールを受け取り、パースする
  • AWS SESを使う場合は、AWS SNS で受け取れる。

REFERENCES:

  • https://forums.aws.amazon.com/ann.jspa?annID=1765
  • http://temporal.hatenablog.com/entry/2013/01/20/174500
  • https://dev.classmethod.jp/articles/amazon-ses-production/

S3

S3 Access Control

アクセスコントロールのタイプ特徴名前
ACLバケット、もしくはオブジェクト単位で設定する事が出来るBucketACL, ObjcetACL
BucketPolicyバケットに対する設定BucketPolicy
IAMユーザ名に応じたアクセスのコントロールが可能IAMRole

BucketACL VS. ObjcetACL VS. BucketPolicy

BucketPolicy > BucketACL & ObjcetACLとなっている

BucketACLObjcetACLBucketPolicy結果
許可許可拒否失敗
許可未設定拒否失敗
許可許可許可成功
許可未設定許可成功
許可許可未設定成功
許可未設定未設定失敗
未設定許可拒否失敗
未設定未設定拒否失敗
未設定許可許可成功
未設定未設定許可成功
未設定許可未設定成功
未設定未設定未設定失敗

BucketPolicy vs. IAMRole

IAMで許可されていないと確実に失敗する

BucketPolicyIAM結果
拒否拒否失敗
拒否許可失敗
許可拒否失敗
許可許可成功
未設定拒否失敗
未設定許可成功

用途

ユースケース[Bucket|Object]ACLBucketPolicyIAM
一個のObjectを公開したい
バケット全体を公開したい
特定のユーザにだけ公開したい
IPアドレス制限をかけたい
Bucketの中のPrefixを指定して公開したい
prefixがユーザ毎に可変

REFERENCES:

  • https://dev.classmethod.jp/articles/s3-acl-wakewakame/

S3 Object ACL

AWS Dosc:

  • https://docs.aws.amazon.com/sdk-for-ruby/v2/api/Aws/S3/ObjectAcl.html

BOTO3:

  • https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#objectacl
For example, the following x-amz-grant-read header grants list objects permission to the two AWS accounts identified by their email addresses.

x-amz-grant-read: emailAddress="xyz@amazon.com", emailAddress="abc@amazon.com"

KDDI:

"x-amz-acl": "public-read"

https://doc.cloud-platform.kddi.ne.jp/developer/object-storage-api/service/object/put-object-acl

Condition Keys

s3:x-amz-acl: Require a Canned ACL.

https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#CannedACL

Canned ACL (Amazon S3 supports a set of predefined grants)

public-readなど

https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#CannedACL

Object S3 Put

  acl: "private", # accepts private, public-read, public-read-write, authenticated-read, aws-exec-read, bucket-owner-read, bucket-owner-full-control

https://docs.aws.amazon.com/sdk-for-ruby/v2/api/Aws/S3/Object.html#put-instance_method

By default, all objects in Amazon S3 are private. You can then add permissions so that people can access your objects. This can be done via:

- Access Control List permissions on individual objects
- A Bucket Policy that grants wide-ranging access based on path, IP address, referrer, etc
- IAM Users and Groups that grant permissions to Users with AWS credentials
- Pre-Signed URLs

https://stackoverflow.com/questions/40518642/setting-specific-permission-in-amazon-s3-boto-bucket

ACL指定なし

Params={"Bucket": cls.BUCKET, "Key": object_name, "ContentType": content_type, 'ACL': 'public-read'},
[mike@mike-pc ~/Workspace/srush/CSVs][10:16:23][X][I][%][λ]> curl -X PUT -T 顧客リストmybridge_no_errors.xls -H "Content-Type: application/vnd.ms-excel" -H "test-meta: 123" -H "x-amz-acl: public-read" -L "https://srush-upload-dev.s3.amazonaws.com/import_clients/wsu-2_e44e1667-7102-4fab-9d20-d51a74ab71e6?AWSAccessKeyId=AKIAX3UKWX7PWLEXYAO6&Signature=eMwRdhTcDVvs6rC1%2FVxaMPxFkM0%3D&content-type=application%2Fvnd.ms-excel&Expires=1596937605"
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><AWSAccessKeyId>AKIAX3UKWX7PWLEXYAO6</AWSAccessKeyId><StringToSign>PUT

application/vnd.ms-excel
1596937605
x-amz-acl:public-read
/srush-upload-dev/import_clients/wsu-2_e44e1667-7102-4fab-9d20-d51a74ab71e6</StringToSign><SignatureProvided>eMwRdhTcDVvs6rC1/VxaMPxFkM0=</SignatureProvided><StringToSignBytes>50 55 54 0a 0a 61 70 70 6c 69 63 61 74 69 6f 6e 2f 76 6e 64 2e 6d 73 2d 65 78 63 65 6c 0a 31 35 39 36 39 33 37 36 30 35 0a 78 2d 61 6d 7a 2d 61 63 6c 3a 70 75 62 6c 69 63 2d 72 65 61 64 0a 2f 73 72 75 73 68 2d 75 70 6c 6f 61 64 2d 64 65 76 2f 69 6d 70 6f 72 74 5f 63 6c 69 65 6e 74 73 2f 77 73 75 2d 32 5f 65 34 34 65 31 36 36 37 2d 37 31 30 32 2d 34 66 61 62 2d 39 64 32 30 2d 64 35 31 61 37 34 61 62 37 31 65 36</StringToSignBytes><RequestId>4F185B74DAC73838</RequestId><HostId>8dZd62L8jUBZIZIV8e0hXuTiOrvpQTUa6aB6Tj3QPGh1fCZV3QhjkGyytpc5EhUnYD5RjHPB7IM=</HostId></Error>% 

ACL指定あり


参考文献

https://github.com/boto/boto3/issues/1070 https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-presigned-urls.html#using-presigned-urls-to-perform-other-s3-operations

SSM (AWS Systems Manager)

  • 一番わかり易いのが、sshログインせずとも、Management Console 上から Agent経由でOS上でコマンドを実行してくれるサービスです
  • つまりは、SSHレス
  • SSM Agent は Amazon Linux AMI 2017.09からデフォでインストール済み

ref https://qiita.com/numasawa/items/ed1f1ef6c7c3c6b4c56b

ref https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-parameter-store.html

SSM Parameter Store vs. Secrets Manager

比較項目Parameter StoreSecrets Manager
情報の保管単位"/dev/os-users"のような階層型のパラメータに保管可能。パラメータには1つまたは複数の値を保管可能。パラメータと値は1:1または1:ndev/db-string"のような階層型のシークレットに保管可能。シークレットには、1つまたは複数の「キーと値のペア」を保管可能。シークレットと、「キーと値のペア」は1:1または1:n
保管された情報の暗号化暗号化され、KMSに保存暗号化され、KMSに保存
保管された情報へのAPIアクセス可能可能
APIアクセス時のRate limit非公開700 Req/sec ※DescribeSecret、GetSecretValueの場合(参照)
保管された情報へのアクセス制御IAMポリシーで制御可能IAMポリシーで制御可能
連携可能なAWSサービス多数(参照)RDS for MySQL、PostgreSQL、Auroraの認証情報保存を標準サポート(Secrets Managerの設定画面上で、対象のRDSを選択可能)。AWS CLIやSDKを通じてEC2やECS、Labmda等と連携可能
保管された情報のバージョニング複数バージョンを保持可能。1パラメータにつき100(参照)複数バージョンを保持可能。Secrets Managerの内部的には1シークレットにつき約100保持可能だが、バージョンに付与できるラベルの最大数は20(参照)。バージョンとラベルの関係性については、クラメソさんのブログが詳しい
保管された情報の使用状況の監査・監視CloudTrail、CloudWatch、SNSを活用して監査・監視可能CloudTrail、CloudWatch、SNSを活用して監査・監視可能
シークレット情報の自動更新Parameter Storeの機能としては不可。AWS CLIやLambda等を活用して作り込みすることで対応可能RDS for MySQL、PostgreSQL、Auroraの認証情報自動更新を標準サポート。その他DBの接続情報やAPIキー等は、Parameter Storeにて提供されるLambdaスクリプトをカスタマイズすることで対応可能
利用料金無料。但し、暗号化に利用されるKMSにてCMK(カスタマーマスターキー。ユーザ側で生成したキー)を利用する場合、KMSのAPI呼び出し料金が必要有料。シークレット 1 件あたり 0.40 USD/月。10,000 回の API コールあたり 0.05 USD。料金例はこちら。更に、Parameter Storeと同様、KMSの暗号化にCMKを利用する場合、KMSのAPI呼び出し料金が必要

REF

  • https://qiita.com/tomoya_oka/items/a3dd44879eea0d1e3ef5

KMS

2種類の鍵

Key特徴永続化 in AWSexport
マスターキー(Customer Master key, CMK)データキー(鍵)を暗号化するAWS内で永続化されるユーザーExport不可。
データキー(Data Key, DK)データを暗号化するAWS内で永続化されないユーザーExport可。

Customer Master Keyを使う場合は、KMSのAPIを利用してencode/decodeする

2つ鍵が必要な理由

  • 暗号化の問題は鍵の管理方法
    • 鍵をexportされてしまうと漏洩の可能性がある。
    • なぜなら、鍵が暗号化されていないから
  • それを防ぐため、鍵をさらに別の鍵(鍵の鍵)で暗号化しておけば、元の鍵(暗号化した鍵)が漏洩してもデータは守られる。
    • ただし、鍵の鍵が漏洩する可能性があり、結局鍵を無限に暗号化しなければならない
  • そこで絶対に安全な方式で保管されているマスターキーを使って鍵を暗号化することにする

CMKとDKのフロー

大切なのは、API経由でCMKを使用して暗号化データキーを複合化し、その復号化された平文のデータキーを使用後に削除すること
そして、手元で管理するのは暗号化データキーのみにすること

  1. データの暗号化
    1. CMKのIDを使って、API経由で次の2つの鍵を作る
      1. 平文のデータキー
      2. 暗号化データキー
    2. データの暗号化
      1. 平文のデータキーでデータを暗号化
    3. 平文のデータキーの削除。
  2. 管理
    1. 管理するのは次の2つ
      1. 暗号化データキー
      2. 暗号化されたデータ
  3. データの復号化
    1. CMKのIDと暗号化データキーを使って、API経由で平文のデータキーを手に入れる
      1. これが、データキーの復号化
    2. データの復号化
      1. 平文のデータキーでデータの復号化
    3. 平文のデータキーの削除

エイリアス

  • カスタマーマスターキーにはUUIDが割り振られているが分かりづらいので、エイリアスを指定できる。

REFERENCES:

  • https://dev.classmethod.jp/articles/10minutes-kms/
  • https://docs.aws.amazon.com/ja_jp/kms/latest/developerguide/concepts.html#data-keys
  • https://dev.classmethod.jp/cloud/aws/cm-advent-calendar-2015-aws-relearning-key-management-service/

RDS

MySQLのパラメターグループ

resource "aws_db_parameter_group" "example" {
  name   = "example"
  family = "mysql5.7" <========== ファミリーはengine:vertionを合わせた値

  parameter {
    name  = "character_set_database"
    value = "utf8mb4"
  }

  parameter {
    name  = "character_set_server"
    value = "utf8mb4"
  }
}

DBのオプショングループ

resource "aws_db_option_group" "example" {
  name                 = "example"
  engine_name          = "mysql"
  major_engine_version = "5.7"

  option {
    option_name = "MARIADB_AUDIT_PLUGIN" <========= これはユーザーのログオンや実行したクエリのアクティビティを記録するための別のDB
  }
}

DB専用のサブネットグループ

  • サブネットはプライベートを選択する
  • multi AZなので、複数のprivate subnetを選択する
resource "aws_db_subnet_group" "example" {
  name       = "example"
  subnet_ids = [aws_subnet.private_0.id, aws_subnet.private_1.id]
}

DBインスタンスの定義

resource "aws_db_instance" "example" {
  identifier                 = "example" <============ DBのエンドポイントで使う識別子
  engine                     = "mysql"
  engine_version             = "5.7.23"
  instance_class             = "db.t3.small"
  allocated_storage          = 20
  storage_type               = "gp2" <===== 汎用SSDかプロビジョン度IOPS。gp2は汎用SSD
  storage_encrypted          = true
  kms_key_id                 = aws_kms_key.example.arn <========== これを設定すると、DISK暗号化が有効になる。
  username                   = "admin" 
  password                   = "VeryStrongPassword!" <===== これは例えvariableにしても、平文でtfstateに書き込まれてしまう。。。
  multi_az                   = true <==== multi_azの有効化、無論subnet_groupで複数のAZのサブネットを有効化する必要がある。
  publicly_accessible        = false
  backup_window              = "09:10-09:40" <====== RDSの毎日のバックアップのタイミング(UTC)、maintenance_windowの前に設定すると安心感がある
  backup_retention_period    = 30 <======== バックアップ保存期間。最大は35
  maintenance_window         = "mon:10:10-mon:10:40"  <===== メンテナンスタイミング(UTC)
  auto_minor_version_upgrade = false <===== マイナーバージョンのアップグレードを無効化
  deletion_protection        = true  <============= 削除保護
  skip_final_snapshot        = false <================ インスタンス削除時にスナップショットを作成するため、これはfalse
  port                       = 3306 <====== mysqlのデフォは3306
  apply_immediately          = false <========= 一部の変更は再起動が必要なので、即時に変更はかけない(=メンテナンスウィンドウにかけられる)
  vpc_security_group_ids     = [module.mysql_sg.security_group_id]  <==== RDSインスタンスのセキュリティグループ
  parameter_group_name       = aws_db_parameter_group.example.name
  option_group_name          = aws_db_option_group.example.name
  db_subnet_group_name       = aws_db_subnet_group.example.name

  lifecycle {
    ignore_changes = [password]  <====== 上のpasswordは平文でtfに管理されてしまうため。無視する
  }
}

上の場合は、gitやtfにPWを管理させないので、aws cliで自分で更新する必要がある。

RDSのセキュリティグループ

module "mysql_sg" {
  source      = "./security_group"
  name        = "mysql-sg"
  vpc_id      = aws_vpc.example.id
  port        = 3306
  cidr_blocks = [aws_vpc.example.cidr_block]
}

ElasticCache(redis)のインスタンス化

resource "aws_elasticache_parameter_group" "example" {
  name   = "example"
  family = "redis5.0" <==== redisを使う

  parameter {
    name  = "cluster-enabled"
    value = "no"
  }
}

ElasticCacheサブネットグループ

resource "aws_elasticache_subnet_group" "example" {
  name       = "example"
  subnet_ids = [aws_subnet.private_0.id, aws_subnet.private_1.id]
}

ElasticCacheのインスタンス

resource "aws_elasticache_replication_group" "example" {
  replication_group_id          = "example"
  replication_group_description = "Cluster Disabled"
  engine                        = "redis"
  engine_version                = "5.0.3"
  number_cache_clusters         = 3
  node_type                     = "cache.m3.medium"
  snapshot_window               = "09:10-10:10"
  snapshot_retention_limit      = 7
  maintenance_window            = "mon:10:40-mon:11:40"
  automatic_failover_enabled    = true
  port                          = 6379
  apply_immediately             = false
  security_group_ids            = [module.redis_sg.security_group_id]
  parameter_group_name          = aws_elasticache_parameter_group.example.name
  subnet_group_name             = aws_elasticache_subnet_group.example.name
}

ElasticCacheのSG

module "redis_sg" {
  source      = "./security_group"
  name        = "redis-sg"
  vpc_id      = aws_vpc.example.id
  port        = 6379
  cidr_blocks = [aws_vpc.example.cidr_block]
}

DynamoDB

CI/CD

デプロイメントパイプライン

Flow

  1. GithubのWebhookで変更検知
  2. Githubからソースを取得
  3. Dockerイメージをbuildしてコンテナレジストリにプッシュ
  4. コンテナレジストリからDockerイメージをPullしてECSでデプロイ

ECRリポジトリの定義

resource "aws_ecr_repository" "example" {
  name = "example"
}

ECRのライフサイクルポリシー

  • ECRリポには保存できるイメージに限りがあるため
  • releaseで始まるイメージタグを30個までに制限
resource "aws_ecr_lifecycle_policy" "example" {
  repository = aws_ecr_repository.example.name

  policy = <<EOF
  {
    "rules": [
      {
        "rulePriority": 1,
        "description": "Keep last 30 release tagged images",
        "selection": {
          "tagStatus": "tagged",
          "tagPrefixList": ["release"],
          "countType": "imageCountMoreThan",
          "countNumber": 30
        },
        "action": {
          "type": "expire"
        }
      }
    ]
  }
EOF
}

CI(continuous integration)の設定

  • DockerイメージのビルドとECRのPushをCodebuildでやる
  • CIは狭義にはビルドやテスト、インスペクションなどを継続的に実行していくこと

CodeBuildが使用するIAMロールの作成

次のポリシードキュメントを作る

  • ビルド出力アーティファクトを保存するためのS3操作権限
    • ビルド出力アーティファクトとは、Build後のコードのこと
  • ビルドログを出力するためのCloudWatch Logs操作権限
  • Docker ImageをPushするためのECR操作権限
data "aws_iam_policy_document" "codebuild" {
  statement {
    effect    = "Allow"
    resources = ["*"]

    actions = [
      "s3:PutObject",
      "s3:GetObject",
      "s3:GetObjectVersion",
      "logs:CreateLogGroup",
      "logs:CreateLogStream",
      "logs:PutLogEvents",
      "ecr:GetAuthorizationToken",
      "ecr:BatchCheckLayerAvailability",
      "ecr:GetDownloadUrlForLayer",
      "ecr:GetRepositoryPolicy",
      "ecr:DescribeRepositories",
      "ecr:ListImages",
      "ecr:DescribeImages",
      "ecr:BatchGetImage",
      "ecr:InitiateLayerUpload",
      "ecr:UploadLayerPart",
      "ecr:CompleteLayerUpload",
      "ecr:PutImage",
    ]
  }
}

サービスロールの定義

module "codebuild_role" {
  source     = "./iam_role"
  name       = "codebuild"
  identifier = "codebuild.amazonaws.com"
  policy     = data.aws_iam_policy_document.codebuild.json
}

CodeBuildのプロジェクト作成

resource "aws_codebuild_project" "example" {
  name         = "example"
  service_role = module.codebuild_role.iam_role_arn <===== さっき作成したロールを指定

  source { <============ ビルド対象のファイル
    type = "CODEPIPELINE" <=========== CODEPIPELINEの指定で、CodePipelineと連携することを宣言
  }

  artifacts {<============ ビルド後のファイル
    type = "CODEPIPELINE"  <=========== CODEPIPELINEの指定で、CodePipelineと連携することを宣言
  }

  environment { <========== ビルド環境
    type            = "LINUX_CONTAINER"
    compute_type    = "BUILD_GENERAL1_SMALL"
    image           = "aws/codebuild/ubuntu-base:14.04"
    privileged_mode = true <=========== Dockerコマンドを利用するため、特権を付与
  }
}

CodeBuildの定義ファイル(buildspec.yml)の作成

  • buildspec.ymlはCodeBuildのビルド処理を規定する
version: 0.2

phases:
  pre_build: <========== ECRにログイン
    commands:
    - $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
    - REPO=$(aws ecr describe-repositories --repository-names example --output text --query "repositories[0].repositoryUri")
    - IMAGE=$REPO:latest
  build: <=============== Dockerイメージのビルドとプッシュ
    commands:
    - docker build -t $IMAGE .
    - docker push $IMAGE
  post_build: <=========================== imagedefinitions.jsonファイルの作成
    commands:
    - printf '[{"name":"example","imageUri":"%s"}]' $IMAGE > imagedefinitions.json
artifacts:
  files: imagedefinitions.json

CD(continuous delivery)の設定

  • アプリのコードがmasterにマージされたら、ECSにデプロイされる仕組みを作る
  • CDはCIを拡張した手法で、ビルドやテストだけでなく、リリースプロセス全体を自動化すること

ポリシードキュメントの定義

  • ステージ間でデータを受け渡すためのS3操作権限
  • ECSにDockerイメージをデプロイするためのECS操作権限
  • CodeBuildやECSにロールを渡すためのPassRole権限
data "aws_iam_policy_document" "codepipeline" {
  statement {
    effect    = "Allow"
    resources = ["*"]

    actions = [
      "s3:PutObject",
      "s3:GetObject",
      "s3:GetObjectVersion",
      "s3:GetBucketVersioning",
      "codebuild:BatchGetBuilds",
      "codebuild:StartBuild",
      "ecs:DescribeServices",
      "ecs:DescribeTaskDefinition",
      "ecs:DescribeTasks",
      "ecs:ListTasks",
      "ecs:RegisterTaskDefinition",
      "ecs:UpdateService",
      "iam:PassRole",
    ]
  }
}

CodePipeline用のIAMロール

module "codepipeline_role" {
  source     = "./iam_role"
  name       = "codepipeline"
  identifier = "codepipeline.amazonaws.com"
  policy     = data.aws_iam_policy_document.codepipeline.json
}

CodePipelineの各ステージで、データの受け渡しに使用するアーティファクトのストア

resource "aws_s3_bucket" "artifact" {
  bucket = "artifact-pragmatic-terraform-on-aws"

  lifecycle_rule {
    enabled = true

    expiration {
      days = "180"
    }
  }
}

CodePipelineの定義

CodePipelineは複数のステージから構成される

  1. Sourceステージ: githubからコードを取得
  2. Buildステージ: CodeBuildを実行して、ECRにDockerイメージをPushする
  3. deployステージ: ECSへDockerイメージのデプロイ
resource "aws_codepipeline" "example" {
  name     = "example"
  role_arn = module.codepipeline_role.iam_role_arn

  stage {  <============ source stage
    name = "Source"

    action {
      name             = "Source"
      category         = "Source"
      owner            = "ThirdParty"
      provider         = "GitHub"
      version          = 1
      output_artifacts = ["Source"]

      configuration = {
        Owner                = "your-github-name"
        Repo                 = "your-repository"
        Branch               = "master"
        PollForSourceChanges = false  <============== webhookからcodepipelineの起動を行うたポーリングは無効化
      }
    }
  }

  stage { <====================== Buildステージ
    name = "Build"

    action {
      name             = "Build"
      category         = "Build"
      owner            = "AWS"
      provider         = "CodeBuild"
      version          = 1
      input_artifacts  = ["Source"]
      output_artifacts = ["Build"]

      configuration = {
        ProjectName = aws_codebuild_project.example.id
      }
    }
  }

  stage { <=================== Deployステージ。 ECSクラスタとECSサービスを指定する
    name = "Deploy"

    action {
      name            = "Deploy"
      category        = "Deploy"
      owner           = "AWS"
      provider        = "ECS"
      version         = 1
      input_artifacts = ["Build"]

      configuration = {
        ClusterName = aws_ecs_cluster.example.name
        ServiceName = aws_ecs_service.example.name
        FileName    = "imagedefinitions.json" <=============== コンテナ定義の一部を参照する
      }
    }
  }

  artifact_store {  
    location = aws_s3_bucket.artifact.id <=========== 作成したアーティファクトの保存用のS3
    type     = "S3"
  }
}

Codepipeline Webhookの作成

resource "aws_codepipeline_webhook" "example" {
  name            = "example"
  target_pipeline = aws_codepipeline.example.name
  target_action   = "Source"
  authentication  = "GITHUB_HMAC" <======== HMAC形式

  authentication_configuration {
    secret_token = "VeryRandomStringMoreThan20Byte!" <======== HMACの秘密鍵
  }

  filter { <================== CodePipelineの起動条件
    json_path    = "$.ref"
    match_equals = "refs/heads/{Branch}" <==== aws_codepipeline.example の Source.actionのBranchの意味=master
  }
}

Githubプロバイダ

  • 環境変数のGITHUB_TOKENが自動的に使用される
provider "github" {
  organization = "your-github-name"
}

Github Webhook

  • コードの変更を通知するためのWebhoook
resource "github_repository_webhook" "example" {
  repository = "your-repository"
  name       = "web"

  configuration {
    url          = aws_codepipeline_webhook.example.url
    secret       = "VeryRandomStringMoreThan20Byte!" <====== ここのsecretはauthentication_configuration.secret_tokenと同じにする
    content_type = "json"
    insecure_ssl = false
  }

  events = ["push"] <=========== pushだけではなく、pull_requestも指定できる。
}

Cloud9

無料HP作成手順

https://gist.github.com/mgoldchild/bca86490bd659c58d6df6cd3f9af0d69

SSH to GCP instance

$ gcloud init

$ gcloud config list
[core]
account = xxx@xxx.com
disable_usage_reporting = True
project = xxx-238307

Your active configuration is: [default]

$ gcloud compute instances list
NAME       ZONE           MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
wordpress  us-central1-a  f1-micro                   10.xxx.0.2   35.xxx.102.24  RUNNING

$ gcloud compute ssh wordpress
$ mike@wordpress:~$ sudo su mgoldchild

from ssh on web to update password of root user

mgoldchild@wordpress:~$ sudo passwd root
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully
mgoldchild@wordpress:~$ sudo passwd
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully

組み込み型

組み込み型 (built-in types)変更不可 (immutable)変更可 (mutable)反復可 (iterable)シーケンス (sequence)マッピング (mapping)データ (data)
boolTrue,False
int整数
float浮動小数点数
complex複素数
str文字列
list可変長配列
tupleタプル
range
dict連想配列、ハッシュ
set
bytesバイナリ
bytearray
file object

NOTE:

mutableな型の変数をキワード変数に入れるとそのまま引き継がれるので、注意!

def f(v, seq=[]):
  seq.append(v)
  return seq

print(f(12)) # [12]
print(f(23)) # [12, 23]
print(f(40)) # [12, 23, 40]

REFERENCES:

  • https://gammasoft.jp/blog/python-built-in-types/

組み込み関数

クラスの属性操作

関数意味
delattr(object, name)objectから属性nameを削除
getattr(object, name[, default])objectの属性nameの値を取得
hasattr(object, name)objectに属性nameがあるかをチェック
setattr(object, name, value)objectの属性nameの値をvalueに設定

クラスの属性定義

メソッド意味
__getattr__未定義のメンバーにアクセスする際に呼び出される。
__getattribute__未定義・定義済み関わらず、すべてのメンバーアクセスで呼び出される。

クラスのチェック

関数意味
isinstanceクラスのインスタンスかチェック
issubclassクラスのサブクラスのインスタンスかチェック

スコープモジュール

関数説明
dir引数に何も指定しなかった場合は、現在のローカルスコープにある名前(ローカルスコープで定義された変数、関数、クラスなど)を返送する。引数にオブジェクトを指定した場合はそのオブジェクトが持つ属性の一覧を返送する
globalsグローバルな名前空間に存在する名前の一覧を返送する
localsローカルな名前空間に存在する名前の一覧を返送する
vars引数に指定したオブジェクトが持つ__dict__属性を返送する。引数を指定しなかった場合は組み込み関数localsと同様

コードの動的評価

関数説明
compile引数に指定したPythonコードをコンパイルする
eval引数に指定したPythonコード(式)を評価する(代入文など、Pythonの文は渡せない)
exec引数に指定したPythonコードを実行する(複数の文を実行可能。戻り値は常にNone)

コンソール/ファイル

関数説明
inputコンソールからテキストを1行読み込む
open指定したファイルをオープンする
print指定したテキストをコンソールに出力する

その他

関数説明
help引数に指定したオブジェクトの説明

REF

  • https://www.atmarkit.co.jp/ait/articles/1704/28/news041_2.html

アクセッサー

class Car:
  @property
  def name(self):
    return self.__name

  @name.setter
  def name(self, value):
    self.__name = value

c = Car()
c.name = "TOYOTA"
print(c.name)

インデクサー

class Car:
  def __init__(self):
    self.ids = ["TOYOTA", "NISSAN", "HONDA"]
    
  def __getitem__(self, c):
    return self.ids[c]

  def __setitem__(self, c, v):
    self.ids[c] = v

c = Car()
print(c[0])
c[2] = "MITSUBISHI"
print(c[2])

Class Method vs. Static Method

  • インスタンスメソッドでインスタンス変数(self)使わない ⇒ クラスメソッド
  • クラスメソッドでクラス変数(cls)を使わない ⇒ スタティックメソッド
class ClassSample:
  class_var = "hoge"

  @classmethod
  def class_method(cls):
    print("%s, class_var: %s" % (cls, cls.class_var))

  @staticmethod
  def static_method():
    print("%s, class_var: %s" % (ClassSample, ClassSample.class_var))

class SubclassSample(ClassSample):
  class_var = "foo"

ClassSample.class_method() # -> __main__.ClassSample, class_var: hoge
ClassSample.static_method() # -> __main__.ClassSample, class_var: hoge
SubclassSample.class_method() # -> __main__.SubclassSample, class_var: foo
SubclassSample.static_method() #
インスタンス変数へのアクセスクラス変数へのアクセス継承時のクラス変数の値
クラスメソッド不可子のクラス変数の値
スタティックメソッド不可自クラスを宣言すれば可宣言したクラスに依存

REFERENCES:

  • https://qiita.com/1plus4/items/b37ec6ea90569ffdebfe

If VS. Assert

---TrueFalse
if処理を実行なにもしない
assertなにもしない例外を投げる

操作

# indexOf
[1, 2, 3].index(2)	# 1

# find
next((x for x in [1, 2, 3] if x == 2), None)	# 2

# find multi
list(filter(lambda x: x==2,  [1, 2, 3])) # [2]

# contains
2 in [1, 2, 3] # True

# all 
all(x < 10 for x in [1, 2, 3])	# True

# any
any(x < 2 for x in [1, 2, 3])	 # True

# filter
[x for x in [1, 2, 3] if x % 2 != 0]	# [1, 3]	
list(filter(lambda x: x % 2 != 0, [1,2,3])) # [1, 3]	

# map
[x+1 for x in [1, 2, 3]]	# [2, 3, 4]	
list(map(lambda x: x + 1, [1,2,3]) # [2, 3, 4]	

# uniq
list(set([1, 2, 3, 2, 1]))	# [1, 2, 3]	

# diff
[x for x in [1, 2, 3, 4, 5] if x not in list(set([5, 2, 10]))]	# [1, 3, 4]	

# zip
list(zip([1, 2], ["a", "b"], [True, False]))	# [(1, 'a', True), (2, 'b', False)]	

Windowsの文字化け

export JSON

import json

text = json.dumps(
    {"text":"あ"}, 
    sort_keys=True, 
    indent=4, 
    separators=(',', ': '),
    ensure_ascii=False,
)

with open("conv.json", "w", encoding='utf-8') as fd:
    fd.write(text)
    fd.close()

https://qiita.com/kurousa/items/f59ea18db9e33ef446f0

Print text

import sys
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
print('あ')

https://qiita.com/eleven-junichi2/items/f3fcb6abe7fe21a4d89a https://teratail.com/questions/130659

競プロスニペット

import sys, re
from math import ceil, floor, sqrt, pi, factorial, gcd
from copy import deepcopy
from collections import Counter, deque
from heapq import heapify, heappop, heappush
from itertools import accumulate, product, combinations, combinations_with_replacement
from bisect import bisect, bisect_left, bisect_right
from functools import reduce
from decimal import Decimal, getcontext
# input = sys.stdin.readline 
def i_input(): return int(input())
def i_map(): return map(int, input().split())
def i_list(): return list(i_map())
def i_row(N): return [i_input() for _ in range(N)]
def i_row_list(N): return [i_list() for _ in range(N)]
def s_input(): return input()
def s_map(): return input().split()
def s_list(): return list(s_map())
def s_row(N): return [s_input for _ in range(N)]
def s_row_str(N): return [s_list() for _ in range(N)]
def s_row_list(N): return [list(s_input()) for _ in range(N)]
def lcm(a, b): return a * b // gcd(a, b)
sys.setrecursionlimit(10 ** 6)
INF = float('inf')
MOD = 10 ** 9 + 7
num_list = []
str_list = []

def main():
    n = i_input()
    a, b = i_map()
    num_list = i_list()

    print()

if __name__ == '__main__':
    main()

REFERENCES:

  • https://qiita.com/Kota-Y/items/396ab3c57830dad65cfb

スニペット

from pathlib import Path
import glob

def split_imgs(src_dir , dis_dir, x_split_size):
   file_paths = glob.glob(f"{src_dir}/**/*.jpg", recursive = True)
   for file_path in file_paths:
       p = Path(file_path)
       dataset_name = p.parts[0]
       class_name = p.parts[1]
       file_name = p.stem
       ext_name = p.suffix
       full_file_name = p.name
       img_bgr = cv2.imread(file_path)
       height, width = img_bgr.shape[:2]

       next_width = int(width / x_split_size)
       for i in range(x_split_size):
           index = i+1
           x1 = next_width * i
           x2 = x1 + next_width 
           cropped_img_bgr = img_bgr[0:width, x1:x2]
           next_path = "/".join([dis_dir, class_name, f"{file_name}_{index}{ext_name}"])
           next_dir = "/".join([dis_dir, class_name])
           Path(next_dir).mkdir(parents=True, exist_ok=True)
           cv2.imwrite(next_path, cropped_img_bgr)

fix seed

import random
import numpy as np
import torch

seed = 42

random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed(seed) 

正規表現

記法

項目
1正規表現リテラル(/expression/)
2文字列リテラル('expression')をRegExpのコンストラクタへ

エスケープキャラクタ

項目
バックスラッシュがエスケープ文字\
一つと2つの違い1つは正規表現リテラル、2つは文字表現リテラル
バックスラッシュ+記号往々にして記号のエスケープ
バックスラッシュ+文字列往々にして定義済み文字列(文字クラス)
バックスラッシュ+数字往々にして後方参照

フラグ

項目
i(case insensitive)大文字小文字区別なし
g(case global)ローカルパターンでは最初の出現だけマッチするが、グローバルパターンではパターンの全ての出現にマッチする
m(multiple lines)複数行にマッチする
挿入方法正規表現リテラルの場合はスラッシュの後に挿入する。文字列リテラルの場合はRegExpの第二引数に文字列リテラルで挿入する

記述式

項と演算子

項目
式(expression)項と演算子で表現する
項(term)/test/だと4つの項がある。つまり、一文字がひとつの項
演算子(operation)記号やバックスラッシュなど

集合演算子(角括弧)

項目
集合演算子とは角括弧([])で表現する。各括弧の中は候補文字列(どれか一つにマッチさせたい文字列)を入れる。それが、一つの項となる
候補文字列角括弧の中に入れる[abc]の中のどれかにマッチさせたい時に使う
キャレット(^)ある文字列以外のマッチなら集合演算子の直後にキャレット(^)をつける。(集合演算子内の場合)
ダッシュ(-)[a-m]だとaからmまでの、辞書順のすべての文字を指定している
エスケープ(\)エスケープをすると特殊文字列($など)を候補文字列として指定することができる

アンカー($, ^)

項目
役割ある式の出現位置を固定する機能
先頭検索先頭のから場合は^を指定する。(集合演算子外の場合)
末尾検索末尾のから場合は$を指定する

繰り返し演算子(算術演算子など)

項目
?演算子ある項が1個あってもなくてもいい場合は?記号を対象項の末尾に指定する
+演算子ある項が一回以上の繰り返しの場合は+記号を対象項の末尾に指定する
*演算子ある項がゼロ回以上の繰り返しの場合は*演算子を対象項の末尾に指定する
波括弧演算子(引数一つ)ある項の繰り返し回数を指定する場合は、波括弧({})で記述し、第一引数にその回数を指定する
波括弧演算子(引数2つ)ある項の繰り返し回数の範囲を指定する場合は、波括弧({})で記述し、第一引数に下限、第二引数に上限を指定する。
Note: 上限を省略するには、{4, }のような形で指定する
欲張りと控えめな記述デフォルトは欲張りで、欲張りだとマッチする全てのパターンを検索する。控えめだと最小限のマッチの検索のみをする。
“aaa”という文字列を対象とし、/a+?/の場合は、a+を満足させるため、ただ一個のa文字にマッチする(?は最小量指定子)。

文字クラス(バックスラッシュ)

項目
改行や数字全部、英数字全部などはエスケープ キャラクターを使用し記述する

グループ化(括弧演算子+記号|文字)

項目
2つの役割がある。複数項のグループ化とキャプチャ指定である。
グループ化とは何か?括弧演算子を使って複数の項を一つの項にする。/(ab)+/などはabの一回以上の繰り返しを意味する
キャプチャ正規表現の一部に括弧を入れてグループ化すると作られるもの。後方参照できるようになる
受動的な部分式
キャプチャしない括弧(?:x)のように「?:」をグループに指定するとindexから参照できなくなる。($1などで)

選択肢(パイプ)

項目
1複数の選択肢はパイプ(|)を使って記述する

後方参照グループ化(括弧演算子+数字)

項目
バックスラッシュの後に数字を入れるとキャプチャを指定することができる。
XMLなどのマッチをする時に使う

先読み/後読み (lookahead, lookbehind)

意味
(?<=東京)東京が先に入っている(positive lookahead)
(?<!東京)東京が先に入っていない(negative lookahead)
(?=東京)東京が後に入っている(positive lookbehind)
(?!東京)東京が後に入っていない(negative lookbehind)

例: (?<=東京)(?<!大阪)特許(?=許可)(?!許諾)

東京特許許可局 <=== Matched
東京特許許諾
大阪特許許可局
大阪特許許諾

特殊文字

https://cloud.google.com/dataprep/docs/html/Supported-Special-Regular-Expression-Characters_57344771?hl=en

特殊文字の\w\w matches any word character (equal to [a-zA-Z0-9_]) とあるが、この [a-zA-Z0-9_]はあくまで英語の話で、日本語の場合は全角文字、半角カナ、半角英数字またはアンダースコア1文字なので注意!


>>> import re
>>> x = re.search("\w", "日本語")
>>> x
<re.Match object; span=(0, 1), match='日'>

https://www.translatejapan.com/translation/news/index3_2.php?no=131

Reference

  • https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/RegExp
  • http://www.htmq.com/js/RegExp_global.shtml

Tools

NameRole
PEP8the official style guide
Pycodestyle (Formerly PEP8)official linter tool to check the python code against the style conventions of PEP8 python
pylintpython linter which checks the source code and also acts as a bug and quality checker. It has more verification checks and options than just PEP8(Python style guide)
pyflakesverification tool(linter) which checks for Python files for errors
flake8wrapper around pyflakes, pycodestyle and McCabe script
hackinghacking is a set of flake8 plugins that test and enforce the OpenStack StyleGuide
blackThe uncompromising python code auto-formatter. Black reformats entire files in place and also formats the strings to have double-qoutes.
flake8-docstringssimple module that adds an extension for the fantastic pydocstyle tool to flake8
autopep8autopep8 automatically formats Python code to the PEP8 style. It fixes most of the formatting issues that are reported by pycodestyle.
yapfanother auto-formatter which is maintained by google
isortisort is a Python utility / library to sort imports alphabetically, and automatically separated into sections and by type
PyCheckera tool for finding bugs in python source code (old tool)
pydocstylea static analysis tool for checking compliance with Python docstring conventions.
mypyan official optional static type checker for Python that aims to combine the benefits of dynamic (or "duck") typing and static typing
Pyrightan open-source Python type checker and language server and much farster than mypy by MS
Pylancea tool wihch leverages Pyright’s functionality with additional features, some of which are not open-sourced

Conclusion

  • Editor:
    • VSCode
  • Settings:
    • See Setting.json
    • https://github.com/psf/black/blob/master/docs/compatible_configs.md
  • Linter:
    • flake8
  • Sorter:
    • isort
  • Formatter
    • autopep8 or black
  • Type Checker:
    • mypy or Pyright

REFERENCES:

  • https://www.kimoton.com/entry/20181223/1545540702
  • https://dev.classmethod.jp/articles/flake8-plugins-and-format-tools/
  • https://books.agiliq.com/projects/essential-python-tools/en/latest/linters.html
  • https://project.nikkeibp.co.jp/idg/atcl/idg/14/481709/032700526/
  • https://github.com/microsoft/pyright
  • http://mypy-lang.org/
  • https://minus9d.hatenablog.com/entry/2018/10/22/235604
  • https://qiita.com/irukiti/items/5d523c338f4affc9f722

ProjectとApp

特別なモジュール

モジュール用途
formsフォーム
managementpython manage.py xxx で使える。フォルダはmanagement/commands
migrationsマイグレーション
fixturesフィクスチャー
modelsモデル
templatesテンプレート。app配下でもフォルダはapp_name/xxxとする必要がある
templatetagsテンプレート用のヘルパ
testsテスト
viewsビューとビューセット
serializersシリアライザ
appsappの設定
admindjangoアドミン
urlsurl設定

ORM

メソッド戻り値
values()dict
values_list()tuple list
values_list(flat=True)list

REF

  • https://stackoverflow.com/questions/53239534/extract-only-values-without-key-from-queryset-and-save-them-to-list

ORM Relationship

Relationshipmethodsql
1:1select_related()join
N:1select_related()join
1:Nprefetch_related()in
N:Nprefetch_related()in

Example

  • User:UserSetting = 1:1
  • User:Comment = 1:N
class User(models.Model):
    name = models.CharField(max_length=32, default="foo", blank=False)

class UserSetting(models.Model):
    user = models.OneToOneField(User, related_name="karma")
    age = models.IntegerField(null=False, default=0)

class Comment(models.Model):
    user = models.ForeignKey(User, related_name="comments")
    content = models.CharField(max_length=140, null=False, default="")

select_relatedの挙動

Here, the relationship when each select_related() is done is as follows.

Relationshipyourselfjoin targetquery
1:1'UserUserSettingLEFT OUTER JOIN
1':1UserSettingUserINNER JOIN
M:1CommentUserINNER JOIN
1:MUserCommentx
  • one to one' is left outer join since there is a possibility that UserSetting doesn't exist
  • one to many is impossible

Query

OR query

from functools import reduce
from operator import or_
from django.db.models import Q

values = [1, 2, 3]
query = reduce(or_, (Q(pk=x) for x in values))

REFERENCES:

  • https://stackoverflow.com/questions/852414/how-to-dynamically-compose-an-or-query-filter-in-django
  • https://qiita.com/shati-taro/items/977ed91243ee99c9465f

Pluck

XXX.objects.values("name", "id")[1].get("id")

QueryStringify

>>> queryset = MyModel.objects.all()
>>> print(queryset.query)
SELECT "myapp_mymodel"."id", ... FROM "myapp_mymodel"

Filter

XXX.objects.filter(name="ABCさん")

district_count

Company.objects.values("name").distinct().count()

Count

>>> import django.db.models

>>> likes = Like.objects.all().select_related("comment", "note")
>>> users = MyUser.objects.prefetch_related(Prefetch("like_set", queryset=likes), "following", "followers")
>>> user = users.get(pk=11)
>>>
>>> user.like_set.filter(comment_id__isnull=False).count()
>>> user.like_set.aggregate(value=Sum(Case(When(note_id__isnull=False, then=1), default=0),output_field=IntegerField()))["value"]

DRF::Serializer

Model fields

https://www.webforefront.com/django/modeldatatypesandvalidation.html

Data typeDjango model typeSQLiteMySQLPostgreSQLOracleNotes
Binarymodels.BinaryField()BLOB NOT NULLlongblob NOT NULLbytea NOT NULLBLOB NULLCreates a blob field to store binary data (e.g. images,audio or other multimedia objects)
Booleanmodels.BooleanField()bool NOT NULLbool NOT NULLboolean NOT NULLNUMBER(1) NOT NULL CHECK ("VAR" IN(0,1))Creates a boolean field to store True/False (or 0/1)values
Booleanmodels.NullBooleanField()bool NULLbool NULLboolean NULLNUMBER(1) NULL CHECK (("VAR" IN (0,1)) OR ("VAR" IS NULL))Works just like BooleanField but also allows NULL values
Date/timemodels.DateField()date NOT NULLdate NOT NULLdate NOT NULLDATE NOT NULLCreates a date field to store dates
Date/timemodels.TimeField()time NOT NULLtime NOT NULLtime NOT NULLTIMESTAMP NOT NULLCreates a time field to store times.
Date/timemodels.DateTimeField()datetime NOT NULLdatetime NOT NULLtimestamp with time zone NOT NULLTIMESTAMP NOT NULLCreates a datetime field to store dates with times
Date/timemodels.DurationField()bigint NOT NULLbigint NOT NULLinterval NOT NULLINTERVAL DAY(9) TO SECOND(6) NOT NULLCreates a field to store periods of time.
Numbermodels.AutoField()integer NOT NULL AUTOINCREMENTinteger AUTO_INCREMENT NOT NULLserial NOT NULLNUMBER(11) NOT NULL & also creates a SEQUENCE and TRIGGER to increase the fieldCreates an integer that autoincrements, primarly used for custom primary keys
Numbermodels.BigIntegerField()bigint NOT NULLbigint NOT NULLbigint NOT NULLNUMBER(19) NOT NULLCreate a big integer to fit numbers between -9223372036854775808 to 9223372036854775807. This range may vary depending on the DB brand
Numbermodels.DecimalField(decimal_places=X,max_digits=Y)decimal NOT NULLnumeric(X, Y) NOT NULLnumeric(X, Y) NOT NULLNUMBER(10, 3) NOT NULLEnforces a number have a maximum X digits and Y decimal points Creates a decimal field to store decimal numbers. Note both X and Y arguments are required, where the X argument represents the maximum number of digits to store and the Y argument represents the number of decimal places to store.
Numbermodels.FloatField()real NOT NULLdouble precision NOT NULLdouble precision NOT NULLDOUBLE PRECISION NOT NULLCreates a column to store floating-point numbers.
Numbermodels.IntegerField()integer NOT NULLinteger NOT NULLinteger NOT NULLNUMBER(11) NOT NULLCreates a column to store integer numbers.
Numbermodels.PositiveIntegerField()integer unsigned NOT NULLinteger UNSIGNED NOT NULLinteger NOT NULL CHECK ("VAR" >= 0)NUMBER(11) NOT NULL CHECK ("VAR" >= 0)Enforces values from 0 to 2147483647 Works just like IntegerField but limits values to positive numbers
Numbermodels.PositiveSmallIntegerField()smallint unsigned NOT NULLsmallint UNSIGNED NOT NULLsmallint NOT NULL CHECK ("VAR" >= 0)NUMBER(11) NOT NULL CHECK ("VAR" >= 0)Enforces values from 0 to 32767 Works just like IntegerField and the specialized PositiveIntegerField but limits numbers to a smaller positive range.
Numberoptions.SmallIntegerField()smallint NOT NULLsmallint NOT NULLsmallint NOT NULLNUMBER(11) NOT NULLEnforces a number is in the range from -32768 to 32767 Works just like IntegerField but in a smaller integer range.
Textmodels.CharField(max_length=N)varchar(N) NOT NULLvarchar(50) NOT NULLvarchar(50) NOT NULLNVARCHAR2(50) NULLCreates a text column, where the max_length argument is required to specify the maximum length in characters.
Textmodels.TextField()text NOT NULLlongtext NOT NULLtext NOT NULLNCLOB NULLCreates a text field to store text.
Text (Specialized)models.CommaSeparatedIntegerField(max_length=50)varchar(N) NOT NULLvarchar(N) NOT NULLvarchar(N) NOT NULLNVARCHAR2(N) NULLEnforces the string a CSV of integers.Works just like CharField except Django enforces the string be a comma separated value of integers prior to interacting with the database (e.g. 3,54,54,664,65)
Text (Specialized)models.EmailField()varchar(254) NOT NULLvarchar(254) NOT NULLvarchar(254) NOT NULLNVARCHAR2(254) NULLEnforces the text is a valid email with the internal Django EmailValidator to determine what is and isn't a valid. Works just like CharField defaulting to a max_length of 254 characters and also enforces the string is a valid email.
Text (Specialized)models.FileField()varchar(100) NOT NULLvarchar(100) NOT NULLvarchar(100) NOT NULLNVARCHAR2(100) NULLEnforces and provides various utilities to handle files (e.g. opening/closing file, upload location,etc). Works just like CharField defaulting to a max_length of 100 characters and also enforces the string is a valid file.
Text (Specialized)models.FilePathField()varchar(100) NOT NULLvarchar(100) NOT NULLvarchar(100) NOT NULLNVARCHAR2(100) NULLEnforces and provides various utilities to limit choices of filenames in certain filesystem directories. Works just like CharField defaulting to a max_length of 100 characters and also enforces the string is a valid file in a filesystem directory.
Text (Specialized)models.ImageField()varchar(100) NOT NULLvarchar(100) NOT NULLvarchar(100) NOT NULLNVARCHAR2(100) NULLEnforces and provides various utilities to handle image files (e.g. getting the height & width) Works just like CharField and the specialized FileField defaulting to a max_length of 100 characters and also enforces the string is a valid image. Note this field requires the presence of the Pillow Python library (e.g. pip install Pillow).
Text (Specialized)models.GenericIPAddressField()char(39) NOT NULLchar(39) NOT NULLinet NOT NULLVARCHAR2(39) NULLEnforces and provides various utilities to only accept valid IPv4 or IPv6 addresses (e.g. 198.10.22.64 and FE80::0202:B3FF:FE1E:8329, as well as utilities like unpack_ipv4 and protocol) Works just like CharField defaulting to a max_length of 39 characters and enforces the string is a valid IP address.
Text (Specialized)models.SlugField()varchar(50) NOT NULLvarchar(50) NOT NULLvarchar(50) NOT NULLNVARCHAR2(50) NULLEnforces a string is a slug string, which is a string that only contains letters, numbers, underscores or hyphens. Works just like CharField defaulting to a max_length of 50 characters and ensure the provided string is a slug -- a concept that's typically used to cleanse URL strings that contains spaces and other potentially invalid character like letter with accents.
Text (Specialized)models.URLField()varchar(200) NOT NULLvarchar(200) NOT NULLvarchar(200) NOT NULLNVARCHAR2(200) NULLEnforces the provided text value is a valid URL Works just like CharField defaulting to a max_length of 200 characters and enforces the string is a valid URL
Text (Specialized)models.UUIDField()char(32) NOT NULLchar(32) NOT NULLuuid NOT NULLVARCHAR2(32) NOT NULLEnforces the provided text is a Universally unique identifiers (UUID) Works just like CharField defaulting to a max_length of 32 characters and enforces the value is a UUID.

Model Fields Blank and Empty

blank=True, null=True

pattern(DB) null(Form) blankmeaning
FalseFalseThis field is required when submitting from a form, and the value stored in the database must not be empty
TrueTrueThis field is not required when submitting from a form, it doesn't have to be in the value stored in the database.
FalseTrueThis field is not required when submitting from a form, but the value stored in the database must not be empty.
TrueFalseThis field must be entered when filling out the form, but the database value can be empty.

Conclusion:

  • ① and ② is ordinary usage
  • ③ is for str field.
    • string values such as CharField and TextField, empty values are stored as empty strings instead of null.
    • For this reason, only blank = True can be specified for fields that handle character strings.
    • It means We want to store "" to DB.
  • ④ is weird.
    • since There is a something values definitely from Form, DB never be going to be null.

URL

Django URLs

  • name
  • Namespace
  • App Name

Name

name is a name of URL pattern.

url(r'^$', views.IndexView.as_view(), name='index')

From views

reverse('index')

From templates

{% url 'index' %}

Namespace

namespace is a namespace in the project specified in urls.py on including app side

url(r'^polls/', include('polls.urls', namespace='polls'))

From views

reverse('polls:index')

From templates

{% url 'polls:index' %}

App Name

app_name is a namespace in the project specified in urls.py on the included app side

app_name = 'polls'
urlpatterns = [
    url(r'^polls/', include('polls.urls')),  # 'namespace="polls"' removed
...
]

From views

reverse('polls:index')

From templates

{% url 'polls:index' %}

Security

django

https://docs.djangoproject.com/en/3.0/ref/csrf/

drf

https://www.django-rest-framework.org/api-guide/testing/#csrf

ProjectとApp

次元拡張・縮小

次元拡張 np.expand_dims torch.unsqueeze

次元縮小 np.squeeze torch.squeeze

Dataset vs. Dataloader

in pytorch and fastai

datset = [all data]
sampler = [subset of datset] # useally used for dividing train, valid and test
batch = [subset of sampler]
dataloader = [batch_1, batch_2, ... batch_n]
dataBunch = {train_dl: deviceDataloader, valid_dl: deviceDataloader, test_dl: deviceDataloader}
deviceDataloader = {dl: dataloader}

len(datasets)="size of all data"
len(sampler)="size of sample"
len(dataLoader)="size of batch"
len(dataBunch)="size of bunch?"

dataset = torchvision.datasets.ImageFolder
sample = torch.utils.data.sampler.SubsetRandomSampler
dataloader = torch.utils.data.DataLoader
databunch = fastai.DataBunch
deviceDataloader = fastai.DeviceDataLoader

learner = {data:dataBunch, model:module, opt_func:'adam', loss_func:l2Loss}
learner.fit(epoch=int, lr=float)

Dataloaderは__iter__と__next__が定義されているので、 iter(Dataloader).next() としてあげれば最初から1バッチずつ取り出すことができます。 デバッグする時等に便利。

images, labels= iter(train_dl).next() # pytorchの場合
images, labels= iter(deviceDataloader.train_dl.dl).next()

REF

  • https://qiita.com/tomp/items/3bf6d040bbc89a171880

CUDA Memory Release

$ nvidia-smi
$ lsof /dev/nvidia*
$ ps f -o user,pgrp,pid,pcpu,pmem,start,time,command -p `lsof -n -w -t /dev/nvidia*`
$ kill -9 $(lsof -t)

REFERENCES:

  • https://gist.github.com/mgoldchild/c79345ed56d712466a2818a615714d4e

自動微分

import torch

# テンソルを作成
# requires_grad=Trueで自動微分対象を指定
x = torch.tensor(1.0, requires_grad=True)
w = torch.tensor(2.0, requires_grad=True)
b = torch.tensor(3.0, requires_grad=True)

# 計算グラフを構築
# y = 2 * x + 3
y = w * x + b

# 勾配を計算
y.backward()

# 勾配を表示
print(x.grad)  # dy/dx = w = 2
print(w.grad)  # dy/dw = x = 1
print(b.grad)  # dy/db = 1

requires_grad

requires_gradでは,requires_grad=Trueとすることで微分対象のtensorを指定します.デフォルトではrequires_grad=Falseとなっており,このままだと微分の対象にはならず,勾配にはNoneが返ります.requires_grad=FalseはFine-tuningで層のパラメータを固定したいときに便利だそうです.

grad_fn

autogradにはFunctionと言うパッケージがあります.requires_grad=Trueで指定されたtensorとFunctionは内部で繋がっており,この2つで計算グラフが構築されています.この計算グラフに計算の記録が全て残ります.生成されたtensorのそれぞれに.grad_fnという属性があり,この属性によってどのFunctionによってtensorが生成されたのかを参照できます.ただし,ユーザによって作られたtensorの場合grad_fnはNoneとなります.

a = torch.tensor(1.0, requires_grad=True)
print(a.grad_fn) # None

b = a+2 # bは足し算(add)によって形成
print(b.grad_fn) # <AddBackward object at 0x7f740ffc0eb8>

BGR_to_RGB without cvt

https://stackoverflow.com/questions/54959387/rgb-image-display-in-matplotlib-plt-imshow-returns-a-blue-image

image = cv2.imread("path/to/file/image.jpg")[:,:,::-1]

Init for SageMaker

importのデフォ

インスコしたパッケージ

$ pipenv install pandas
$ pipenv install kaggle
$ pipenv install numpy
$ pipenv install scipy
$ pipenv install sklearn
$ pipenv install jupyterlab
$ pipenv install jupytext
$ pipenv install matplotlib
$ pipenv install seaborn

Install Jupyter Lab Packages

$ jupyter labextension install @lckr/jupyterlab_variableinspector
$ jupyter labextension install @jupyterlab/toc

OR

$ jupyter labextension list
JupyterLab v0.35.4
Known labextensions:
   app dir: /home/mike/.local/share/virtualenvs/titanic-wXc5dux6/share/jupyter/lab
        @jupyterlab/toc v0.6.0  enabled  OK
        @lckr/jupyterlab_variableinspector v0.1.0  enabled  OK

スニペット

import cv2
import matplotlib.pyplot as plt

文字化け対策

インストール済みのフォントを探す

$ fc-list 
/usr/share/fonts/noto/NotoSansNabataean-Regular.ttf: Noto Sans Nabataean:style=Regular
/usr/share/fonts/OTF/ipag.ttf: IPAGothic,IPAゴシック:style=Regular
/usr/share/fonts/droid/DroidSansFallbackFull.ttf: Droid Sans:style=Regular
/usr/share/fonts/noto/NotoSans-BoldItalic.ttf: Noto Sans:style=Bold Italic
/usr/share/fonts/TTF/DejaVuSans-Bold.ttf: DejaVu Sans:style=Bold
/usr/share/fonts/noto/NotoSerifSinhala-Bold.ttf: Noto Serif Sinhala:style=Bold
/usr/share/fonts/noto/NotoSerifMyanmar-Thin.ttf: Noto Serif Myanmar,Noto Serif Myanmar Thin:style=Thin,Regular
/usr/share/fonts/noto/NotoSerifDevanagari-Regular.ttf: Noto Serif Devanagari:style=Regular
/usr/share/fonts/noto/NotoSerifTamil-Bold.ttf: Noto Serif Tamil:style=Bold
/usr/share/fonts/noto/NotoSerifTangut-Regular.ttf: Noto Serif Tangut:style=Regular
/usr/share/fonts/TTF/Inconsolata-ExtraCondensedMedium.ttf: Inconsolata,Inconsolata Extra Condensed Medium:style=Extra Condensed Medium,Regular

日本語を使う画像の場合はフォントを指定する

plt.rcParams["font.family"] = "IPAGothic"

Kill Process by Port

fuser -k 8080/tcp
lsof -i4

https://stackoverflow.com/questions/11583562/how-to-kill-a-process-running-on-particular-port-in-linux

シェルスクリプト

Doller sign の意味

  • $1, $2, $3, ... are the positional parameters.
  • "$@" is an array-like construct of all positional parameters, {$1, $2, $3 ...}.
  • "$*" is the IFS expansion of all positional parameters, $1 $2 $3 ....
  • $# is the number of positional parameters.
  • $- current options set for the shell.
  • $$ pid of the current shell (not subshell).
  • $_ most recent parameter (or the abs path of the command to start the current shell immediately after startup).
  • $IFS is the (input) field separator.
  • $? is the most recent foreground pipeline exit status.
  • $! is the PID of the most recent background command.
  • $0 is the name of the shell or shell script.

コロンの意味

  • :は何もしないコマンド。
  • 使いみちは、正常終了させたい時に使う(set -eと併用など)
  • set -eはnon zeroなコードが返った場合は終了するので

boolean

WAIT_FOR_IT=false

if "${WAIT_FOR_IT}"; then
  echo "TRUE!!!"
fi

REF

  • https://stackoverflow.com/questions/5163144/what-are-the-special-dollar-sign-shell-variables

TTY/PTS

用語意味
ttyはteletypewriter)native terminal device
pty (pseudo terminal device)terminal device which is emulated by an other program (example: xterm, screen, or ssh are such programs).
pts (pseudo terminal slave)A pts is the slave part of a pty

自分の端末

$ tty
/dev/pts/9 

ログイン中のユーザー一覧

$ w
 19:34:16 up 20:31, 10 users,  load average: 2.02, 1.64, 1.59
USER     TTY        LOGIN@   IDLE   JCPU   PCPU WHAT
mike     :1        Thu23   ?xdm?   3:48m  0.01s /usr/lib/gdm-x-session --run-script /usr/bin/gnome-session
mike     pts/1     Thu23   44:27   0.00s  0.00s tmux
mike     pts/2     Thu23   44:27  12.17s  4.01s /usr/bin/python /usr/bin/pipenv shell
mike     pts/3     Thu23    0.00s  0.00s  0.00s tmux
mike     pts/4     Thu23   19:55m  2:47   2:46  mdbook serve -p=5000
mike     pts/5     Thu23    3:59m  2.12s  0.06s psql -h localhost -p 5432 -U root -W root
mike     pts/6     Thu23   18:35m  1.81s  0.92s /usr/bin/python /usr/bin/pipenv shell
mike     pts/8     Thu23   20:12m  0.27s  0.27s -zsh
mike     pts/9     Thu23    0.00s  8.45s  0.02s w
mike     pts/10    Thu23    2:45m  0.56s  0.56s -zsh

別ターミナルにコマンドを送る

fdの

$ ps
    PID TTY          TIME CMD
  17935 pts/10   00:00:00 zsh
 113650 pts/10   00:00:00 ps
$ ll /proc/17935/fd
dr-x------ mike mike  0 B Fri Sep 11 19:42:51 2020  .
dr-xr-xr-x mike mike  0 B Fri Sep 11 17:14:09 2020  ..
lrwx------ mike mike 64 B Fri Sep 11 19:42:53 2020  0 ⇒ /dev/pts/10
lrwx------ mike mike 64 B Fri Sep 11 19:42:53 2020  1 ⇒ /dev/pts/10
lrwx------ mike mike 64 B Fri Sep 11 19:42:53 2020  10 ⇒ /dev/pts/10
lr-x------ mike mike 64 B Fri Sep 11 19:42:53 2020  11 ⇒ /home/mike/.antigen/init.zsh.zwc
lrwx------ mike mike 64 B Fri Sep 11 19:42:53 2020  2 ⇒ /dev/pts/10

別のターミナルにメッセージ送信

echo "test" > /dev/pts/10

File System/Process/Strem

Linuxの仕組みを抽象的に構造体のやり取りとして説明すると、その3つにまとまる

用語意味
File Systemデータを保管するnode
Stream通信するためのedge
Processデータ処理をするためのnode

REFERENCES:

  • ふつうのLinuxプログラミング

Docker

すべてのコンテナを停止する

$ docker stop $(docker ps -q)

すべてのコンテナ削除

$ docker rm $(docker ps -q -a)

Arg vs Env

コマンドimage buildrun process
Arg使用される使用されない
Env使用されない使用される
--build-arg VAR_NAME=6 

Run vs. Cmd

コマンドimage buildrun process制約
Run使用される使用されない複数OK
Cmd使用されない使用されるデフォルトの引数や推奨パラメータ
ENTRYPOINT使用されない使用されるコンテナで必ず実行したいコマンドや引数

よく利用されるentrypoint.shファイル

#!/bin/bash
set -e # エラーがあったらシェルスクリプトをそこで打ち止めにしてくれる

... code ...

exec "$@" # entrypoint.sh echo "OK" => "OK" となる

REF

  • https://sousaku-memo.net/php-system/1164
  • https://vsupalov.com/docker-arg-vs-env/

SSH設定

TL;DR

Mac->UbuntuのSSHの備忘録です。 図書館用に443(HTTPS)も開けています。

クライアントの設定(Mac)

項目コマンド
ディレクトリの作成mkdir ~/.ssh/
キーの作成cd ~/.ssh/
ssh-keygen -t rsa #パスフレ無し
config作成vim ~/.ssh/config #以下の設定内容を貼り付け
パーミッションの変更sudo chmod -R 700 ~/.ssh/
sudo chmod 600 ~/.ssh/id_rsa
公開鍵コピーcat ~/.ssh/id_rsa.pub

クライアントのconfigの設定内容

# server
Host blog
    HostName            123.456.789.012
    Port                22 #or 443
    IdentityFile        ~/.ssh/id_rsa
    User                john
    Protocol            2
    ServerAliveInterval 15
    ServerAliveCountMax 10

# gitlab
Host gitlab
    HostName            gitlab.com
    IdentityFile        ~/.ssh/id_rsa

サーバーの設定(Ubuntu)

項目コマンド
ポート開放sudo ufw allow 22/tcp
ポート開放(HTTPS)sudo ufw allow 443/tcp
Firewallの有効化sudo ufw enable
ディレクトリの作成mkdir ~/.ssh/
ファイルの移動cd .ssh
キーの追加cat ~/id_rsa.pub >> authorized_keys
公開鍵の削除rm ~/id_rsa.pub
パーミッションの変更sudo chmod -R 700 ~/.ssh/
sudo chmod 600 ~/.ssh/authorized_keys

SSHd側で443ポートの追加

項目コマンド
複数ポートでlistensudo vi /etc/ssh/sshd_config # Port 443を追加する
再起動sudo shutdown -r now
開放しているポートの確認sudo lsof -i -nP # 443でlistenしてればOK

テスト(Mac)

項目コマンド
普通に接続ssh -i ~/.ssh/id_rsa john@123.456.789.012
configで接続ssh blog
設定ファイルを明示的に読み込んで接続ssh -F ~/.ssh/config blog
REMOTE HOST IDENTIFICATION HAS CHANGEDの時ssh-keygen -R 123.456.789.012 # ホストをknown_hostsファイルから削除

テスト(リポジトリ)

項目コマンド
接続テストssh -T git@github.com
アップストリームのorigin削除git remove origin master
アップストリームのorigin追加git remote add origin git@github.com:{userName}/{repositoryName}.git

関係ないがオレオレ証明書のmemo

$ openssl genrsa 2048 > server.key
$ openssl req -new -key server.key > server.csr
$ openssl x509 -days 3650 -req -signkey server.key < server.csr > server.crt

参考文献

http://runble1.com/ubuntu-config-ssh/ http://superbrothers.hatenablog.com/entry/20090730/1248971671 http://serverfault.com/questions/518729/cygwin-ssh-issue-could-not-resolve-hostname-awshost1-hostname-nor-servname-pro http://www.unixuser.org/~euske/doc/openssh/jman/ssh_config.html http://qiita.com/tag1216/items/5d06bad7468f731f590e
http://d.hatena.ne.jp/ozuma/20130511/1368284304

GPG

Generate a new key

[mike@mike-pc ~][19:03:13][Py:3.8.1][O][I][%][λ]> gpg --full-gen-key
gpg (GnuPG) 2.2.19; Copyright (C) 2019 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
  (14) Existing key from card
Your selection?
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: mike
Name must be at least 5 characters long
Real name: mgoldchild
Email address: mgoldchild@gmail.com
Comment:
You selected this USER-ID:
    "xxx <xxx@example.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: WARNING: server 'gpg-agent' is older than us (2.2.18 < 2.2.19)
gpg: Note: Outdated servers may lack important security fixes.
gpg: Note: Use the command "gpgconf --kill all" to restart them.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

gpg: key BDDB43041BF65C3E marked as ultimately trusted
gpg: directory '/home/mike/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/mike/.gnupg/openpgp-revocs.d/00637C918AFC60EF6C53F8FEBDDB43041BF65C3E.rev'
public and secret key created and signed.

pub   rsa4096 2020-01-17 [SC]
      00637C918AFC60EF6C53F8FEBDDB43041BF65C3E
uid                      xxx <xxx@example.com>
sub   rsa4096 2020-01-17 [E]

[mike@mike-pc ~][19:06:59][Py:3.8.1][O][I][%][λ]>
[mike@mike-pc ~][19:07:10][Py:3.8.1][O][I][%][λ]> gpg --list-secret-keys --keyid-format long
gpg: WARNING: server 'gpg-agent' is older than us (2.2.18 < 2.2.19)
gpg: Note: Outdated servers may lack important security fixes.
gpg: Note: Use the command "gpgconf --kill all" to restart them.
/home/mike/.gnupg/pubring.kbx
-----------------------------
sec   rsa4096/BDDB43041BF65C3E 2020-01-17 [SC]
      00637C918AFC60EF6C53F8FEBDDB43041BF65C3E
uid                 [ultimate] xxx <xxx@example.com>
ssb   rsa4096/5F95054F1052FAC5 2020-01-17 [E]

[mike@mike-pc ~][19:08:08][Py:3.8.1][O][I][%][λ]> gpg --armor --export BDDB43041BF65C3E
...

https://docs.gitlab.com/ee/user/project/repository/gpg_signed_commits/

export and import

$ gpg --export-secret-key -a > secretkey.asc
$ gpg --import secretkey.asc
$ shred --remove secretkey.asc

https://askubuntu.com/questions/32438/how-to-share-one-pgp-key-on-multiple-machines

Git Commands

たまに忘れるので、自分にもわかりづらい適当なメモを残します。

基本

用語概念
GIT警察、検察
リポジトリ
ファイル人間
ファイルの変更犯罪
アントラッキングファイル不法入国者
アンモディファイドファイルカタギ
モディファイドファイル被疑者
ステージドファイル被告人
コミット服刑
ブランチ前科
ステージング裁判所

18333fig0201-tn.png

逮捕&起訴

$ git add <Filename>
$ git add . # 全部
$ git add -p # 対話式で選択

判決

$ git commit -m 'commit message' # 判決理由が入る

強制送還

$ rm <filename> # 普通に削除
$ git clean -f # 先に--dry-run で確認すると酔い

免罪、誤認逮捕、不起訴

$ git rm <filename>
$ git mv <filename>
$ git reset <filename> # addしたindexにあるfileをindexから除外
$ git reset --hard HEAD^
$ git reset --hard <commit hash> # 刑の免除
$ git revert <commit hash> # 逆位相
$ git rebase -i # タイムリープ
$ git checkout <commit hash>

処分保留?

$ git stash list
$ git stash save -u <message> # アントラッキングも含める
$ git stash apply <stash number>
$ git stash drop <stash number>
$ git stash clear # 全消し

比較系

$ git diff 
$ git diff --cached
$ git diff HEAD HEAD^

取り調べ

$ git status
$ git status --short

実刑の確認

$ git show <commit name>

前科の確認

$ git log 
$ git log --graph --date=short --format='%C(yellow)%h%C(reset) %C(magenta)[%ad]%C(reset)%C(red)%d%C(reset) %s %C(cyan)@%an%C(reset)' # aliasのやつ

マージ系

$ git merge <branchname> # 現在のブランチに別のブランチをマージ
$ git push -f # プルリク歴史修正の時の強制プッシュ
$ git push origin <local branchname> # 現在のブランチをリモートにマージ
$ git pull origin <remote branchname> # リモートのブランチを現在のブランチにマージ
$ git fetch # originの今のブランチの変更履歴を取得 --allだと全てのブランチ
$ git mergetool

ブランチ刑

$ git reflog # ブランチの操作ログ
$ git checkout -b <branchname> # ブランチを作成してチェックアウト
$ git branch -a  # 全部ブランチ名の確認
$ git branch -r  # リモート全部ブランチ名の確認
$ git branch -v  # 詳細表示
$ git branch -d <branchname> # ローカルのを削除
$ git push origin :<branchname> # リモートに削除

$ git fetch
$ git checkout master
$ git merge origin/master

タグとか

$ git tag # tag一覧
$ git tag <tagname> # タグ付け
$ git -d <tagname> # ローカルのタグ削除
$ git push origin :<tagname> # リモートに削除
$ git push origin --tags # タグ全部送信

最初にやること

$ git init # 一から作る
$ git remote add origin git@<ssh hostname>:<myname>/<reponame>.git
$ touch README.md
$ git add .
$ git commit -m 'init'
$ git push -u origin master
$ git clone # 他人のパクる

不法入国者へ戻す

$ git rm --cached "filename"
$ echo "filename" >> .gitignore 

submodule

$ git submodule add https://github.com/twbs/bootstrap.git bootstrap
$ git submodule update # 内部submoduleを同期する

後からgitignoreに追加

$ echo "hoge.tmp" >> .gitignore
$ git rm --cached hoge.tmp

リベース

マージとリベースの違い

※Gitは共通の祖先のコミットから比較してdiffを出している。

$ # 下図だと、共通の親はCなのでCからFまでの変更点(EとDへ変更した内容)としてまとめられる
$ checkout master && git merge topic 
$ # 下図だと、共通の親はEなのでEからD'までの変更点(Dで変更した内容)としてまとめられる
$ checkout topic && git rebase master

マージ image リベース image

プルリクが別のプルリクに依存する場合のプルリクの作り方

$ git fetch --all # リモートのブランチ一覧取得
$ git checkout develop # developブランチは派生元にしたいブランチ(このブランチはmasterから派生していおり、変更が今後ありそうにないブランチ、プルリクではLGTM済み)
$ git checkout feature # developブランチから新たなfeatureを作成する
$ # featureブランチのプルリク作成
$ git commit -m "追加" # featureに追加する
$ # developのプルリクがmasterにマージされた
$ git fetch --all # リモートのブランチ一覧取得
$ git checkout feature 
$ git rebase develop # featureブランチの上で最新のdevelopにrebaseする
$ git push origin feature -f # フォースプッシュでプルリクの履歴を書き換える

プルリクのコミットをキレイにする(rebase squash)

$ git rebase -i <commit hash> # 修正したいコミットの一つ前のコミットのハッシュを指定する(0d4a808の前のコミットを指定する)

pick 9a54fd4 commitの説明を追加   # <- この中で一番古いのコミット
squash 0d4a808 pullの説明を追加    # <- これをsオプションで上のコミットと混ぜられる

# Rebase 326fc9f..0d4a808 onto d286baa
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
$ git push origin hoge -f
$ # もしcannot squash without a previous commitが出た場合
$ git rebase --abort

プルリクの過去のコミットを変更する(rebase edit)

  • 空のコミットメッセージと内容のcommitがある場合は下手に
$ git rebase -i <commit hash> # 修正したいコミットの一つ前のコミットのハッシュを指定する(0d4a808の前のコミットを指定する)

pick 9a54fd4 commitの説明を追加   # <- この中で一番古いのコミット
edit 0d4a808 pullの説明を追加      # <- このコミットでの変更内容を再変更する

# Rebase 326fc9f..0d4a808 onto d286baa
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
$ vim hoge.js 
$ git add hoge.js # 変更を追加
$ git commit --amend # コミットに追加する
$ git rebase --continue # コミットを適用する
$ git push origin hoge -f

リベースのマージ

$ git rebase branch
// コンフリクトしたファイルを修正後
$ git add conflicted_file
$ git commit
$ git rebase --continue
$ git rebase --abort // ダメそうだったら

スタッシュ

コマンドをよく忘れるが次を見ればいい。 https://qiita.com/akasakas/items/768c0b563b96f8a9be9d

コンフリクト解消

$ git pull origin master # コンフリ発生!!
$ git reset --hard ORIG_HEAD # マージを元にもどす

リベース前のブランチからの派生した新ブランチを、リベース済みの元ブランチへのリベースする方法

  • develop > feature > hotfix の順で派生しておりhotfixがfeatureの機能に依存している
    1. featureをdevelopでrebaseした(その結果featureのコミット番号が全部変わった)
    2. bugfixをfeatureでrebaseしようとするとconflictが発生した(しかも、diffがめちゃくちゃ)
$ git push origin hotfix # rebase前のhotfixのバックアップ
$ git checkout hotfix
$ git rebase --onto feature ff34ed1 # featureを元にしたff34ed1に続くcommitを持つhotfixのブランチを作る
$ # つまり、
$ # - ff34ed1は古いfeature(リベースされる前)の最後のcommit番号。
$ #   - つまり、hotfixのPRのコミットログにあるfeatureの最後のCommit番号 
$ #   - 別の言い方をすればhotfixブランチの元のcommit番号
$ # - featureオプションはもちろん新しいrebase済みのブランチを指す
First, rewinding head to replay your work on top of it...
Applying: AAAAAAAA #31
Applying: XXXXXXX #31
Applying: VVVVVVV #31
$ git diff master --stat # hotfixのPRのdiffとくらべて同じなら多分大丈夫
6 files changed, 251 insertions(+), 3 deletions(-)

つまり、rebaseされた元のブランチfeaturに、 rebaseされる前のfeatureの最後のcommit(hotfixの元のcommit)を足したということ

リベース前のブランチからの派生した新ブランチ(マージコミット済み)を、リベース済みの元ブランチへのリベースする方法

master > feature > hotfix の順でhotfixはfeatureからrebaseで切った。
ただし、masterが別のブランチ(feature2)でマージされ、歴史が進められたので、featureブランチとfeature2ブランチでconflictした
そこで、featureブランチをmasterでmergeし、マージコミットをfeatureブランチに作って、conflictを解消した
その後、featureブランチはmasterブランチにマージした(mergeコミットありで)
hotfixはfeatureから切られているので、featureに再rebaseしたが、hotfixの修正内容が反映されていない。
その時は、hotfixをmasterブランチでmergeして解消するのが良い。

同一ファイルを分割してCommit

$ git add -p
y or n or q...
$ git diff --cached # the diff between staging and HEAD

あるファイルをあるコミット/ブランチの前に戻す

$ git checkout c5f567~1 -- file_a.py file_b.py

https://stackoverflow.com/questions/215718/reset-or-revert-a-specific-file-to-a-specific-revision-using-git

--no-ff --no-commit

https://qiita.com/nog/items/c79469afbf3e632f10a1

参考文献

  • https://liginc.co.jp/web/tool/79390
  • http://www.backlog.jp/git-guide/stepup/stepup7_5.html
  • https://stackoverflow.com/questions/27445747/how-to-rebase-over-already-rebased-branch
  • https://stackoverflow.com/questions/1587846/how-do-i-show-the-changes-which-have-been-staged

DVC

管理方法

S3でのセットアップ

先にバケットとIAM User(S3FullAccess)を作っておく、 そして.envで設定しておき、pipenvで読み込み、その後.envを作成する。

$ cp .env.example .env

初期設定

$ dvc init

リモート設定

ローカルでのデータの管理ディレクトリの設定

$ dvc remote add mylocal /tmp/local_storage

リモートでデータの管理パスの設定 (-dでデフォルトになる)

$ dvc remote add -d newremote s3://mydvc/bush-api

リモートの確認

$ dvc remote list
mylocal /tmp/local_storage
newremote       s3://mydvc/bush-api

NOTE:

  • デフォルト以外で実行する時は、明示的に--remote mylocalが必要

追加時

DVCではcommitは不要

$ touch data/data.xml
$ dvc add data/data.xml
$ git add data/.gitignore data/data.xml.dvc
$ git commit -m "add data.xml"

Push

$ dvc push
$ git push origin main

Status

$ dvc status

Checkout

$ dvc checkout data/data.xml

Fetch

$ git fetch
$ dvc fetch

Pull

$ git pull origin main
$ dvc pull

参考文献

  • https://takaherox.hatenablog.com/entry/2020/02/24/134850
  • https://dvc.org/doc/command-reference/remote/add

VIM文法

たまに頭が混乱するのでメモ

モード

モード機能切替方法
ノーマルカーソルの移動や文字列のヤンクなどができるvimを起動したとき、もしくは「esc」を押す
挿入文字列の挿入ができるノーマルモードで「i」「a」「I」「A」のいずれかを押す
ビジュアル矩形選択ができるノーマルモードで「v」「V」「Ctrl+v」のいずれかを押す
exコマンドファイルの保存や文字列の検索ができるノーマルモードで「:」「/」「?」のいずれかを押す

文型

文型
第1文型(C){command}
第2文型(M){motion}
第3文型(OM){operator}{motion}
第4文型(SO){selector}{operator}
第5文型(OT){operator}{text-object}

品詞

コマンド機能
コマンド(C)それ一つで編集(編集対象と編集方法)が完結する操作
モーション(M)基本的に行を示す操作。カーソルの移動にも使う
オペレーター(O)編集方法を示す操作
セレクター(S)行列(矩形)の編集範囲を示す操作
テキストオブジェクト(T)編集するテキストを示す操作。記号などで囲まれているものの中を編集範囲にできる
カウント各文の繰り返し回数を示す操作

第一文型(C)

スクロール移動

コマンド機能
Ctrl-u半画面分の上へ(アップ)
Ctrl-d半画面分の下へ(ダウン)
Ctrl-b一画面分の上へ(バックフォワード)
Ctrl-f一画面分の下へ(フォワード)

行に対する編集

コマンド機能
ddカーソルのある行デリート
Dカーソルから行末までデリート
ccカーソルのある行カット
Cカーソルから行末まで行カット
yyカーソルのある行までヤンク
Yカーソルから行末までヤンク
sカーソルのある文字を消して挿入モードに入る
Sカーソルのある1行を全て消して挿入モードにはいる

カットとプット

コマンド機能
xカーソルの下の文字を消す
Xカーソル一つ前の下の文字を消す
pカーソルの下の行にプット
Pカーソルの行にプット

数値の編集

コマンド機能
Ctrl-aカーソルのある行の数値を足す(インクリメント)
Ctrl-xカーソルのある行の数値を減らす(デクリメント)

アンドゥ・リドゥー、 繰り返し

コマンド機能
uアンドゥー
Ctrl-rリドゥー
.直前のコマンドを繰り返す

インデントの編集

コマンド機能
>>インデントをつける
<<インデントをなくす
ctrl-t挿入モードでインデントを追加
ctrl-d挿入モードでインデントを削除

挿入

コマンド機能
iカーソル位置からインサートモードに入る
aカーソルの直後からインサートモードに入る
I行頭からインサートモードに入る
A行末からインサートモードに入る

第二文型(M)

基本移動

コマンド機能
hカーソルを左にずらす
jカーソルを下に下げる
kカーソルを上に上げる
lカーソルを右にずらす
gjカーソルを下に下げる(折り返しにも対応している)
gkカーソルを上に上げる(折り返しにも対応している)

基本行移動

コマンド機能
+下の行の先頭へ
-上の行の先頭へ
_-1 行下の最初の非空白文字に移動
ggそのファイルの先頭へ(Goto)
Gそのファイルの末尾へ(Goto)

オブジェクト単位で移動

コマンド機能
(文後方に
)文前方に
{段落後方に
}段落前方に
[[セクション前方に、もしくは1桁目が '}' で始まる次の場所に。
]]セクション後方に、もしくは1桁目が '}' で始まる次の場所に。
[]セクション後方に、もしくは1桁目が '}' で始まる次の場所に。
][セクション前方に、もしくは1桁目が '}' で始まる次の場所に。

行頭行末移動

コマンド機能
0行の先頭へ
^行の先頭へ(正規表現のアンカーと一緒)
$行の末尾へ(正規表現のアンカーと一緒)

単語の単位で移動

コマンド機能
w次の単語の先頭に進む(ワード)
W次の単語(記号では区切られれていない)の先頭に進む
b次の単語の先頭に戻る(バッグ)
B次の単語(記号では区切られれていない)の先頭に戻る
e今の単語の末尾に進む(エンド)
E今の単語(記号では区切られれていない)の末尾に進む
ge前の単語の末尾に戻る(Gotoエンド)
gE前の単語(記号では区切られれていない)の末尾に戻る(Gotoエンド)

行内で検索して移動

コマンド機能
fa次のaまで飛ぶ
Fa前のaまで飛ぶ
ta次のaの手前まで飛ぶ
Ta前のaの次まで飛ぶ
;f, F, t, Tで検索した文字を同方向に繰り返し検索する
,f, F, t, Tで検索した文字を逆方向に繰り返し検索する
%ついになる括弧に移動
/

検索して移動

コマンド機能
/word文字列wordを検索(上から下へ)
?word文字列wordを検索(下から上へ)
*カーソルより下の文字を検索する
#カーソルより上の文字を検索する
n次の候補に
N前の候補に

オペレーター(O)

デリート・カット・ヤンク

コマンド機能
d選択範囲をデリート
c選択範囲をカットして挿入モードに移行する
y選択範囲をヤンク

インデント

コマンド機能
>右にシフトする
>左にシフトする
!外部コマンドを使ってフィルターに通す
=インデント整える

大文字小文字入れ替え

コマンド機能
~大文字/小文字を入れ換える
g~大文字/小文字を入れ換える
gu小文字にする
gU大文字にする

折りたたみ関係

コマンド機能
zi折り畳みの有効無効の切り替え
zf折り畳みを作成する
za折り畳みの開け閉め
zd折り畳みを削除する
zA折り畳みの開け閉め(再帰)
zD折り畳みを削除する(再帰)
zE全ての折り畳みを削除
zR全ての折り畳みを開く
zM全ての折り畳みを閉じる

第三文型(OM)

単語に対する編集コマンド

コマンド機能
ywカーソル下のワードをヤンク
cwカーソルの下のワードをカット
dwカーソル下のワードをデリート

行に対する編集

コマンド機能
d$カーソルから行末までデリート
c$カーソルから行末までカット
y$カーソルから行末までヤンク
dGカーソル行以下をデリート
cGカーソル行以下をカット
yGカーソル行以下をヤンク
ggVG全選択

カッコを閉じる

コマンド機能
f{ zf %{の括弧を閉じる
space選択範囲を開ける

セレクター(S)

コマンド機能
v文字単位で選択
Ctrl-vブロック単位で選択
V行単位で選択

第四文型(SO)

複数行のインデントの操作

コマンド機能
Ctrl-V j =行を矩形選択して、「=」でインデントを揃える

複数行の行頭・行末に同じ文字を挿入する

コマンド機能
Ctrl-v j $ A 文字入力 esc行末同じ文字列を入れる
Ctrl-v I $ A 文字入力 esc行頭同じ文字列を入れる

複数行のある行又は列の文字列を削除・挿入・置換する

コマンド機能
Ctrl-V j d任意の行列を削除する
Ctrl-v j d任意の列を削除する
Ctrl-V j c 文字入力任意の行列を挿入する
Ctrl-v j c 文字入力任意の列を挿入する
Ctrl-v j i 文字入力 esc任意の列に同じ文字列を入れる
Ctrl-v j d 文字入力 esc任意の列に同じ文字列を入れる
Ctrl-V j d 文字入力 esc任意の行を文字列を入れる
Ctrl-v r 文字入力任意の列を置き換えるする
Ctrl-V r 文字入力任意の行列を置き換えるする

複数行削除

コマンド機能
Ctrl-V j I 文字入力 escある列に同じ文字列を入れる

選択範囲を閉じる

コマンド機能
Ctrl-V zf選択範囲を閉じる
space選択範囲を開ける

テキストオブジェクト(T)

テキストオブジェクトのプレフィックス?

コマンド機能
{Operator} a {Text object}対象のオブジェクとのその中身に対してオペーレーターの操作をする(a)
{Operator} i {Text object}対象のオブジェクの中身に対してオペーレーターの操作する(inner)

テキストオブジェクト

コマンド機能
w単語を区切りそうな文字列まで
W非空白文字の連続
[,(,{,<,",`左の記号で囲まれている文字列
bブロック。() 等カーソル位置から直近の囲み文字の範囲(前方一致)
Bblock ブロック。() 等カーソル位置から直近の囲み文字の範囲(後方一致)
tタグ

第五文型(OT)

プレーンテキストの文字の中身消し

コマンド機能
ditカーソルのある行の最初のタグの中身を消す
citカーソルのある行の最初のタグの中身を消して挿入モードへ移行する
diwカーソルのある行の最初の単語の中身を消す
ciwカーソルのある行の最初の単語の中身を消して挿入モードへ移行する
disカーソルのある行の最初のセンテンスの中身を消す
cisカーソルのある行の最初のセンテンスの中身を消して挿入モードへ移行する
dipカーソルのある行の最初のパラグラフの中身を消す
cipカーソルのある行の最初のパラグラフの中身を消して挿入モードへ移行する

プログラミング言語の文字の中身消し

コマンド機能
di"カーソルのある行の最初の"の中身を消す
ci"カーソルのある行の最初の"の中身を消して挿入モードへ移行す
di[カーソルのある行の最初の[の中身を消す
ci[カーソルのある行の最初の[の中身を消して挿入モードへ移行す

同じ文字列をの置換

コマンド機能
* n cw esc n .*で見つかったワード一つ一つを置換する
:/%s/word/word2wordをword2にいっぺんに置換する

その他の第一文型(C)

ファイル移動

コマンド機能
Ctrl-o戻る
Ctrl-t進む

ファイル表示操作

コマンド機能
:e filenamefilenameを現在のウィンドウで開く(:edit)
:sp filenamefilenameを横分割したウィンドウで開く(:split)
:vs filenamefilenameを縦分割して開く(:vsplit)
:sv filenamefilenameを横分割で読み取り専用で開く(:sview)

ファイル保存操作

コマンド機能
:w hoge.txthoge.txtという名前つけて保存
:qウィンドウを閉じる
:wq保存して終了
:q!保存せずウィンドウを閉じる
:qa!保存せず全てのウィンドウを閉じる

ウィンドウ

コマンド機能
Ctrl-w h左のウィンドウへ
Ctrl-w j下のウィンドウへ
Ctrl-w k上のウィンドウへ
Ctrl-w l右のウィンドウへ
Ctrl-w _選択中のウィンドウの最大化
Ctrl-w =ウィンドウを全て同じ大きさに
Ctrl-w +ウィンドウの高さを一行減らす
Ctrl-w -ウィンドウの高さを一行増やす
Ctrl-w <ウィンドウの幅を一文字減らす
Ctrl-w >ウィンドウの幅を一文字減らす

タブ

コマンド機能
gt次のタブへ
gT前のタブへ

貼り付け方法の変更

コマンド機能
:set pasteペーストモードに(オートインデントされない)
:set nopastenoペーストモードに(オートインデントされる)

補完(挿入モードのサブモード)

コマンド機能
Ctrl-xサブモードのプレフィックス
Ctrl-x Ctrl-oOmni補完表示
Ctrl-x Ctrl-n局所キーワード補完(前方)
Ctrl-x Ctrl-p局所キーワード補完(後方)
Ctrl-n次の候補へ(補完表示中)
Ctrl-p前の候補へ(補完表示中)
CTRL-e補完中止

ヘルプ

コマンド機能
:h {command}ヘルプ

References

  • http://vim-jp.org/vimdoc-ja/
  • http://qiita.com/takeharu/items/9d1c3577f8868f7b07b5
  • http://vimdoc.sourceforge.net/htmldoc/scroll.html
  • http://nanasi.jp/articles/howto/editing/blockwise-operation.html
  • http://www.webhtm.net/vim/mode.htm
  • http://qiita.com/satomyumi/items/755cfbb0e97d48280775#cit
  • http://shinespark.hatenablog.com/entry/2015/11/12/070000
  • http://motw.mods.jp/Vim/command.html
  • http://blog.carbonfive.com/2011/10/17/vim-text-objects-the-definitive-guide/
  • http://qiita.com/b4b4r07/items/7fc12842d03e7e46412c
  • http://reddog.s35.xrea.com/wiki/Vim%20%E6%8A%98%E3%82%8A%E7%95%B3%E3%81%BF.html
  • http://daisuzu.hatenablog.com/entry/2015/12/05/002129

Emacs文法

  • ctrl a: 先頭へ
  • ctrl e: 末尾へ
  • ctrl k: カーソルから行末まで削除
  • ctrl u: 全文字消し
  • ctrl b: 一文字戻る
  • ctrl f: 一文字進む

Vim vs. Emacs

binding用途
Vim複数行のテキスト編集ファイル編集
Emacs単数行のテキスト編集ブラウザの検索バーのテキスト編集

Code

Rangerコマンド

Movement is same as Vim.

File Operations

ShortcutDesc
cwrename current file
ddcut
drreset cut
yyyank
yrreset yank
/search
dDdelete
pppaste

File Path Operations

NOTE: need to instal xsel

ShortcutDesc
ypyank file path name
ynyank file name
ydyank directory name

File Selection Operation

ShortcutDesc
spaceselect file
vselect all
Vrectangular select
uvdeselection

Commands

ShortcutDesc
:Execute Range Command
SLaunch sub sheell in current directory
!Execute Shell Command
dudisk usage
chmodchange permissions

Tabs

ShortcutDesc
C-ncreate new tab
gncreate new tab
C-wclose current tab
gt or tabnext tab
gT or shift+tabprevious tab
alt+[n]goto [n]th tab
~divide screen by 2 tabs
uqreopen recent colosed tab

Sort

Shortcut (normal/reverse order)Desc
ob / oBbasename (file name)
oe / oEextension (extension name)
ot / oTtype
oa / oAatime
oc / oCctime
om / oMmtime
os / oSsize
on / oNnatural (directory entry)

Edition

ShortcutDesc
ilaunch pager
wtask view

archインストールメモ

arch liveのusbメモリからThinkpad x1 carbon 6genにarchをインスコした時の備忘録(UEFIブート)。なお、winは消す

live USBメディアの作成

公式サイト( https://www.archlinux.org/download/ )からISOのDL 焼くのめんどくさいときはEtcherを使う https://www.balena.io/etcher/

ISOのチェックサム

$ gpg --keyserver pgp.mit.edu --keyserver-options auto-key-retrieve --verify archlinux-2019.01.01-x86_64.iso.sig
gpg: assuming signed data in 'archlinux-2019.01.01-x86_64.iso'
gpg: Signature made Wed 02 Jan 2019 12:23:53 AM JST
gpg:                using RSA key 4AA4767BBC9C4B1D18AE28B77F2D434B9741E8AC
gpg: requesting key 7F2D434B9741E8AC from hkp server pgp.mit.edu
\gpg: key 7F2D434B9741E8AC: 31 signatures not checked due to missing keys
gpg: key 7F2D434B9741E8AC: public key "Pierre Schmitz <pierre@archlinux.de>" imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg:               imported: 1
gpg: Good signature from "Pierre Schmitz <pierre@archlinux.de>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 4AA4 767B BC9C 4B1D 18AE  28B7 7F2D 434B 9741 E8AC

デバイスの確認(sdb1が今回のターゲット) マウントされていた場合はアンマウントする

$ lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
loop0         7:0    0    13M  1 loop /snap/gnome-characters/124
loop1         7:1    0  14.5M  1 loop /snap/gnome-logs/45
loop2         7:2    0  15.1M  1 loop /snap/aws-cli/135
loop3         7:3    0    13M  1 loop /snap/gnome-characters/139
loop4         7:4    0  42.1M  1 loop /snap/gtk-common-themes/701
loop5         7:5    0  87.9M  1 loop /snap/core/5662
loop6         7:6    0   2.3M  1 loop /snap/gnome-calculator/238
loop7         7:7    0 147.3M  1 loop /snap/skype/66
loop8         7:8    0   2.3M  1 loop /snap/gnome-calculator/260
loop9         7:9    0  34.6M  1 loop /snap/gtk-common-themes/818
loop10        7:10   0  89.5M  1 loop /snap/core/6130
loop11        7:11   0 140.7M  1 loop /snap/gnome-3-26-1604/74
loop12        7:12   0   3.7M  1 loop /snap/gnome-system-monitor/57
loop13        7:13   0 140.9M  1 loop /snap/gnome-3-26-1604/70
sdb           8:16   1   7.5G  0 disk
├─sdb1        8:17   1   1.8G  0 part /media/mike/Ubuntu 18.04.1 LTS amd64
└─sdb2        8:18   1   2.3M  0 part
nvme0n1     259:0    0   477G  0 disk
├─nvme0n1p1 259:1    0   512M  0 part /boot/efi
└─nvme0n1p2 259:2    0 476.4G  0 part /

dev/sdb1 をアンマウントする

$ umount /dev/sdb
$ lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
loop0         7:0    0    13M  1 loop /snap/gnome-characters/124
loop1         7:1    0  14.5M  1 loop /snap/gnome-logs/45
loop2         7:2    0  15.1M  1 loop /snap/aws-cli/135
loop3         7:3    0    13M  1 loop /snap/gnome-characters/139
loop4         7:4    0  42.1M  1 loop /snap/gtk-common-themes/701
loop5         7:5    0  87.9M  1 loop /snap/core/5662
loop6         7:6    0   2.3M  1 loop /snap/gnome-calculator/238
loop7         7:7    0 147.3M  1 loop /snap/skype/66
loop8         7:8    0   2.3M  1 loop /snap/gnome-calculator/260
loop9         7:9    0  34.6M  1 loop /snap/gtk-common-themes/818
loop10        7:10   0  89.5M  1 loop /snap/core/6130
loop11        7:11   0 140.7M  1 loop /snap/gnome-3-26-1604/74
loop12        7:12   0   3.7M  1 loop /snap/gnome-system-monitor/57
loop13        7:13   0 140.9M  1 loop /snap/gnome-3-26-1604/70
sdb           8:16   1   7.5G  0 disk
├─sdb1        8:17   1   1.8G  0 part
└─sdb2        8:18   1   2.3M  0 part
nvme0n1     259:0    0   477G  0 disk
├─nvme0n1p1 259:1    0   512M  0 part /boot/efi
└─nvme0n1p2 259:2    0 476.4G  0 part /

ISOを書き込む

$ sudo dd bs=4M if=archlinux-2019.01.01-x86_64.iso of=/dev/sdb status=progress && sync                                                        
[sudo] password for mike:
150+1 records in
150+1 records out
631242752 bytes (631 MB, 602 MiB) copied, 105.399 s, 6.0 MB/s

BIOSの設定

  • セキュアブートをオフにする
    Security > Secure boot > Secure boot > Disabled
  • USBメモリの起動優先順位を変更する

そしてLive USBから起動する。

Archのインスコ

ミラーサーバーの国の優先順位を変更 日本とアメリカだと10倍ぐらい速度の差があった

# vim /etc/pacman.d/mirrorlist # 日本を最上位に移動する
# head /etc/pacman.d/mirrorlist
...
# Japan
# pacman -Syu # Wifiの設定後でもOK

WiFiの設定

まずインターフェイスの確認 wから始まっているのが往々にして無線のネットワークインターフェイス

# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp0s31f6: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether e8:6a:64:86:78:38 brd ff:ff:ff:ff:ff:ff
3: wlp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DORMANT group default qlen 1000
    link/ether 20:79:18:d2:ca:1c brd ff:ff:ff:ff:ff:ff

wlp2s0が対象のI/F ore_oreという名前(任意)のプロファイルを作る

# cp /etc/netctl/examples/wireless-wpa /etc/netctl/ore_ore
# cat /etc/netctl/ore_ore
Description='A simple WPA encrypted wireless connection'
Interface=wlan0
Connection=wireless

Security=wpa
IP=dhcp

ESSID='MyNetwork'
# Prepend hexadecimal keys with \"
# If your key starts with ", write it as '""<key>"'
# See also: the section on special quoting rules in netctl.profile(5)
Key='WirelessKey'
# Uncomment this if your ssid is hidden
#Hidden=yes
# Set a priority for automatic profile selection
#Priority=10

ore_ore プロファイルを修正する 変更するのは次の3点

  1. Interface: WifiのI/F(この場合はwlp2s0)
  2. ESSID: wifiのSSID
  3. Key: WifiのPW
# vi /etc/netctl/ore_ore # ゴニョゴニョ
# cat /etc/netctl/ore_ore
Description='A simple WPA encrypted wireless connection'
Interface=wlp2s0
Connection=wireless

Security=wpa
IP=dhcp

ESSID='XXX'
# Prepend hexadecimal keys with \"
# If your key starts with ", write it as '""<key>"'
# See also: the section on special quoting rules in netctl.profile(5)
Key='XXX'
# Uncomment this if your ssid is hidden
#Hidden=yes
# Set a priority for automatic profile selection
#Priority=10

Wifiに接続する pingが通れば成功

# netctl start ore_ore # 数秒かかる
# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=121 time=8.90 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=121 time=10.1 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=121 time=10.4 ms
...

パーテーションの設定

(U)EFIかどうか確認 ディレクトリが存在すればOK

# ls /sys/firmware/efi/
config_table  efivars  esrt  fw_platform_size  fw_vendor  runtime  runtime-map  systab

ドライブを探す ThinkPad X1 carbonはPCIe SSDなのでインターフェイスの名前はnvme0n1で、後ろにp1のようにパーテーション番号がつく。

$ lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
loop0         7:0    0    13M  1 loop /snap/gnome-characters/124
loop1         7:1    0  14.5M  1 loop /snap/gnome-logs/45
loop2         7:2    0  15.1M  1 loop /snap/aws-cli/135
loop3         7:3    0    13M  1 loop /snap/gnome-characters/139
loop4         7:4    0  42.1M  1 loop /snap/gtk-common-themes/701
loop5         7:5    0  87.9M  1 loop /snap/core/5662
loop6         7:6    0   2.3M  1 loop /snap/gnome-calculator/238
loop7         7:7    0 147.3M  1 loop /snap/skype/66
loop8         7:8    0   2.3M  1 loop /snap/gnome-calculator/260
loop9         7:9    0  34.6M  1 loop /snap/gtk-common-themes/818
loop10        7:10   0  89.5M  1 loop /snap/core/6130
loop11        7:11   0 140.7M  1 loop /snap/gnome-3-26-1604/74
loop12        7:12   0   3.7M  1 loop /snap/gnome-system-monitor/57
loop13        7:13   0 140.9M  1 loop /snap/gnome-3-26-1604/70
sdb           8:16   1   7.5G  0 disk
├─sdb1        8:17   1   1.8G  0 part /media/mike/Ubuntu 18.04.1 LTS amd64
└─sdb2        8:18   1   2.3M  0 part
nvme0n1     259:0    0   477G  0 disk
├─nvme0n1p1 259:1    0   512M  0 part /boot/efi
└─nvme0n1p2 259:2    0 476.4G  0 part /

UEFIブートなので、GPTパーテーションを作る 下のような感じで書き換える

EF00はEFIパーテーションHEX 8E00は linux LVM (logical volume manager) のHEX なお、空欄ではEnterキーを押している

$ gdisk /dev/nvme0n1
GPT fdisk (gdisk) version 1.0.4

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.

Command (? for help): o
This option deletes all partitions and creates a new protective MBR.
Proceed? (Y/N): y

Command (? for help): n
Partition number (1-128, default 1):  
First sector (34-1000215182, default = 2048) or {+-}size{KMGTP}: 
Last sector (2048-1000215182, default = 1000215182) or {+-}size{KMGTP}: +512MB
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): EF00
Changed type of partition to 'EFI System'

Command (? for help): n
Partition number (2-128, default 2): 
First sector (34-1000215182, default = 1050624) or {+-}size{KMGTP}: 
Last sector (1050624-1000215182, default = 1000215182) or {+-}size{KMGTP}: 
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): 8E00
Changed type of partition to 'Linux LVM'

Command (? for help): w
# 最後のコマンドはy、全部書き換える

パーテーションの確認

$ fdisk -l /dev/nvme0n1
Disk /dev/nvme0n1: 477 GiB, 512110190592 bytes, 1000215216 sectors
Disk model: LENSE30512GMSP34MEAT3TA                 
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 07E88104-29C7-41AE-91AD-379E474EA1C7

Device           Start        End   Sectors   Size Type
/dev/nvme0n1p1    2048    1050623   1048576   512M EFI System
/dev/nvme0n1p2 1050624 1000215182 999164559 476.4G Linux LVM

LVMパーテーションの暗号化

LVMパーテーションの暗号化する 暗号はデフォのLUKSを使用する パスフレーズは覚えておく

# cryptsetup luksFormat /dev/nvme0n1p2 # ※p1ではない

LVMの中に論理ボリュームを作成する

まずは、LVMを復号化して開く main_partは任意のデバイスマッパーネームをつける

# cryptsetup open --type luks /dev/nmve0n1p2 main_part

LVMの中に物理ボリューム(PV)を作成

# pvcreate /dev/mapper/main_part

PVの確認

# pvscan 
  PV /dev/mapper/cryptlvm   VG main_group      lvm2 [476.43 GiB / 0    free]
  Total: 1 [476.43 GiB] / in use: 1 [476.43 GiB] / in no VG: 0 [0   ]
# pvdisplay
  --- Physical volume ---
  PV Name               /dev/mapper/cryptlvm
  VG Name               main_group
  PV Size               <476.44 GiB / not usable <3.32 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              121967
  Free PE               0
  Allocated PE          121967
  PV UUID               D9rfJy-SqUn-I6Ca-PzzO-eb79-E61t-fHkwmu

ボリュームグループ(VG)を作成 main_group はVG名 (任意)

vgcreate main_group /dev/mapper/main_part

VGの確認

# vgscan
  Reading volume groups from cache.
  Found volume group "main_group" using metadata type lvm2
# vgdisplay
  --- Volume group ---
  VG Name               main_group
  System ID             
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  4
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                3
  Open LV               3
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               476.43 GiB
  PE Size               4.00 MiB
  Total PE              121967
  Alloc PE / Size       121967 / 476.43 GiB
  Free  PE / Size       0 / 0   
  VG UUID               LiXnT1-xe6V-dmpZ-r7fs-HZF4-14wT-VrFTy5

論理ボリュームを(LV)作成 swapはメモリの半分(8GB)割り当てる rootは64GB割り当てる homeは残り全部

lvcreate -L8G main_group -n swap
lvcreate -L64G main_group -n root
lvcreate -l 100%FREE main_group -n home

LVの確認

# lvscan
  ACTIVE            '/dev/main_group/swap' [8.00 GiB] inherit
  ACTIVE            '/dev/main_group/root' [64.00 GiB] inherit
  ACTIVE            '/dev/main_group/home' [404.43 GiB] inherit
# lvdisplay
  --- Logical volume ---
  LV Path                /dev/main_group/swap
  LV Name                swap
  VG Name                main_group
  LV UUID                79nm1Z-BCbW-Rhra-tryB-7lR9-XsCv-1jHiQD
  LV Write Access        read/write
  LV Creation host, time archiso, 2019-01-22 13:14:18 +0000
  LV Status              available
  # open                 2
  LV Size                8.00 GiB
  Current LE             2048
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           254:1
   
  --- Logical volume ---
  LV Path                /dev/main_group/root
  LV Name                root
  VG Name                main_group
  LV UUID                FqcEYQ-0cUp-BMul-VxND-42Es-BHsE-Yj4zdB
  LV Write Access        read/write
  LV Creation host, time archiso, 2019-01-22 13:14:50 +0000
  LV Status              available
  # open                 1
  LV Size                64.00 GiB
  Current LE             16384
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           254:2
   
  --- Logical volume ---
  LV Path                /dev/main_group/home
  LV Name                home
  VG Name                main_group
  LV UUID                VlSY7x-8Q0O-UFQL-rnQT-05xp-inTH-QLCieR
  LV Write Access        read/write
  LV Creation host, time archiso, 2019-01-22 13:15:09 +0000
  LV Status              available
  # open                 1
  LV Size                404.43 GiB
  Current LE             103535
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           254:3
  --- Logical volume ---
  LV Path                /dev/main_group/swap
  LV Name                swap
  VG Name                main_group
  LV UUID                79nm1Z-BCbW-Rhra-tryB-7lR9-XsCv-1jHiQD
  LV Write Access        read/write
  LV Creation host, time archiso, 2019-01-22 13:14:18 +0000
  LV Status              available
  # open                 2
  LV Size                8.00 GiB
  Current LE             2048
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           254:1
   
  --- Logical volume ---
  LV Path                /dev/main_group/root
  LV Name                root
  VG Name                main_group
  LV UUID                FqcEYQ-0cUp-BMul-VxND-42Es-BHsE-Yj4zdB
  LV Write Access        read/write
  LV Creation host, time archiso, 2019-01-22 13:14:50 +0000
  LV Status              available
  # open                 1
  LV Size                64.00 GiB
  Current LE             16384
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           254:2
   
  --- Logical volume ---
  LV Path                /dev/main_group/home
  LV Name                home
  VG Name                main_group
  LV UUID                VlSY7x-8Q0O-UFQL-rnQT-05xp-inTH-QLCieR
  LV Write Access        read/write
  LV Creation host, time archiso, 2019-01-22 13:15:09 +0000
  LV Status              available
  # open                 1
  LV Size                404.43 GiB
  Current LE             103535
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           254:3

フォーマットとマウント

LVをフォーマットする マッピングされているので、次のような名前になる /dev/mapper/VG名-LV名

# mkfs.ext4 /dev/mapper/main_group-root
# mkfs.ext4 /dev/mapper/main_group-home

スワップも

# mkswap /dev/mapper/main_group-swap

LVをマウントする /mnt/にマウントする

# mount /dev/mapper/main_group-root /mnt/
# mkdir /mnt/home
# mount /dev/mapper/main_group-home /mnt/home
# swapon /dev/mapper/main_group-swap

ブートローダーをマウントする

# mkdir /mnt/boot/
# mount /dev/nvme0n1p1 /mnt/boot

設定し終えるとブロックデバイスはこんな感じ

# lsblk
NAME                  MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
nvme0n1               259:0    0   477G  0 disk  
├─nvme0n1p1           259:1    0   512M  0 part  /boot
└─nvme0n1p2           259:2    0 476.4G  0 part  
  └─cryptlvm          254:0    0 476.4G  0 crypt 
    ├─main_group-swap 254:1    0     8G  0 lvm   [SWAP]
    ├─main_group-root 254:2    0    64G  0 lvm   /
    └─main_group-home 254:3    0 404.4G  0 lvm   /home

Archのインスコ

baseとbase-develをインスコする https://www.archlinux.jp/groups/x86_64/base/ https://www.archlinux.jp/groups/x86_64/base-devel/ このpacstrapコマンドでboot以外のフォルダも作られる

# pacstrap /mnt/ base base-devel 

マウントの設定ファイルを修正 システム起動時に自動的にマウントするため

# genfstab -p /mnt >> /mnt/etc/fstab

Archのインスコ (中で作業)

チェンジルートする

# arch-chroot /mnt

32bitのインテルのドライバーを入れるため Miltilibを有効化。下の2行をコメントアウトする

# vi etc/pacman.conf
[multilib]
Include = /etc/pacman.d/mirrorlist

インテルのマイクロコードをインスコ

# pacman -Sy intel-ucode

マイクロコードを確認 (のちのち再起動後確認できる)

# dmesg | grep microcode
[    1.703624] microcode: sig=0x806ea, pf=0x80, revision=0x9a
[    1.703917] microcode: Microcode Update Driver: v2.2.

Linuxカーネルのコピーをインスコ

# pacman -S linux-headers linux-lts linux-lts-headers

initrdの設定

mkinitcpioはinitrd(initramfs)のイメージを作るためのスクリプト 下の様に修正する

# vi /etc/mkinitcpio.conf
HOOKS=(base udev autodetect keyboard keymap modconf block encrypt lvm2 filesystems fsck)

initramfsを生成する

# mkinitcpio -p linux
# mkinitcpio -p linux-lts # linux-lts をインスコした場合は

ブートローダーの設定

ローダーを作る GRUBを使わずsystemd-bootを使用する

bootctl --path=/boot/ install

ローダーの設定をする 下のように編集する

# vi /boot/loader/loader.conf
default arch
timeout 3
editor 0 

arch.confを作成する arch.confのXXXの伏せ字をblkidのコマンドのUUIDのIDの結果で埋める PARTUUIDではないので注意する、またクォーテーションは含めない vi だったらコマンドで (:r !blkid) で結果を読み込める

# blkid
/dev/nvme0n1p2: UUID="XXX" TYPE="crypto_LUKS" PARTLABEL="Linux LVM" PARTUUID="XXX2"
# vi /boot/loader/entries/arch.conf
title Arch Linux
linux /vmlinuz-linux
initrd /intel-ucode.img # intel マイクロコードを読み込む
initrd /initramfs-linux.img # mkinitcpioで作成したimgを読み込む
options cryptdevice=UUID=XXX:cryptlvm root=/dev/mapper/main_group-root quiet rw

起動

# umount -R /mnt
# shutdown -r now
# # ~起動後~
# # rootでログインできればOK

再起動後のArchの設定

WiFi

live USBと同じ

ミラーリスト

ミラーリストで日本の優先度を一番にする

# vi /etc/pacman.d/mirrorlist

言語

localeの設定

# vi /etc/locale.gen
en_US.UTF-8 UTF8 # ←をアンコメントアウト
# localectl set-locale LANG=”en_US.UTF-8”

時間

time zone を日本に設定

tzselect
Please identify a location so that time zone rules can be set correctly.
Please select a continent, ocean, "coord", or "TZ".
1) Africa                                                            7) Europe
2) Americas                                                          8) Indian Ocean
3) Antarctica                                                        9) Pacific Ocean
4) Asia                                                             10) coord - I want to use geographical coordinates.
5) Atlantic Ocean                                                   11) TZ - I want to specify the timezone using the Posix TZ format.
6) Australia
#? 4
Please select a country whose clocks agree with yours.
1) Afghanistan             9) China                 17) Iraq                  25) Kyrgyzstan            33) Oman                  41) Sri Lanka             49) Vietnam
2) Armenia                10) Cyprus                18) Israel                26) Laos                  34) Pakistan              42) Syria                 50) Yemen
3) Azerbaijan             11) East Timor            19) Japan                 27) Lebanon               35) Palestine             43) Taiwan
4) Bahrain                12) Georgia               20) Jordan                28) Macau                 36) Philippines           44) Tajikistan
5) Bangladesh             13) Hong Kong             21) Kazakhstan            29) Malaysia              37) Qatar                 45) Thailand
6) Bhutan                 14) India                 22) Korea (North)         30) Mongolia              38) Russia                46) Turkmenistan
7) Brunei                 15) Indonesia             23) Korea (South)         31) Myanmar (Burma)       39) Saudi Arabia          47) United Arab Emirates
8) Cambodia               16) Iran                  24) Kuwait                32) Nepal                 40) Singapore             48) Uzbekistan
#? 19

The following information has been given:

        Japan

Therefore TZ='Asia/Tokyo' will be used.
Selected time is now:   Sat Feb  9 16:34:35 JST 2019.
Universal Time is now:  Sat Feb  9 07:34:35 UTC 2019.
Is the above information OK?
1) Yes
2) No
#? 1

You can make this change permanent for yourself by appending the line
        TZ='Asia/Tokyo'; export TZ
to the file '.profile' in your home directory; then log out and log in again.

Here is that TZ value again, this time on standard output so that you
can use the /usr/bin/tzselect command in shell scripts:
Asia/Tokyo

ハードウェアクロックの時間のズレを調整

# hwclock --systohc --utc

hostname

host名の追加

echo archer > /etc/hostname

Pacman

pacman.confにColorILoveCandyを追加 プログレスバーがpacmanに変わる

# vi/etc/pacman.conf
# Misc options
#UseSyslog
Color
#TotalDownload
CheckSpace
#VerbosePkgLists
ILoveCandy

ユーザーの追加

rootのPW変更

# passwd

Sudoerの設定 wheelグループはどんなコマンドも許可

# pacman -S sudo
# visudo # 下の2行のコメントを外す

## Uncomment to allow members of group wheel to execute any command
# wheel ALL=(ALL) ALL

一般ユーザー追加

# useradd -m -G wheel -s /bin/bash mike
# passwd mike
# reboot # 一応mikeユーザーでログインできることを確認する

一応仮想コンソール用ユーザーも追加する mikeはGUI用のユーザーでnekoはCUI用 万が一mikeで問題が発生した時用に

# useradd -m -G wheel -s /bin/bash neko
# passwd neko

ルートユーザーでログインすることを無効化する

$ sudo passwd -l root

Yayのインスコ

$ sudo pacman -S git
$ sudo pacman -S make fakeroot # NOTE: これが依存PKG
$ git clone https://aur.archlinux.org/yay.git
$ cd yay
$ makepkg -si

Virtual Console

keymap

capslockをctrl化する https://wiki.archlinux.jp/index.php/%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E3%81%A7%E3%81%AE%E7%89%B9%E5%88%A5%E3%81%AA%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E3%82%AD%E3%83%BC もとのキーマップをコピーして新しい設定を作る

# mkdir -p /usr/local/share/kbd/keymaps
# cp /usr/share/kbd/keymaps/i386/qwerty/us.map.gz /usr/local/share/kbd/keymaps/
# gunzip /usr/local/share/kbd/keymaps/us.map.gz

capslockをctrlに変更

# vi /usr/local/share/kbd/keymaps/us.map
...
keycode 58 = Control

読み込み

# loadkeys /usr/local/share/kbd/keymaps/us.map

起動時に読み込みにする場合 下を追記する

# vi /etc/vconsole.conf
...
KEYMAP=/usr/local/share/kbd/keymaps/us.map

X

タッチパッドのドライバー

libinputをインスコする

$ pacman -S xf86-input-libinput

Install

インテルドライバーのインスコ

# pacman -S xf86-video-intel lib32-intel-dri lib32-mesa lib32-libgl

Xのインスコ

# pacman -S xorg-server xorg-xinit xorg-apps mesa xterm

Xが起動するか確認

# startx 

Font

元ネタ https://www.reddit.com/r/archlinux/comments/5r5ep8/make_your_arch_fonts_beautiful_easily/

フォントインスコ

$ sudo pacman -S ttf-dejavu ttf-liberation noto-fonts

プリセットの作成

$ sudo ln -s /etc/fonts/conf.avail/70-no-bitmaps.conf /etc/fonts/conf.d
$ sudo ln -s /etc/fonts/conf.avail/10-sub-pixel-rgb.conf /etc/fonts/conf.d
$ sudo ln -s /etc/fonts/conf.avail/11-lcdfilter-default.conf /etc/fonts/conf.d

/etc/fonts/local.confに下のように設定フィアルを作成する 再起動するとフォントがきれいになっている

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
    <match>
        <edit mode="prepend" name="family"><string>Noto Sans</string></edit>
    </match>
    <match target="pattern">
        <test qual="any" name="family"><string>serif</string></test>
        <edit name="family" mode="assign" binding="same"><string>Noto Serif</string></edit>
    </match>
    <match target="pattern">
        <test qual="any" name="family"><string>sans-serif</string></test>
        <edit name="family" mode="assign" binding="same"><string>Noto Sans</string></edit>
    </match>
    <match target="pattern">
        <test qual="any" name="family"><string>monospace</string></test>
        <edit name="family" mode="assign" binding="same"><string>Noto Mono</string></edit>
    </match>
</fontconfig>
    

IME

日本語フォントをインスコする

$ pacman -S otf-ipafont

Fcitxをインスコする

$ pacman -S fcitx fcitx-mozc fcitx-configtool

下のように.xinitrcを作成する

$ cat .xinitrc 
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS=”@im=fcitx” 

Fcitx configurationで下のように設定して、 再起動するとIMEが使えるようになる

add mozc and prioritize it more over Keyboard English
change default keyboard layout to to English(US)
Global config > show advance options
    active input method = lart
    inactive input method = ralt

ファンクションキー

Fnキーの挙動をインバートするにはFn+Escを押下すればOK 参考 https://bbs.archlinux.org/viewtopic.php?id=233368

Keymap

capslockを無効化する ログイン中かえたいなら setxkbmap -option ctrl:nocaps でもOK 恒久的に変えたいので、X configuration fileを修正する /etc/X11/xorg.confを変更せず、自分で設定ファイルを追加する xorg.confはHWを変更すると壊れやすいため なお、ファイルの頭の数字は2桁で読み込み順番に関係する 再起動すればXで反映されている

# vi /etc/X11/xorg.conf.d/20-keyboard-layout.conf
Section "InputClass"
    Identifier       "keyboard_layout"
    MatchIsKeyboard  "on"
    Option           "XkbLayout"  "us"
    Option           "XkbOptions" "ctrl:nocaps"
EndSection

Thinkpad X1 carbon 6gen用の設定

休止状態の設定

もう一度 mkinitcpio.confを編集してresume を追加する

# vi /etc/mkinitcpio.conf
HOOKS=(base udev autodetect keyboard keymap modconf block encrypt lvm2 resume filesystems fsck)

initramfsのイメージを生成する

mkinitcpio -p linux
# mkinitcpio -p linux-lts

arch.confを以下のように修正する。 resume=/dev/mapper/main_group-swap の設定を追加する

title Arch Linux
linux /vmlinuz-linux
initrd /intel-ucode.img
initrd /initramfs-linux.img
options cryptdevice=UUID=XXX:cryptlvm root=/dev/mapper/main_group-root resume=/dev/mapper/main_group-swap quiet rw

サスペンドの設定

サポートされているサスペンドの設定の確認

# dmesg | grep -i "acpi: (supports"
[    0.979007] ACPI: (supports S0 S4 S5)

再起動しBIOSからSleep StateをLinuxに変更する Config > Power > Sleep State > Linux

Sleep StateをLinuxに変更後 S3が追加されている

# dmesg | grep -i "acpi: (supports"
[    1.053591] ACPI: (supports S0 S3 S4 S5)

CPUのクロックスロットリングの問題

パッチを当てる CPUのクロック数がおかしいときがあるため

# aurman -S lenovo-throttling-fix-git
# sudo systemctl enable --now lenovo_fix.service

BIOS更新

現状のバージョン確認 最近買ったので最新だった

https://pcsupport.lenovo.com/us/zh/products/laptops-and-netbooks/thinkpad-x-series-laptops/thinkpad-x1-carbon-6th-gen-type-20kh-20kg/downloads/ds502281

# dmidecode -s bios-version
N23ET59W (1.34 )

もし、上げる場合は、ファームウェアを更新する fwupdをインスコする

# pacman -S fwupd

Laptopが電源につなぐ。 BIOSのバージョンあげるのは自己責任で

# fwpudmgr refresh 
# fwpudmgr get-updates
# fwupdmgr update

Trim SSD

SSDのTRIMとはHDDでいうデフラグ的なもの できるか確認。SSDの1行目か2行目に0でない値があれば可能

# lsblk --discard
NAME                  DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO
nvme0n1                      0      512B       2T         0
├─nvme0n1p1                  0      512B       2T         0
└─nvme0n1p2                  0      512B       2T         0
  └─cryptlvm                 0        0B       0B         0
    ├─main_group-swap        0        0B       0B         0
    ├─main_group-root        0        0B       0B         0
    └─main_group-home        0        0B       0B         0

定期的なトリミングを有効化する Ubuntuでもしていないらしいので、する必要もないのかもしれない?

# pacman -S utils-linux
# systemctl enable fstrim.timer

その他

pacmanのメモ

# pacman -S <word> # パッケージインスコ
# pacman -R <word> # パッケージ削除
# pacman -Syy # パッケージリストの更新 (`apt update`)
# pacman -Syyu # パッケージリストの更新とパッケージ更新
# pacman -Ss <word> # wordでパッケージを検索する
# pacman -Qs <word> # wordでローカルでローカルのパッケージを検索する
# pacman -Qsi <word> # Qsの詳細
# pacman -Ql # ローカルのパッケージ一覧
# pacman -Syu # パッケージのアップグレード

用語

  • LVM (Logicl Volume Manager) はブロックデバイスを仮想化する機能。
    • PV(物理ボリューム): ようするにハードディスクそのもの
    • VG(ボリュームグループ): ようするにRAIDでいうJBOD(スパニング)
    • LV(論理グループ): ようするにパーテーション
  • ループデバイスは通常のファイルをブロックデバイスとして読み書きできるようにする機能

References

  • https://github.com/ejmg/an-idiots-guide-to-installing-arch-on-a-lenovo-carbon-x1-gen-6#installing-arch-and-setting-it-up-to-boot-and-run
  • https://wiki.archlinux.jp/index.php/%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%82%AC%E3%82%A4%E3%83%89
  • https://wiki.archlinux.jp/index.php/USB_%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%83%A1%E3%83%87%E3%82%A3%E3%82%A2#BIOS.E3.83.BBUEFI_.E3.83.96.E3.83.BC.E3.82.BF.E3.83.96.E3.83.AB_USB
  • https://unix.stackexchange.com/questions/89609/arch-linux-live-usb-no-longer-booting-uefi
  • https://wiki.archlinux.jp/index.php/Lenovo_ThinkPad_X1_Carbon
  • https://blog.amedama.jp/entry/2015/09/24/142537
  • https://piro791.blog.so-net.ne.jp/2008-11-04
  • https://qiita.com/MoriokaReimen/items/dbe1448ce6c0f80a6ac1
  • https://qiita.com/eup42/items/ea927f83e52f8d504427
  • http://lfsbookja.osdn.jp/7.10-systemd/chapter07/console.html
  • https://bbs.archlinux.org/viewtopic.php?id=234539
  • https://lambdalisue.hatenablog.com/entry/2013/09/27/212118

その他

openしたLVMをクローズする

# cryptsetup close /dev/mapper/main_part

write error failed: No space left on device のエラーが出た時

きれいに

# lsblk
# fdisk /dev/nvme0n1 # 全部のパーテーション消すまで繰り返す
d # delete a partition
w
y
# mkfs -t /dev/nvme0n1 # フォーマット

また作りなおす

# partition bootableは上述の処理と同じ
# 次はカラのパーテーションを作る

ref

  • https://qiita.com/mgoldchild/items/e369ca8054abf213eeeb

Manjaroのセットアップ

Manjaro setup after installation

firstly, update mirrorlist

$ sudo pacman-mirrors -f5

update packages and libraries

$ sudo pacman -Syu # or -Syuu

Install base-devel

for prevending err of Can not find strip binary after i did makepkg -si for yay

$ sudo pacman -S base-devel

Install yay

$ git clone https://aur.archlinux.org/yay.git
$ cd yay
$ makepkg -si

Install Google Chrome

in order to use 1password

$ yay -S --no--confirm google-chrome

register github

$ mkdir ~/.ssh/
$ cd ~/.ssh/ 
$ ssh-keygen -t rsa
$ vim ~/.ssh/config
# github
Host github
    HostName            github.com
    IdentityFile        ~/.ssh/id_rsa
$ sudo chmod -R 700 ~/.ssh/ 
$ sudo chmod 600 ~/.ssh/id_rsa
$ cat ~/.ssh/id_rsa.pub
$ ssh -T git@github # test!

clone dotfiles

$ git clone git@github.com:mgoldchild/dotfiles.git

VIM with clipboard

$ sudo pacman -S gvim

Update GRUB_TIMEOUT

$ sudo vim /etc/default/grub
[sudo] password for mike:
GRUB_DEFAULT=saved
GRUB_TIMEOUT=5  # <==== change to 1
GRUB_TIMEOUT_STYLE=menu
GRUB_DISTRIBUTOR='Manjaro'
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
GRUB_CMDLINE_LINUX=""
$ sudo update-grub
$ reboot

Enable SSD Trim

$ sudo systemctl enable fstrim.timer

Check for errors

$ sudo systemctl --failed
  UNIT                         LOAD   ACTIVE SUB    DESCRIPTION
  ● systemd-modules-load.service loaded failed failed Load Kernel Modules

  LOAD   = Reflects whether the unit definition was properly loaded.
  ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
  SUB    = The low-level unit activation state, values depend on unit type.

  1 loaded units listed. Pass --all to see loaded but inactive units, too.
  To show all installed unit files use 'systemctl list-unit-files'.

$ sudo journalctl -p 3 -xb
-- Logs begin at Thu 2019-06-06 02:40:18 JST, end at Fri 2019-06-07 20:44:34 JST. --
Jun 07 10:18:38 mike-pc systemd-modules-load[226]: Failed to find module 'vboxdrv'
Jun 07 10:18:38 mike-pc systemd-modules-load[226]: Failed to find module 'vboxnetadp'
Jun 07 10:18:38 mike-pc systemd-modules-load[226]: Failed to find module 'vboxnetflt'
Jun 07 10:18:38 mike-pc systemd-modules-load[226]: Failed to find module 'vboxpci'
Jun 07 10:18:38 mike-pc systemd-modules-load[401]: Failed to find module 'vboxdrv'
Jun 07 10:18:38 mike-pc systemd-modules-load[401]: Failed to find module 'vboxnetadp'
Jun 07 10:18:38 mike-pc systemd-modules-load[401]: Failed to find module 'vboxnetflt'
Jun 07 10:18:38 mike-pc systemd-modules-load[401]: Failed to find module 'vboxpci'
Jun 07 10:18:38 mike-pc systemd[1]: Failed to start Load Kernel Modules.
-- Subject: A start job for unit systemd-modules-load.service has failed
-- Defined-By: systemd
-- Support: https://forum.manjaro.org/c/technical-issues-and-assistan
...

investigate service

$ sudo journalctl -u systemd-modules-load.service
Jun 06 23:24:49 mike-pc systemd[1]: Starting Load Kernel Modules...
Jun 06 23:24:49 mike-pc systemd-modules-load[427]: Failed to find module 'vboxdrv'
Jun 06 23:24:49 mike-pc systemd-modules-load[427]: Failed to find module 'vboxnetadp'
Jun 06 23:24:49 mike-pc systemd-modules-load[427]: Failed to find module 'vboxnetflt'
Jun 06 23:24:49 mike-pc systemd-modules-load[427]: Failed to find module 'vboxpci'
Jun 06 23:24:49 mike-pc systemd[1]: systemd-modules-load.service: Main process exited, code=exited, status=1/FAILU>
Jun 06 23:24:49 mike-pc systemd[1]: systemd-modules-load.service: Failed with result 'exit-code'.
Jun 06 23:24:49 mike-pc systemd[1]: Failed to start Load Kernel Modules.

$ sudo pacman -Qs virtualbox
local/linux316-virtualbox-host-modules 6.0.8-1 (linux316-extramodules)
    Host kernel modules for VirtualBox
local/virtualbox 6.0.8-2
    Powerful x86 virtualization for enterprise as well as home use

solutions:

  • https://forum.manjaro.org/t/failed-to-load-kernel-modules-virtualbox/28703
  • https://unix.stackexchange.com/questions/202396/manjaro-module-vboxdrv-not-found
$ pacman -Qs virtualbox-host-modules
local/linux316-virtualbox-host-modules 6.0.8-1 (linux316-extramodules)
    Host kernel modules for VirtualBox

$ uname -r
4.19.45-1-MANJARO

$ sudo pacman -S linux419-virtualbox-host-modules
$ reboot

HHKB設定

HHKB Settings

spec
HHKB Professional2 Type-S 白/無刻印
(英語配列)

https://www.pfu.fujitsu.com/hhkeyboard/type-s/

SWITCH

1: ON
2: OFF
3: ON
4: OFF
5: ON
6: OFF

check the key code

$ xev | grep keycode

find a keycode

$ xmodmap -pke G Print
keycode 107 = Print Sys_Req Print Sys_Req
keycode 134 = Print NoSymbol Print
keycode 218 = Print NoSymbol Print

Super_R to Print button

$ cat .xmodmap
! For HHKB
keycode 134 = Print

Reload settings

$ xmodmap ~/.xmodmap

自動バックアップ

  • Install deja dup
  • Fist of all, it's need to format media by EXT4 format by gparted.
  • After that, update the media permission like below.
$ sudo chown -R $USER:$USER /run/media/mike/b1107875-0e05-4587-b144-6e2037fc9306/

リストア

  1. Install manjaro from USB memory
  2. Update mirrorlist
  3. Sync system by cmd below:
  • sudo pacman -Syu --noconfirm
  1. Install deja vu
  • sudo pacman -S --noconfirm deja-dup
  1. Restore data from its GUI

Docker Setup on Linux

add mike to docker group

$ sudo systemctl enable docker
$ sudo groupadd docker
$ sudo gpasswd -a mike docker
$ reboot

FCITX設定

Install basic package of fcitx

$ sudo pacman -S --noconfirm fcitx fcitx-mozc fcitx-configtool

Install particular package for fcitx

NOTE: if u don't install particular packages for specific gui tool kit, the IME doesn't work well. i have got weird behavior on my PC without these packages, like can not input words in gui inputbox.

$ sudo pacman -S fcitx-gtk2 fcitx-gtk3 fcitx-qt5
$ yay -S fcitx-qt4

Reboot

$ reboot

Fcitx configuration settings

Open fcitx-configuration

firstly, change default keyboard layout to to English(US). and update settings following below that:

  • Input Method
    • English (US)
    • Mozc
  • Global config
    • Trigger Input Method = Empty
    • Active input method = RALT
    • Inactive input method = LALT

To confirm fcitx status

$ fcitx-diagnose

Disable FF Alt key

Disable opening menu by alt

  • about:config > ui.key.menuAccessKey = 0
  • about:config > ui.key.menuAccessKeyFocuses = false

GNOME3設定

i configure out gnome 3 thorough gnome-tweakes

installation

$ sudo pacman -S gnome-tweaks

Settings

I updated settings like following below

  • Background
    • Universe.jpg
  • TouchPad
    • Natural Scrolling: ON
  • Online Accounts
    • Google

Gnome-tweaks

I updated settings like following below that:

  • Appearance
    • Application: Yaru-dark
    • Sound: Yaru
  • General
    • Animations: false
  • Top Bar
    • All true-
  • Keyboard & Mouse
    • Emacs Input: Enabled

Capslock to ctrl

$ gsettings set org.gnome.desktop.input-sources xkb-options "['ctrl:nocaps']"

Emacs bind for browser

$ gsettings set org.gnome.desktop.interface gtk-key-theme "Emacs"

Reload gnome-extensions

Press Alt + F2 and then enter r in the dialog box

see https://askubuntu.com/questions/75604/why-does-users-theme-extension-not-show-up-under-gnome-tweak-tool

Night mode

$ gsettings set org.gnome.settings-daemon.plugins.color night-light-temperature 3000

https://askubuntu.com/questions/914500/how-to-adjust-the-hue-intensity-of-gnome-night-light

Goldendictの設定

Hotkey

Cctl + Shift

Key Settings

go Menu > Edit > Preference > Scan Popup
and check items about following below that:

  • Enable scan popup functionality
    • Start with scan popup turned on
    • Only Show popup when all selected keys are kept pressed -Ctrl + Shift
    • Keyps may also be pressed afterwards, within 5 secs

Add dictionary

DL dictionary files from link below:

  • Babylon
    • Babylon English-Japanese (Babylon_English_Japanese.BGL)
      • https://www.babylon-software.com/free-dictionaries/languages/Babylon-English-Japanese/907.html
    • Babylon Japanese-English (Babylon_Japanese_English_dicti.BGL)
      • https://www.babylon-software.com/free-dictionaries/languages/Babylon-Japanese-English/1257.html

apply dictionaries

  • place dictionaries
    • create Dictionaries directory on home
    • copy downloaded dictionary files into Dictionaries folder
  • Scan dictionaries in GoldenDict
    • open Menu > Edit > Dictionaries > Sources > Files
    • Add Dictionaries folder
    • Press rescan now button
  • After that, press apply and done

i3

i3 Installation

$ sudo pacman -S --noconfirm i3-gaps

statusbar

$ sudo pacman -S --noconfirm libmpdclient # support for 'internal/mpd'
$ yay -S --noconfirm polybar # yay -S --rebuild polybar

login DM

# sudo pacman -S --noconfirm lightdm lightdm-gtk-greeter
# sudo pacman -S --noconfirm lightdm-gtk-greeter-settings # for tweak setting of lightdm
# sudo systemctl enable lightdm.service

background of Login DM

Place image in shared space for permission Use sudo lightdm-gtk-greeter-settings for lightdm setting

$ sudo cp /home/$USER/dotfiles/images/universe.jpg /usr/share/pixmaps/
$ sudo cp /home/$USER/dotfiles/images/ba90.png /usr/share/pixmaps/

NetworkManger

NOTE:

  • Need to stop netctl to use networkmanager
  • netctl list # show profile list, for example, i have oreore profile
  • sudo netctl stop oreore
  • sudo netctl disable oreore
$ sudo pacman -S --noconfirm networkmanager network-manager-applet
$ sudo systemctl start NetworkManager
$ sudo systemctl enable NetworkManager

Applet

Bluetooth(for blueman-applet on tray)

$ sudo pacman -S --noconfirm blueman

Clipboard manager

$ sudo pacman -S --noconfirm parcellite

Dictionary

  1. install dictionaries
    • $ mkdir ~/.goldendict/dict
    • move dictionary files under the dict folder
    • GoldenDict > Edit > Dictionaries > Sources > Files > Add ~/.goldendict/dict
    • GoldenDict > Edit > Dictionaries > Sources > Files > Scan now
    • GoldenDict > Edit > Dictionaries > Sources > Wikipedia > add and enable https://ja.wikipedia.org/w
  2. GoldenDict > Edit > Preference > Scan popup
    • enable show scan flag when word is selected
  3. GoldenDict > Desktop Menu > enable Sacn popup

links

$ mkdir ~/.goldendict/dict
$ sudo pacman -S --noconfirm goldendict

Otheres

# Launcher
sudo pacman -S --noconfirm rofi dmenu # qlcplus-qt5

# Office
sudo pacman -S --noconfirm libreoffice-fresh

# Image Viewer
sudo pacman -S --noconfirm feh sxiv

# Video Player
sudo pacman -S --noconfirm vlc

# Notification daemon
sudo pacman -S --noconfirm gnome-icon-theme # dependency for dunst
sudo pacman -S --noconfirm dunst

# Window transparent
sudo pacman -S --noconfirm compton

# Screen Capture utility
sudo pacman -S --noconfirm scrot

# EPub Reader
sudo pacman -S --noconfirm calibre

# Blightness
# NOTE: python-gobject is dependency for redshift-gtk
# see https://github.com/jonls/redshift/issues/615
sudo pacman -S --noconfirm python-gobject
sudo pacman -S --noconfirm redshift

# Volume control for system tray
sudo pacman -S --noconfirm volumeicon

# Screen Locker
# sudo pacman -S --noconfirm i3lock xautolock
sudo pacman -S --noconfirm light-locker

Setings of natural scrolling in i3

export DefaultImModule=fcitx
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS=@im=fcitx
export LC_CTYPE=ja_JP.UTF-8

run FCITX-mozc
run_im fcitx

export LC_CTYPE=en_US.UTF-8

# Enable natural scrolling
# $ xinput list #
# ⎡ Virtual core pointer                          id=2    [master pointer  (3)]
# ⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
# ⎜   ↳ SynPS/2 Synaptics TouchPad                id=11   [slave  pointer  (2)]
# ⎜   ↳ TPPS/2 IBM TrackPoint                     id=12   [slave  pointer  (2)]
#
# $ xinput list-props 11
# Device 'SynPS/2 Synaptics TouchPad':
#         libinput Scroll Methods Available (289):        1, 1, 0
#         libinput Scroll Method Enabled (290):   1, 0, 0
#         libinput Scroll Method Enabled Default (291):   1, 0, 0
xinput set-prop 11 'libinput Natural Scrolling Enabled' 1

Install Font

install nerd font

$ git clone https://github.com/macchaberrycream/RictyDiminished-Nerd-Fonts.git ~/.fonts
$ fc-cache -f -v

Check current installed fonts

$ fc-list | grep Ricty | Regular
# fotmat [font-file-path: font-name:style]

Install Japanese Font

$ sudo pacman -S noto-fonts-cjk

ref to https://forum.manjaro.org/t/texts-in-some-applications-are-garbled/95868

NTP

Activate NTP server.

$ timedatectl
               Local time: Mon 2020-08-31 18:51:48 JST
           Universal time: Mon 2020-08-31 09:51:48 UTC
                 RTC time: Mon 2020-08-31 09:51:49
                Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: no
              NTP service: inactive
          RTC in local TZ: no
$ timedatectl set-ntp true
$ timedatectl
               Local time: Mon 2020-08-31 18:57:25 JST
           Universal time: Mon 2020-08-31 09:57:25 UTC
                 RTC time: Mon 2020-08-31 09:57:25
                Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

REFERENCES:

  • https://qiita.com/j8takagi/items/cc63ee5e9cfcb20fd244

Pacman

Versions

$ pacman -V

  .--.                   Pacman v5.1.3 - libalpm v11.0.3
 / _.-' .-.  .-.  .-.    Copyright (C) 2006-2018 Pacman Development Team
 \  '-. '-'  '-'  '-'    Copyright (C) 2002-2006 Judd Vinet
  '--'
                         This program may be freely redistributed under
                         the terms of the GNU General Public License.

Update mirrorlist

$ sudo pacman-mirrors -f5

Use only Speed top 10

$ sudo pacman-mirrors --fasttrack 10

Use only Japan Server

$ sudo pacman-mirrors --country Japan

::INFO Downloading mirrors from repo.manjaro.org
::INFO User generated mirror list
::------------------------------------------------------------
::INFO Custom mirror file saved: /var/lib/pacman-mirrors/custom-mirrors.json
::INFO Using default mirror file
::INFO Querying mirrors - This may take some time
  0.091 Japan          : http://ftp.tsukuba.wide.ad.jp/Linux/manjaro/
::INFO Writing mirror list
::Japan           : http://ftp.tsukuba.wide.ad.jp/Linux/manjaro/stable
::INFO Mirror list generated and saved to: /etc/pacman.d/mirrorlist

$ cat /etc/pacman.d/mirrorlist

##
## Manjaro Linux default mirrorlist
## Generated on 2020-05-12 22:09
##
## Please use 'pacman-mirrors -f [NUMBER] [NUMBER]' to modify mirrorlist
## (Use 0 for all mirrors)
##

## Country : Japan
Server = http://ftp.tsukuba.wide.ad.jp/Linux/manjaro/stable/$repo/$arch

Install package

$ sudo -S $pkg

(Dangerous) Upgrade database

NOTE: by this cmd is not bad, but this leads directly to partial updates. Arch doesn't keep old libs around like most distros such as Ubuntu, so partial updates is not allowed.

$ sudo pacman -Sy

Upgrade database forcibly

$ sudo pacman -Syy

Upgrade database and packages

$ sudo pacman -Syu

Upgrade database and upgrade/downgrade package

$ sudo pacman -Syuu

Upgrade database and packages forcibly

NOTE:

  • -Syyu = -Syy + -Syu
  • if you update your /etc/pacman.d/mirrorlist, you need to execute this cmd
$ sudo pacman -Syyu

Updagrade packages including AUR repository

$ yay -Syu

Remove Package with unused dependencies

$ sudo pacman -Rs $pkg

How to fix “unable to lock database” error

$ sudo rm /var/lib/pacman/db.lck

lbffi.so.6: cannot open shared object file: No Such file ...

sudo ln -sf /usr/lib/libffi.so.7 /usr/lib/libffi.so.6

Trouble Shooting

  • https://forum.manjaro.org/t/manjaro-gnome-settings-18-0-and-manjaro-gnome-settings-17-0-are-in-conflict/63701/5
  • https://forum.manjaro.org/t/pacman-syyu/24160

Python

Insatll pyenv and pipenv on Arch

$ sudo pacman -S --noconfirm python-pipenv
$ yay -S --noconfirm pyenv

Install python through pyenv

$ pyenv install 3.6.0 # tensorflow doesn't work on version 3.7
$ pyenv versions
  system
    * 3.6.0 (set by /home/mike/apps/deep_learning/.python-version)

If u wanna use specific python version in local

$ pyenv local 3.6.0
$ python --version
Python 3.6.0

Specify python version of virtualenv which is used by pipenv

$ pipenv install --python 3.6
Virtualenv already exists!
Removing existing virtualenv…
Creating a virtualenv for this project…
Pipfile: /home/mike/apps/models/tutorials/image/imagenet/Pipfile
Using /home/mike/.pyenv/versions/3.6.0/bin/python3.6 (3.6.0) to create virtualenv…
⠙ Creating virtual environment...Using base prefix '/home/mike/.pyenv/versions/3.6.0'
New python executable in /home/mike/.local/share/virtualenvs/imagenet-qPLN_QUI/bin/python3.6
Also creating executable in /home/mike/.local/share/virtualenvs/imagenet-qPLN_QUI/bin/python
Installing setuptools, pip, wheel...done.
Running virtualenv with interpreter /home/mike/.pyenv/versions/3.6.0/bin/python3.6

✔ Successfully created virtual environment!
Virtualenv location: /home/mike/.local/share/virtualenvs/imagenet-qPLN_QUI
Creating a Pipfile for this project…
Pipfile.lock not found, creating…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (ca72e7)!
Installing dependencies from Pipfile.lock 

Confirm python version

$ python --version
Python 3.7.3
$ pipenv run python --version
Python 3.6.0
$ pipenv shell # launch new shell
$ python --version
Python 3.6.0

Install packages

$ pipenv install 

Install Python linters

$ pip install -U flake8 autopep8 black isort

Instsall Python tools

$ pip install -U httpie codemod

Snap

An Example of installing VoTT

Download snap file of VoTT from github release page.

Install snapd

$ sudo pacman -S snapd

Enable snapd

$ sudo systemctl enable --now snapd.socket

Install vott file via cli

$ sudo snap install --dangerous vott-2.2.0-linux.snap
2020-06-14T12:17:57+09:00 INFO Waiting for automatic snapd restart...
vott 2.2.0 installed
sudo snap install --dangerous vott-2.2.0-linux.snap  2.40s user 1.05s system 2% cpu 2:25.85 total

Launch

$ sudo vott

REFERENCES:

  • https://snapcraft.io/docs/installing-snap-on-arch-linux

SSH

make ssh key

$ mkdir ~/.ssh/
$ cd ~/.ssh/ 
$ ssh-keygen -t rsa
$ ssh-keygen -t rsa -f id_xxx_rsa # with file name

update config

$ vim ~/.ssh/config
# github
Host github
    HostName            github.com
    IdentityFile        ~/.ssh/id_rsa

change permission

$ sudo chmod -R 700 ~/.ssh/ 
$ sudo chmod 600 ~/.ssh/id_rsa

copy to github

$ cat ~/.ssh/id_rsa.pub

test

$ ssh -T git@github # test

for dotfiles

$ git remote remove origin;
$ git remote add origin git@github.com:mgoldchild/dotfiles.git

TouchPad

NOTE: this is an only for GUI on X.org

add NaturalScrolling option to InputClass that has pointer or touchpad Identifier ref https://askubuntu.com/questions/908484/natural-scrolling-in-lubuntu-17-04/1061379

$ sudo vim /usr/share/X11/xorg.conf.d/40-libinput.conf

the contents of file is below

Section "InputClass"
    Identifier "libinput pointer catchall"
    MatchIsPointer "on"
    MatchDevicePath "/dev/input/event*"
    Driver "libinput"
    Option "NaturalScrolling" "true"  # <-- add this line
EndSection
Do the same for the touchpad section:

Section "InputClass"
    Identifier "libinput touchpad catchall"
    MatchIsTouchpad "on"
    MatchDevicePath "/dev/input/event*"
    Driver "libinput"
    Option "NaturalScrolling" "true" # <-- add this line
EndSection

USBフォーマット

make ex4 file system

$ grparted

confirm mountpoint

$ lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sdb           8:16   1  29.3G  0 disk
└─sdb1        8:17   1  29.3G  0 part /run/media/mike/5f9e6061-c1ba-4e43-8ecd-8624219810f6
nvme0n1     259:0    0   477G  0 disk
├─nvme0n1p1 259:1    0   300M  0 part /boot/efi
└─nvme0n1p2 259:2    0 476.7G  0 part /

change permission

$ sudo chown -R $USER:$USER /run/media/mike/5f9e6061-c1ba-4e43-8ecd-8624219810f6

VPN(L2TP, IPSec)

Setup

NOTE: this memo is VPN of L2TP/IPSec PSK
based on https://github.com/hwdsl2/setup-ipsec-vpn
and network-manager-l2tp-gnome was not working for me that's why i used vpn cmd manually.

make .envrc

$ cp .env .envrc

check IEK algorithm type

result was below in my vpn server it means IKE algorithm is aes128-sha1-modp1024!

$ sudo ike-scan $VPN_SERVER_IP --trans="(1=7,14=128,2=2,3=1,4=2)"
XXX.XXX.XXX.XXX  Main Mode Handshake returned HDR=(CKY-R=5911387ba9cc4c1e) SA=(Enc=AES KeyLength=128 Hash=SHA1 Group=2:modp1024 Auth=PSK LifeType=Seconds LifeDuration=1800)

to load vpn credential

$ cd ~/dotifiles
$ sudo direnv allow && sudo direnv exec . bash
# echo $VPN_SERVER_IP

run setup script

# sh /home/mike/dotfiles/scripts/vpn-setup.sh

Start L2TP/IPSec

Firstly, need to start processes

$ /usr/bin/systemctl restart strongswan
$ /usr/bin/systemctl restart xl2tpd

SWitch shell to use env

$ sudo direnv allow && sudo direnv exec . bash

Start VPN

$ wget -qO- http://ipv4.icanhazip.com; echo # current ip address
$ 
$ ipsec up myvpn # start ipsec
$ echo "c myvpn" > /var/run/xl2tpd/l2tp-control # start l2tp
$ ifconfig # confim whether ppp0(Point-to-Point Protocol) exits or not
$ ip route # check default route
$ route add $VPN_SERVER_IP gw 192.168.0.1 # replace default route; 192.168.0.1 is gateway ip, it appeared by `default via X.X.X.X ....`
$ route add default dev ppp0 # Add a new default route to start routing traffic via the VPN server
$ 
$ wget -qO- http://ipv4.icanhazip.com; echo # new ip address

finish VPN

$ route del default dev ppp0
$ echo "d myvpn" > /var/run/xl2tpd/l2tp-control
$ ipsec down myvpn

Get gateway address

DEFAULT_GW=$(python3 ~/dotfiles/scripts/gw_addr.py)
route add $VPN_SERVER_IP gw $DEFAULT_GW # replace default route; 192.168.0.1 is gateway ip, it appeared by `default via X.X.X.X ....`

VPN(OpenVPN)

Wine

Package Installation

$ sudo pacman -S wine
$ sudo pacman -S wine-gecko wine-mono

exe installer

$ wine hoge.exe

msi installer

$ wine msiexec /i hoge.msi

inf installer

$ wine rundll32 setupapi,InstallHinfSection DefaultInstall 132 hoge.inf

reset installed wine

$ rm -rf ./wine

REFERENCES:

  • http://itmst.blog71.fc2.com/blog-entry-63.html

XModmap

Modify Key Map

Install dependencies

$ sudo pacman -S xorg-xev
$ sudo pacman -S xmodmap
$ sudo pacman -S xbindkeys

Check keycode

in my case, RALT was target

$ xev # press RALT

KeyRelease event, serial 37, synthetic NO, window 0x5000001,
    root 0x135, subw 0x0, time 1868483, (404,481), root:(443,576),
    state 0x80, keycode 108 (keysym 0xfe03, ISO_Level3_Shift), same_screen YES,
    XKeysymToKeycode returns keycode: 92
    XLookupString gives 0 bytes:
    XFilterEvent returns: False

So key code is 108

another way to confirm

$ xbindkeys -mk
Press combination of keys or/and click under the window.
You can use one of the two lines after "NoCommand"
in $HOME/.xbindkeysrc to bind a key.

--- Press "q" to stop. ---
"(Scheme function)"
    m:0x80 + c:108
    Mod5 + ISO_Level3_Shift
X connection to :1 broken (explicit kill or server shutdown).

108 is the keycode

Confirm current keymap

$ xmodmap
xmodmap:  up to 4 keys per modifier, (keycodes in parentheses):

shift       Shift_L (0x32),  Shift_R (0x3e)
lock
control     Control_L (0x25),  Control_L (0x42),  Control_R (0x69)
mod1        Alt_L (0x40),  Meta_L (0xcd)
mod2        Num_Lock (0x4d)
mod3
mod4        Super_L (0x85),  Super_R (0x86),  Super_L (0xce),  Hyper_L (0xcf)
mod5        ISO_Level3_Shift (0x5c),  Mode_switch (0xcb)

So, now I wanna remove ISO_Level3_Shift from mod5 and add Alt_R

Update xmodmap

Script of .xmodmap will be like below:

remove mod5 = ISO_Level3_Shift
keycode 108 = Alt_R

reload xmodmap

$ xmodmap .xmodmap

REFERENCES:

  • http://haraita9283.blog98.fc2.com/blog-entry-273.html

Install RStudio

$ yay -S rstuiod-desktop
$ ln -s /usr/share/qt/resources ~/.QtWebEngineProcess

REF

  • https://aur.archlinux.org/packages/rstudio-desktop/

文字からフォントを探す

ref https://github.com/jaagr/polybar/wiki/Fonts

need to install module

$ perl -MCPAN -e 'install Font::FreeType'

Usage

$ perl ~/dotfiles/scripts/find-font.pl "😀"

find a character from character code

$ fc-list | grep "Noto"
$ fc-cache # to reflesh cache
$ fc-match "NotoSansSymbols2-Regular"
$ gucharmap # to find a character from character code
$ # open https://nerdfonts.com/ # to get character code

Queryの順序

指定順序と実行順序

The conceptual order of query processing is:

指定順序実行順序内容
21FROM(Including JOINs)実行対象のテーブルを指定する
32WHEREテーブルに対してレコードの抽出条件を指定する
43GROUP BYレコードをグループ化する
54HAVINGグループ化した結果に対して抽出条件を指定する
15SELECT取得(表示)する列を指定する
66ORDER BY取得した列を並び替える

まとめ経

GROUP BY句

  • 複数のレコードをグルーピングする
  • データ操作には、FROM句とWHERE句の結果が使用される
  • GROUP BYを使った場合、SELECT句に加工なしで使える項目は、GROUP BY句に使った項目に依存する
  • 要はGROUP BY句で指定していない、重複するカラムをSELECT文に集計関数抜きなどでは指定できない

HAVING句

  • GROPU BY用のWHERE句
  • HAVING句の指定はグループ(複数行のレコード)に対して行われる
  • HAVING構文は、集計関数を含めることができる点を除けば、WHERE 構文と同じ
  • WHERE 検索条件がグループ化操作の前に適用されるのに対し、HAVING 検索条件はグループ化操作の発生後に適用される

サブクエリ

  • 主にSELECT, JOIN, FROM, WHERE, HAVINGなどで括弧と共に使う。
  • 相関サブクエリはエイリアスなどを使って、外側の結果を参照したもの
  • 基本的にサブクエリは一つの関数として読む
タイプ読み方
(非相関)サブクエリサブクエリの引数はなく。1度だけ実行される
相関サブクエリサブクエリの引数があるため、引数が変わったタイミングで実行される

boolean戻す系

ANY, ALL, EXISTS演算子

  • ANY, ALL, EXISTS演算子はサブクエリの「TRUE」または「FALSE」を評価する

ANY(SOME)

  • 比較演算子と共に使用する
  • 結果セットの値のいずれかが比較演算子の関係を満たす場合にTRUEを返す

ALL

  • 比較演算子と共に使用する
  • 結果セットの値の全てが比較演算子の関係を満たす場合にTRUEを返す

EXISTS

  • サブクエリの生成した値が存在する場合はTRUEを返す
  • 否定はNOT EXISTS

結合系

UNION

和集合

  • 重複を削除する場合
/* BLUE + RED */

SELECT * FROM BLUE
UNION
SELECT * FROM RED ;
  • 重複を削除しない場合
/* BLUE + RED */

SELECT * FROM BLUE
UNION ALL
SELECT * FROM RED ;

EXPECT

差集合

/* BLUE - RED(BLUEにはあって、REDにはないもの) */

SELECT * FROM BLUE
EXCEPT
SELECT * FROM RED ;

INTERSECT

積集合

/* BLUE * RED */
 
SELECT * FROM BLUE
INTERSECT
SELECT * FROM RED ;

集計系

集計関数

関数名機能
COUNT集計対象の行数を出力
MAX集計対象のなかで最大のものを出力
MIN集計対象のなかで最小のものを出力
SUM集計対象の合計値を出力
AVG集計対象の平均を出力

GROPU BYしてその中の最大の値を含む行を取得する


-- table

id  home  datetime     player   resource
---|-----|------------|--------|---------
1  | 10  | 04/03/2009 | john   | 399 
2  | 11  | 04/03/2009 | juliet | 244
5  | 12  | 04/03/2009 | borat  | 555
3  | 10  | 03/03/2009 | john   | 300
4  | 11  | 03/03/2009 | juliet | 200
6  | 12  | 03/03/2009 | borat  | 500
7  | 13  | 24/12/2008 | borat  | 600
8  | 13  | 01/01/2009 | borat  | 700

-- wants result

id  home  datetime     player   resource 
---|-----|------------|--------|---------
1  | 10  | 04/03/2009 | john   | 399
2  | 11  | 04/03/2009 | juliet | 244
5  | 12  | 04/03/2009 | borat  | 555
8  | 13  | 01/01/2009 | borat  | 700


SELECT tt.*
FROM topten tt
INNER JOIN
    (SELECT home, MAX(datetime) AS MaxDateTime
    FROM topten
    GROUP BY home) groupedtt 
ON tt.home = groupedtt.home 
AND tt.datetime = groupedtt.MaxDateTime

別テーブルに存在するIDの合計値を取得したい

- 全社員の売上の合計を表示したい。

社員マスタ
社員コード	社員名	部署コード	年齢
1	テスト社員1	1	22
2	テスト社員2	2	30
3	テスト社員3	null	20

売上明細
売上NO	社員コード	売上日	売上金額
1	1	20150401	200
2	1	20150402	300
3	2	20150408	100
4	2	20150501	150
5	3	20150505	550

SELECT
   MAX(T1.社員名) AS 社員名
   ,SUM(T2.売上金額) AS 売上金額
FROM
  社員マスタ AS T1
LEFT JOIN
  売上明細 AS T2
ON
  T1.社員コード = T2.社員コード
GROUP BY
  T1.社員コード


--実行結果

社員名	売上金額
テスト社員1	500
テスト社員2	250
テスト社員3	550

別テーブルにIDが存在していたら、元のレコードを取得する

- 売上のある社員のみ表示したい。

社員マスタ
社員コード	社員名	部署コード	年齢
1	テスト社員1	1	22
2	テスト社員2	2	30
3	テスト社員3	null	20
4	テスト社員4	1	30

売上明細
売上NO	社員コード	売上日	売上金額
1	1	20150401	200
2	1	20150402	300
3	2	20150408	100
4	2	20150501	150
5	3	20150505	550
SELECT
     社員名
FROM
     社員マスタ AS T1
WHERE
     EXISTS(
          SELECT
               1
          FROM
               売上明細 AS S1
          WHERE
               T1.社員コード = S1.社員コード
     )


--↓EXISTSを使わない場合
SELECT
     MAX(T1.社員名) AS 社員名
FROM
     社員マスタ AS T1
JOIN
     売上明細 AS T2
ON
     T1.社員コード = T2.社員コード
GROUP BY
     T1.社員コード
```gg

自己結合

  • テーブルが再帰的(同一テーブルへのparent_idを持っている)時などに有効
従業員コード従業員名上司コード
00001チャーリー・ブラウン
00002ペパーミント・パティ
00003ルシール・ヴァン・ぺルト00001
00004ライナス・ヴァン・ぺルト00003
00005シュローダー00001
00006マーシー00002
SELECT
     部下.従業員コード
     ,部下.従業員名
     ,上司.従業員名 AS 上司の名前
FROM
     従業員 AS 部下
JOIN 
     従業員 AS 上司
ON
     部下.上司コード = 上司.従業員コード
ORDER BY
    部下.従業員コード
従業員コード従業員名上司の名前名
00003ルシール・ヴァン・ぺルトチャーリー・ブラウン
00004ライナス・ヴァン・ぺルトルシール・ヴァン・ぺルト
00005シュローダーチャーリー・ブラウン
00006マーシーペパーミント・パティ

結合系

UNION

和集合

  • 重複を削除する場合
/* BLUE + RED */

SELECT * FROM BLUE
UNION
SELECT * FROM RED ;
  • 重複を削除しない場合
/* BLUE + RED */

SELECT * FROM BLUE
UNION ALL
SELECT * FROM RED ;

EXPECT

差集合

/* BLUE - RED(BLUEにはあって、REDにはないもの) */

SELECT * FROM BLUE
EXCEPT
SELECT * FROM RED ;

INTERSECT

積集合

/* BLUE * RED */
 
SELECT * FROM BLUE
INTERSECT
SELECT * FROM RED ;

アソシエーション

1:多

  • 芸能人と一般人のパターン
  • 多が1を知る必要がある

多:多

  • タグ付けのテーブルなどで使われるパターン
  • 2次元では表現できないので、中間テーブルを用意する

1:1

  • 目的ごとに1つのテーブルを分けるパタン
  • 意味論的と変更可能性を考慮して設計する

例) 例えば、UserテーブルとそのUserのCredentialが合った場合、

  • UserがCredentialのIDを所有する
    • 意味論的にusers knows credential_idの方がcredentials knows user_idより良いから
  • ただし、今後の変更で1:多になるなら
    • つまり、User:Credential = 1:多になる場合はCredentailがUserを知る必要がある
    • スカラ値は正規化ではRDBでは許容されないから
  • データ的にprimary度が高い方を親とする
  • 作られる時系列を考慮する
    • Nullが埋まるFKはよくないので、先に作られる方を親とする
    • もし、credentials knows user_idにすると、credentailを作る時に、user_idが必要になる

JOIN vs Union

  • 左と右をつなげたい場合(カラム追加)は => join
  • 上と下をつなげたい場合(レコード追加)は => union
SELECT
    posts.id,
    lx.is_liked,
    lx2.likes_count
FROM
    posts
LEFT OUTER JOIN(
    SELECT
        p1.id AS note_id,
        IF(l1.user_id = 1, "YES", "NO") AS is_liked
    FROM
        posts AS p1
    LEFT OUTER JOIN(
        SELECT
            *
        FROM
            likes
        WHERE
            likes.user_id = 1
    ) AS l1
ON
    l1.note_id = p1.id
GROUP BY
    p1.id,
    l1.user_id
) AS lx
ON
    lx.note_id = posts.id
LEFT OUTER JOIN(
    SELECT posts.id AS note_id,
        COUNT(*) likes_count
    FROM
        posts
    LEFT OUTER JOIN likes ON likes.note_id = posts.id
    GROUP BY
        likes.note_id,
        posts.id
    ORDER BY
        posts.id
) AS lx2
ON
    lx2.note_id = posts.id

JOIN vs. in

もし、結合のカラムがuniqueならば JOIN(①)とIN(②)は同じ結果になる

SELECT  a.*
FROM    a
JOIN    b
ON      a.col = b.col

SELECT  a.*
FROM    a
WHERE   col IN
        (
        SELECT  col
        FROM    b
        )

uniqueでなくても、JOINの時にditrictすると(③)、inと同じ意味。

SELECT  a.*
FROM    a
JOIN    (
        SELECT  DISTINCT col
        FROM    b
        )
ON      b.col = a.col

パフォーマンスは in > join on ditinct

REF

  • https://stackoverflow.com/questions/1200295/sql-join-vs-in-performance

テーブル継承パターン

E.g.

  • We have Note and Draft model class.
  • Parent model class of Note and Draft is Post.
  • And both have body and title field.
  • But Note only has published_date field.
  • Draft doesn't have it.

Concrete Table Inheritance pattern

Notes table

id: xxx
title:xxx
body: xxx
published_date: xxx, not null

Drafts table

id: xxx
title:xxx
body: xxx

Single Table Inheritance pattern

Posts Table

id: xxx
type: enum, note or draft
title:xxx
body: xxx
published_date: xxx, nullable

Class Table Inheritance pattern

Posts Table

id: xxx
title:xxx
body: xxx

Notes table

id: xxx
post_id: xxx
published_date: xxx, not null

Drafts table

id: xxx
post_id: xxx

Difference

PatternParent tableChildren table
Concrete Table Inheritance-x
Single Table Inheritancex-
Class Table Inheritancexx

NOTE:

  • This patterns are depended on premise of existence of multiple class.
  • But tables that will not be modified frequenly like a intermediate table for N:N is okay not to be separate.
  • That means it's okay not use this pattern.

References

  • https://en.wikipedia.org/wiki/Single_Table_Inheritance
  • https://github.com/bliki-ja/bliki-ja.github.io
  • https://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
  • https://www.martinfowler.com/eaaCatalog/classTableInheritance.html
  • https://www.martinfowler.com/eaaCatalog/concreteTableInheritance.html

MySQLの排他処理

https://blog.amedama.jp/entry/2015/09/19/012009

Exclusion Control

  • Pessimistic locking
  • Pessimistic locking without select for
  • Optimistic locking

Settings

$ mysql -u root -e "show variables like 'version'"
+---------------+--------+
| Variable_name | Value  |
+---------------+--------+
| version       | 5.6.26 |
+---------------+--------+
$ mysql -u root -e "select @@tx_isolation"
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
$ mysql -u root -e "show variables like 'default_storage_engine'"
+------------------------+--------+
| Variable_name          | Value  |
+------------------------+--------+
| default_storage_engine | InnoDB |
+------------------------+--------+
mysql> prompt prompt1> 
PROMPT set to 'prompt1> '
prompt1>

mysql> prompt prompt2> 
PROMPT set to 'prompt2> '
prompt2>

No exclusion control

table

mysql> create table accounts (
    ->     id Integer auto_increment,
    ->     name Text not null,
    ->     cash Integer not null,
    ->     primary key (id)
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> desc accounts;
+-------+---------+------+-----+---------+----------------+
| Field | Type    | Null | Key | Default | Extra          |
+-------+---------+------+-----+---------+----------------+
| id    | int(11) | NO   | PRI | NULL    | auto_increment |
| name  | text    | NO   |     | NULL    |                |
| cash  | int(11) | NO   |     | NULL    |                |
+-------+---------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

data

mysql> insert into accounts (name, cash) values ('foo', 100);
Query OK, 1 row affected (0.00 sec)

confirm

prompt1> begin;
Query OK, 0 rows affected (0.00 sec)

prompt1> select * from accounts where name like 'foo';
+----+------+------+
| id | name | cash |
+----+------+------+
|  1 | foo  |  100 |
+----+------+------+
1 row in set (0.00 sec)


prompt2> begin;
Query OK, 0 rows affected (0.00 sec)

prompt2> select * from accounts where name like 'foo';
+----+------+------+
| id | name | cash |
+----+------+------+
|  1 | foo  |  100 |
+----+------+------+
1 row in set (0.00 sec)

update

prompt1> update accounts set cash = 150 where name like 'foo';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

prompt2> update accounts set cash = 200 where name like 'foo';
...


prompt1> commit;
Query OK, 0 rows affected (0.00 sec)

prompt2> update accounts set cash = 200 where name like 'foo';
Query OK, 1 row affected (8.78 sec)
Rows matched: 1  Changed: 1  Warnings: 0

prompt2> commit;
Query OK, 0 rows affected (0.00 sec)

result

mysql> select * from accounts where name like 'foo';
+----+------+------+
| id | name | cash |
+----+------+------+
|  1 | foo  |  200 |
+----+------+------+
1 row in set (0.00 sec)

Pessimistic locking

table

mysql> create table accounts (
    ->     id Integer auto_increment,
    ->     name Text not null,
    ->     cash Integer not null,
    ->     primary key (id)
    -> );
Query OK, 0 rows affected (0.07 sec)

mysql> desc accounts;
+-------+---------+------+-----+---------+----------------+
| Field | Type    | Null | Key | Default | Extra          |
+-------+---------+------+-----+---------+----------------+
| id    | int(11) | NO   | PRI | NULL    | auto_increment |
| name  | text    | NO   |     | NULL    |                |
| cash  | int(11) | NO   |     | NULL    |                |
+-------+---------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

data

mysql> insert into accounts (name, cash) values ('foo', 100);
Query OK, 1 row affected (0.00 sec)

query

prompt1> begin;
Query OK, 0 rows affected (0.00 sec)

prompt1> select * from accounts where name like 'foo' for update;
+----+------+------+
| id | name | cash |
+----+------+------+
|  1 | foo  |  100 |
+----+------+------+
1 row in set (0.00 sec)

prompt2> begin;
Query OK, 0 rows affected (0.00 sec)

prompt2> select * from accounts where name like 'foo' for update;
...

prompt1> update accounts set cash = 150 where name like 'foo';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

prompt1> commit;
Query OK, 0 rows affected (0.01 sec)

prompt2> select * from accounts where name like 'foo' for update;
+----+------+------+
| id | name | cash |
+----+------+------+
|  1 | foo  |  150 |
+----+------+------+
1 row in set (13.00 sec)

prompt2> update accounts set cash = 250 where name like 'foo';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

prompt2> commit;
Query OK, 0 rows affected (0.00 sec)

result

mysql> select * from accounts where name like 'foo';
+----+------+------+
| id | name | cash |
+----+------+------+
|  1 | foo  |  250 |
+----+------+------+
1 row in set (0.00 sec)

Pessimistic locking without select for

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update accounts set cash = cash + 100 where name like 'foo';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from accounts where name like 'foo';
+----+------+------+
| id | name | cash |
+----+------+------+
|  1 | foo  |  350 |
+----+------+------+
1 row in set (0.00 sec)

Optimistic locking

table

mysql> create table accounts (
    ->     id Integer auto_increment,
    ->     version Integer not null,
    ->     name Text not null,
    ->     cash Integer not null,
    ->     primary key (id)
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> desc accounts;
+---------+---------+------+-----+---------+----------------+
| Field   | Type    | Null | Key | Default | Extra          |
+---------+---------+------+-----+---------+----------------+
| id      | int(11) | NO   | PRI | NULL    | auto_increment |
| version | int(11) | NO   |     | NULL    |                |
| name    | text    | NO   |     | NULL    |                |
| cash    | int(11) | NO   |     | NULL    |                |
+---------+---------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

data

mysql> insert into accounts (version, name, cash) values (1, 'foo', 100);
Query OK, 1 row affected (0.00 sec)

query

prompt1> begin;
Query OK, 0 rows affected (0.00 sec)

prompt1> select * from accounts where name like 'foo';
+----+---------+------+------+
| id | version | name | cash |
+----+---------+------+------+
|  1 |       1 | foo  |  100 |
+----+---------+------+------+
1 row in set (0.00 sec)

prompt2> begin;
Query OK, 0 rows affected (0.00 sec)

prompt2> select * from accounts where name like 'foo';
+----+---------+------+------+
| id | version | name | cash |
+----+---------+------+------+
|  1 |       1 | foo  |  100 |
+----+---------+------+------+
1 row in set (0.00 sec)

prompt1> update accounts set version = 2, cash = 150 where name like 'foo' and version = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

prompt2> update accounts set version = 2, cash = 200 where name like 'foo' and version = 1;
...

prompt1> commit;
Query OK, 0 rows affected (0.00 sec)

prompt2> update accounts set version = 2, cash = 200 where name like 'foo' and version = 1;
Query OK, 0 rows affected (12.56 sec)
Rows matched: 0  Changed: 0  Warnings: 0

prompt2> rollback;
Query OK, 0 rows affected (0.00 sec)

prompt2> begin;
Query OK, 0 rows affected (0.00 sec)

prompt2> select * from accounts where name like 'foo';
+----+---------+------+------+
| id | version | name | cash |
+----+---------+------+------+
|  1 |       2 | foo  |  150 |
+----+---------+------+------+
1 row in set (0.00 sec)

prompt2> update accounts set version = 3, cash = 250 where name like 'foo' and version = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

prompt2> commit;
Query OK, 0 rows affected (0.00 sec)

result

mysql> select * from accounts where name like 'foo';
+----+---------+------+------+
| id | version | name | cash |
+----+---------+------+------+
|  1 |       3 | foo  |  250 |
+----+---------+------+------+
1 row in set (0.00 sec)

NOTE:

  • using pessimistic locking (select ... for update) without index of coulmn (in previous example, it's name) locks whole records since RDBMS doesn't know the specific record.
  • In this case, it is necessary to be careful because operations from another transaction are blocked up to rows which are not supposed to be processed in parallel.

親殺し

DROP DATABASE test;

CREATE DATABASE test;

use test;

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL
);

CREATE TABLE buildings (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL
);

CREATE TABLE rooms (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    user_id INT NOT NULL,
    building_id INT NOT NULL,
    FOREIGN KEY (user_id)
        REFERENCES users (id)
        ON DELETE CASCADE,
    FOREIGN KEY (building_id)
        REFERENCES buildings (id)
        ON DELETE CASCADE
);

INSERT INTO users(name) VALUES('hoge');
INSERT INTO buildings(name) VALUES('test');
INSERT INTO rooms(name, user_id, building_id) VALUES('room1',1,1);

SELECT * FROM buildings;
SELECT * FROM users;
SELECT * FROM rooms;

DELETE FROM buildings WHERE id = 1;

-- room will be deleted even if user exists

MySQLのPWリセット

mysql.server stop
mysql.server start --skip-grant-tables
mysql
use mysql;
update user set authentication_string=PASSWORD("XXX") where User='root';
flush privileges;
quit;
mysql.server restart
mysql -uroot -pXXX

MySQLでFK制約一時的外し

SET FOREIGN_KEY_CHECKS=0;
SET FOREIGN_KEY_CHECKS=1;
SELECT @@foreign_key_checks;

-- Transaction

BEGIN
SELECT * FROM table_name FOR UPDATE
COMMIT
ROLLBACK


-- User
--- to avoid sudoers because of  UNIX_SOCKET Authentication Plugin (auth_socket)
--- https://jyn.jp/ubuntu-16-04-mariadb-password-bug/
use mysql
CREATE USER 'hoge'@'localhost' IDENTIFIED BY '123';
GRANT ALL ON *.* TO 'hoge'@'localhost';

MySQLでFKにNull

Cliの準備

CLIの準備(Ubuntu)

$ sudo apt install postgresql-client-common
$ sudo apt-get install postgresql-client

passwordを入力しないで接続する方法

$ cd
$ vi .pgpass
$ cat .pgpass
localhost:5432:database_0:user_0:password_0
$ chmod 600 .pgpass
$ psql -h localhost -U user_0 -d database_0

もしくは

$ export Password=password_0
$ psql -h localhost -U user_0 -d database_0

djangoのtestでdatabaseを自動生成するのでエラーが出た場合、

ALTER USER user_0 CREATEDB;

MySQL vs. PostgreSQL

機能MySQLPostgreSQL
起動$ mysql -p -h ホスト名 -P ポート番号 -u ユーザ名 DB名$ psql -h ホスト名 -p ポート番号 -U ユーザ名 DB名
データベース一覧show databases;\l
データベース切替use DB名 \u DB名\c DB名
テーブル一覧show tables;\d、\dt、\d+、\dt+
テーブル定義確認desc テーブル名;\d テーブル名
テーブルCREATE文確認show create table テーブル名pg_dump DB名 -U ユーザ名 -s -t テーブル名
インデックス一覧SHOW INDEX FROM tbl_name;\d table_name
行表示の切り替えselect * from t \G\x select * from t;
SQLファイル実行.\i
SQLダンプmysqldumppg_dump
TSVダンプmysqldump -u USER --password=PASS DATABASE_NAME TABLE_NAME -T /tmp???
TSVインポートLOAD DATA LOCAL INFILE '$FILE_NAME' REPLACE INTO TABLE $TABLE_NAME IGNORE 1 LINES;copy table_name from '/absolute_path/to/data.tsv' ( delimiter ' ', format csv, header true ); ※1
SQL時間計測デフォルトで表示される\timing on
ログ出力開始\T log.txt\o log.txt
ログ出力終了\t\o
定義をコピーしてテーブル作成create table t2 like t1;create table t2 (like t1);
実行計画SQLの先頭にEXPLAINをつけるSQLの先頭にEXPLAINをつける
接続先サーバ確認\s\conninfo
接続を確認show processlist;select * from pg_stat_activity;
連番IDカラム名 int auto_incrementカラム名 serial
今日の日付curdate()current_date
現在時刻now()now()
ヘルプ\h または ?
設定ファイル~/.my.cnf~/.
show user listSELECT User, Host FROM mysql.user;\du

その他

$ psql -h localhost -p 5432 -U root -W root
$ create database xxx OWNER = admin TEMPLATE = template0 ENCODING = 'UTF8';

MySQL \Gに匹敵するもの

select * from users \gx

クオーテーションの違い

dbシングルクォーテーションダブルクォーテーションバッククォート
postgre文字列定数カラム名todo
mysql文字列定数文字列定数名カラム名

REFERENCES:

  • https://qiita.com/aosho235/items/c657e2fcd15fa0647471
  • https://serverfault.com/questions/34741/postgres-equivalent-to-mysqls-g

バックログ vs. エピック

用語意味
ストーリーエンドユーザーによる要件
バックログタスク(ストーリー)を優先度順に集めたものが
エピックタスクやストーリーを一定のジャンルでグルーピング
スプリントイテレーションのこと

REF

  • https://www.ricksoft.jp/qa/questions/38175763/%E3%82%A8%E3%83%94%E3%83%83%E3%82%AF%E3%81%A8%E3%83%90%E3%83%83%E3%82%AF%E3%83%AD%E3%82%B0%E3%81%A8%E3%81%84%E3%81%86%E6%A6%82%E5%BF%B5%E3%81%8C%E3%81%AA%E3%81%8B%E3%81%AA%E3%81%8B%E7%90%86%E8%A7%A3%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84
  • https://www.atlassian.com/agile/project-management/epics-stories-themes

カンバン vs. マイルストーン

用語リレーションFW目的
projectproject: issue = N:Nカンバン人の進捗
milestonemilestone: issue = 1:Nスクラムモノの進捗

ref

https://stackoverflow.com/questions/39591795/what-is-the-difference-relationship-between-github-projects-and-milestones#:~:text=Milestones%20is%20a%20tool%20for,and%20steady%20flow%20of%20work.

SOP: Same Origin Policy

Originはオリジン、源泉とも表記され、以下の3つを一組としてすべて一致するとき同一とみなす。 表題に反して、コンテンツは動的に生成されるとは限らない[1]。

ホスト
スキーム
ポート
例えば、次のものは同一のところから来たと扱われる。

http://example.com/
http://example.com:80/
http://example.com/path/file

次のものは、お互いに別のところから来たと扱われる。

http://example.com/
http://example.com:1234/
http://www.example.com/
https://example.com/
http://example.org/
http://wikipedia.org

https://ja.wikipedia.org/wiki/%E5%90%8C%E4%B8%80%E7%94%9F%E6%88%90%E5%85%83%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC

ようは <scheme>://<hostname>:<port>

ただし、domainを設定すれば、sub domainにも送信される

https://qiita.com/il-m-yamagishi/items/9aad5737c80d5bfd5eb8

CORS: Cross-Origin Resource Sharing

Access-Control-Allow-Origin: xxx.com でサーバー側でwihtelistでリクエストを保護する

CSRF:Cross-site Request Forgery

Cookieが自動的に送信される仕様なのが問題

XSS: Cross-site scripting

Cookie

Cookieの基本動作

HTTPリクエストをするとヘッダに次のようなデータがつく。

Set-Cookie: SID=31d4d96e407aad42; Path=/; Domain=example.com

attrvalue
SID31d4d96e407aad42
Path/
Domainexample.com

SID=31d4d96e407aad42のような形でKV形式でデータをヘッダで取り扱う仕組み PathDomainは、このデータの適用範囲を示すもの。

その他の属性

attrtype
HttpOnlyJSで読み込めるかどうか
SecureSSLのみかどうか
SameSite他サイトににCookieを送るかどうか(最近はデフォでLax)

メモ:

Cookieを使わない場合は、CSRFの対策は必要なし

https://security.stackexchange.com/questions/166724/should-i-use-csrf-protection-on-rest-api-endpoints

その場合はlocalstorageのXSS(Cross-site scripting)に注意する

https://softwareengineering.stackexchange.com/questions/314412/can-i-prevent-csrf-attacks-by-using-localstorage-sessionstorage

参考文献

  • http://watanabe-tsuyoshi.hatenablog.com/entry/2015/03/04/123649
  • https://www.scutum.jp/information/waf_tech_blog/2017/11/waf-blog-051.html
  • https://qiita.com/okamoai/items/044c03680766f0609d41
  • https://laboradian.com/same-site-cookies/

LocalStorage vs Cookie

Pros and Cons of LocalStorage vs. Cookie

https://stackoverflow.com/questions/35291573/csrf-protection-with-json-web-tokens

  • LocalStorage

    • strong for CSRF
    • but week for XSS
  • Cookie

    • strong for XSS (httponly mode)
    • but week for CSRF (but there is easy solution such as form hidden value)

Should I use CSRF protection on Rest API endpoints?

https://security.stackexchange.com/questions/166724/should-i-use-csrf-protection-on-rest-api-endpoints

No cookie No CSRF

Protection of localstorage

トークンはAuthorizationヘッダをおすすめしている
ただし、認証が必要な画像のリクエストにはCookieを使用する必要がある

https://softwareengineering.stackexchange.com/questions/314412/can-i-prevent-csrf-attacks-by-using-localstorage-sessionstorage

SAML

OAuth 2.0

https://gist.github.com/mgoldchild/4f77c9ba7e1a0634046a814cefa4ea55

VIM文法

セットアップ

Settings

  • mouse speed
  • touchpad gesture
  • add Japanese Input source
  • night mode

Mannually installing

  • google chrome
  • sync account
  • 1password chrome extension
    • password manager
  • karabiner-elements
    • for Japanese IME Switching
  • homebrew
    • for another applications
  • VSCode
    • via official website
  • Iterm2
    • via official website
  • MS Office
    • via official website
  • Google Japanese Input
    • GoogleのIME

From App Store

  • Amphetamine
  • BetterSnapTool
  • slack
  • kindle

App via homebrew

brew install nvm

REFERENCES:

  • https://pc-karuma.net/mac-keys-modifiers-switch-command-control-caps/
  • https://support.apple.com/ja-jp/guide/japanese-input-method/jpim10267/mac
  • https://hl-journal.com/mac/mac-uskey-change/
  • https://satoshisgarage.tech/?p=7016

NVM

https://qiita.com/sotoiwa/items/a3282640e3718207f9ab

$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.32.1/install.sh | bash

$ cat .zshrc
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm

$ npm -i -g yarn

mysqlclient

https://github.com/PyMySQL/mysqlclient-python/issues/131

brew install mysql
LDFLAGS=-L/usr/local/opt/openssl/lib pip3 install mysqlclient --user

posgre

http://prunus1350.hatenablog.com/entry/2016/01/11/232233

brew install postgresql
pip3 install psycopg2 --user

References