/var/log/pabotesu.log

日々の記録

ESXi on KVMを実装していきたい

Introduction - ESXi on KVMを実装していきたい

あけましておめでとうございます!ひさびさすぎる更新となりました...

2020年の後半はいろいろ資格を取っていたり、技術的な部分のインプットに時間を充ててました...

(それ以外だとiPad Airを 買ったり、キーボードが届いてテンションが上がったり...)

とまぁ、私事になりますが現在業務でVMwareを扱う機会が多く、今月中にもVCPを取得する予定でもあります。

できれば、身近な環境でVMwareのvShpereを実装してみたいと思いました。

ですので、今回は普段遣いしているLinux環境のKVM上でESXiを動かしたい!という試みです。

結論から申し上げますと、実装はできたけど「まだまだ試す部分が多い」という所感です。

この部分は今後の記事のネタにできればと思います。

Environment - 実装環境

#OSとカーネル
$ uname -a
Linux Arch-Machine 5.9.14-zen1-1-zen #1 ZEN SMP PREEMPT Sat, 12 Dec 2020 14:36:44 +0000 x86_64 GNU/Linux

#実装するマシンのホスト名
$ uname -n
Arch-Machine

#ハードウェア
$ lscpu | grep "Architecture\|Thread(s) per core\|Core(s) per socket\|Model name\|Frequency boost\|CPU MHz"
Architecture:                    x86_64
Thread(s) per core:              2
Core(s) per socket:              6
Model name:                      AMD Ryzen 5 3600 6-Core Processor
Frequency boost:                 enabled
CPU MHz:                         2317.892

$ free
              total        used        free      shared  buff/cache   available
Mem:       32873960     1634276    29700216      410256     1539468    30441708
Swap:      33554428           0    33554428

$ lsblk | grep nvme
nvme0n1     259:0    0 465.8G  0 disk 
├─nvme0n1p1 259:1    0   512M  0 part /boot
├─nvme0n1p2 259:2    0    32G  0 part [SWAP]
├─nvme0n1p3 259:3    0    64G  0 part /
└─nvme0n1p4 259:4    0 369.3G  0 part /home

#ネットワーク周り
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp4s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 50:3e:aa:14:33:c1 brd ff:ff:ff:ff:ff:ff
    inet 192.168.10.22/24 brd 192.168.10.255 scope global dynamic noprefixroute enp4s0
       valid_lft 34242sec preferred_lft 28842sec
    inet6 fe80::e894:cfe7:c06f:33e5/64 scope link 
       valid_lft forever preferred_lft forever
3: enp5s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
    link/ether a8:a1:59:16:44:03 brd ff:ff:ff:ff:ff:ff
4: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:d3:55:88 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
5: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:d3:55:88 brd ff:ff:ff:ff:ff:ff

Concept - 構想

+Arch Machine----------------+-------+----------+
|(192.168.10.22)             |enp4s0 |          |
|                            +--+----+          |
|                               |               |
|  +----------------------------+--+---------+  |
|  |                            |            |  |
|  |          +virbr0 ----------+--+         |  |
|  |          |(192.168.122.1)     |         |  |
|  |          +---------+----------+         |  |
|  |                    |                    |  |
|  |   +-ESXi Host------+---------------+    |  |
|  |   |    (192.168.122.252(DHCP))     |    |  |
|  |   +--------------------------------+    |  |
|  |                                         |  |
|  +Virtual Network--------------------------+  |
|   (192.168.122.0/24)                          |
+-----------------------------------------------+

上の図のように、ホストマシン(Arch-Machine)の中にLinuxの標準スイッチを設定して、

その下に、VMとしてESXiホストを実装しております。

実装環境にて、NICが複数ありますが、実はマシンを新調したばかりでしてNICを遊ばせてしまっています..

今回はenp4s0のみが登場します。

Preparation - 前準備

まずは、自分の環境でKVNによる仮想化を実行できるかを調査しましょう。

$ LC_ALL=C lscpu | grep Virtualization

または、

$ grep -E --color=auto 'vmx|svm|0xc0f' /proc/cpuinfo

各々、環境にもよりますが下記のように、仮想化を行える旨で回答が来ればヨシっ!

$ LC_ALL=C lscpu | grep Virtualization
Virtualization:                  AMD-V
#AMDなら"AMD-V",Intelなら"VT-x"

$ grep -E --color=auto 'vmx|svm|0xc0f' /proc/cpuinfo
#AMDなら"svm" Intelなら"vmx"が出力されます。
#今回は長いので省略

次に、必要なパッケージのインストール

$ pacman -S qemu virt-manager
#qemu -> KVMで仮想マシンを動かす上でハードウェアをエミュレートしてくれる
#virt-manager -> KVMのGUIフロントエンド(Linuxのデスクトップ環境なので便利)

ESXiでVMを起動するための設定、いわゆる「VM on VM」を実現する設定もここで、

$ vim /etc/modprobe.d/kvm.conf
options kvm_amd nested=1
#options kvm_intel nested=1  ---> intelならこっち
#↑今回はAMDなので...

機能が有効になっているかを確認。

$ systool -m kvm_amd -v | grep nested #intelなら"systool -m kvm_intel -v | grep nested"
    nested              = "1"
    #nested                = "Y"でもOK

Run - 実行

実際に動かす際は、ESXiのインストールファイルを公式から持ってきて、"virt-install"を下記のように実行。

※あくまで、一例です。

$ virt-install \
--name esxi70 \
--ram 8000 \
--disk path=/var/lib/libvirt/images/esxi70.img,size=20,bus=sata \
--cpu host-passthrough \
--vcpus=4 \
--os-type linux \
--os-variant=virtio26 \
--network bridge=virbr0,model=e1000e \
--graphics spice,listen=0.0.0.0,password=password \
--video qxl \
--cdrom /var/lib/libvirt/images/VMware-VMvisor-Installer-7.0b-16324942.x86_64.iso \
--features kvm_hidden=on \
--machine q35

NICの問題で、"e1000"で実行していましたが、それではESXiのインストール画面でひたすらエラーが出るので、

"e1000e"に変更!、同じintel-NICなのになぜ...?

root以外のユーザが実行するか否かの設定等もありましたが今回は割愛。

Result - 結果

esxi_on_kvm
esxi on kvm

できたわね!

After Word

以上です!

今回は、そりゃそうだみたいな感じの実装でしたが、これをもう少しNW周りをゴリゴリにして、

ESXi on KVMでガチLAB環境を作りたいものです。

APIとかも作るかも...

それでは、サラダバー!!

Reference - 参考

QEMU - ArchWiki

KVM - ArchWiki

KVM とは - Linux 仮想化の仕組み | Red Hat

minecraftサーバの実装を自動化しちゃいたい♡

Introduction - 自動化をしちゃいたい

お疲れ様です。皆様、最近のバズワード「自動化」をご存知でしょうか?

まぁ、自動化と言っても自分は特にIaC(Infrastructure as Code)というものに興味津々でございます。これでもインフラエンジニアの端くれらしいので...

で、話は少し逸れて先週ふと...「マイクラしてぇぇぇ(ゲスボイス)」と思い立ったのです。

イクラを普通にインストールして遊ぶのもすごく楽しいですが、せっかくだしAWS上にインスタンスを用意して、マイクラサーバをデプロイして、みんなで遊んじゃいたいということです。

今回は、それをインフラ周りの構築からマイクラサーバのデプロイ、起動までを自動化してみたら勉強にもなるかしらと思い、キーボードを叩くことにしました。

まぁ、自動化ツールは自分の野望にも必要になってくるものではあるので、少しずつ慣れていければと思います。(まぁ、自動化ツールはあくまでツールであって、「構築・運用における銀の弾丸になりうる」とまでは思っていないというのが私の考えではありますが...)

環境のご説明

前置きが長くなりましたね...

環境のご説明をいたします。

  • 環境
    • ホスト環境
      • OS:Linux
      • 利用したツール:Ansible、Terraform
    • サーバ側の環境
      • 利用クラウドプロバイダ:AWS
      • 利用したサービス:EC2、VPC
      • OS:AmazonLinux 2
      • 公開しているポート番号:80、443、22、25565
      • インストールパッケージ:java、screen (最新のものとなります)

コードのご紹介

書いたものについて

書いたコードはここに置いておきます。

利用方法とかは、ちゃんと README書くので許して...

で、今回は主に初めて利用するAnsibleのコードについてご紹介していきたいと思います。

Ansibleについては、Google先生に聞くか、某大佐の本を購入するか、モクモクの会に出てみるか、調べる方法はいくらでもあるので、割愛。

少し言うなら、エンジニアの皆さんがここ数年、生暖かい目線を送って盛り上げてる自動化ツールかなというのが自分の中での印象です。

んで、最初にファイルのツリーをご開帳。

  • ファイルのツリー
.
├── build_infra.yml
├── build_minecraft.yml
├── inventory
│   ├── aws_ec2.yml
│   └── inventory_file
├── key
│   └── mykey.pem
└── roles
    ├── make_games
    │   ├── files
    │   │   └── eula.txt
    │   └── tasks
    │       └── main.yml
    └── make_infra
        ├── infra_destroy.yml
        ├── tasks
        │   └── main.yml
        └── terraform
            ├── environment
            │   ├── instance
            │   │   ├── aws_ec2.tf
            │   │   ├── output.tf
            │   │   └── variables.tf
            │   ├── main.tf
            │   ├── network
            │   │   ├── aws_securitygroup.tf
            │   │   ├── aws_vpc.tf
            │   │   ├── output.tf
            │   │   └── variables.tf
            │   └── variables.tf
            ├── main.tf
            ├── terraform.tfstate
            ├── terraform.tfstate.backup
            ├── terraform.tfvars
            └── variables.tf

リソースの展開について

Ansibleについて文章書きたいって言ってるのに、半分以上がTerrforomなのは... ?

とまぁ、Terraformのご説明を簡単にすると、インフラストラクチャプロバイダなどのリソース設定をコード化できてしまうというものです。

今回は、わざと混合状態で挑むこととしました。(AWSのリソース設定をAnsibleでイチから書くのがめんどくさかったというのは内緒♡)

Terraformは主に、AWSの各リソースのデプロイに利用しています。

ここで、デプロイの準備を解説させていただくと、EC2とVPCの設定を各ディレクトリに配置しております。

実行する上で、./roles/make_infra/terraform/terraform.tfvarsAWSで取得したIAMユーザのアクセスキーとシークレットキーを入力してください。記入後、下記コマンドを実行。

#編集してください。"./roles/make_infra/terraform/terraform.tfvars"
/*provider-settings*/
aws_access_key = "XXXXXXXXXXXXXXXXXXXX"
aws_secret_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
#Terraformの初期化
terraform init

これで、Terraform側が必要な情報を取得してくれます。

./roles/make_infra/terraform/下にterraform.tfstateterraform.tfstate.backup.terraform/が生成されるかと思います。

Terraform側はこれでOK

一応、以下のようなリソースを展開する準備ができています。

f:id:pabotesu:20200912043439j:plain

ネットワークのアドレスやインスタンスのタイプに関しては、./roles/make_infra/terraform/environment/variables.tfで設定できます。(※プロジェクトネームはいろいろ連動しているので、変えないのが良きかも)

下に、プライベートサブネットができるのは過去に作ったものの流用なので、見逃してください...

#./roles/make_infra/terraform/environment/variables.tf

/*aws-name-settings*/
variable "project-name" {
  default     = "minecraft"
}

/*aws-network-settings*/
variable "vpc-cidr" {
  default     = "192.168.32.0/24"
}

variable "az" {
  default     = ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"]
}


variable "public-subnets" {
  default     = ["192.168.32.0/25"]
}

variable "private-subnets" {
  default     = ["192.168.32.128/25"]
}

/*aws-instance-settings*/
variable "ec2-config" {
      type = map(string)
      default = {
          ami = "ami-0ff21806645c5e492"
          instance_type = "t2.small"
          instance_key = "mykey"
          root_ebs_type = "gp2"
          root_ebs_size = "8"
      }
  }

Ansibleの利用

今回、Ansibleはrolesという機能を利用していきたいと思います。

rolesとは、

ロールは、既知のファイル構造に基づいて特定の vars_files、タスク、およびハンドラーを自動的に読み込む方法です。 ロールでコンテンツをグループ化すると、他のユーザーとのロールの共有が容易になります。

参考:ロール - Ansible Documentation

と、言う感じで、つらつらPlaybookを書くよりも、より可読性や共有性をアップできるということですね。

上から、./build_infra.yml./build_minecraft.ymlは各ロール内のtasksのymlファイルを実行しています。

./build_infra.ymlは上のTerraformタスクを実行していて、./build_minecraft.ymlは展開されたインスタンスに対してminecraftの実装をしています。また、ここのversion変数でminecraftのバージョンを指定できます。

#./build_infra.yml
---
- name: build infra   
  hosts: localhost
  become: false
  roles:
    - make_infra
#./build_minecraft.yml
---
- name: build minecraft 
  hosts: target
  become: yes
  vars:
    version: "1.12.2"
    password: passw0rd
  roles:
    - make_games

次にinventoryディレクトリにある、./inventory/aws_ec2.ymlは展開されたEC2インスタンスの情報を引っ張ってきてくれています。

ここで、./inventory/aws_ec2.ymlaws_access_key_idaws_secret_access_keyは、先程Terraformにも記入したアクセスキー、シークレットキーと同じテナントに紐付いているものとなります。(同じもので良いですよ)

./inventory/inventory_fileインスタンスと22番接続する際に必要な情報が入ってます。

./inventory/inventory_file内のansible_ssh_private_key_fileは接続に必要なキーペアの名前を記入の上、ファイルを./key/ディレクトリ下に保存してください。

#./inventory/aws_ec2.yml
plugin: aws_ec2

aws_access_key_id: XXXXXXXXXXXXXXXXXXXX
aws_secret_access_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
aws_security_token:

regions:
 - ap-northeast-1
strict: no
keyed_groups:
 - key: tags.Name
   prefix: tag_Name_
   separator: ""

groups:
 target: "tags.Name is match('^minecraft-')"

compose:
  ansible_host: global_ip_address
  
#./inventory/inventory_file
[target:vars]
ansible_port=22
ansible_user=ec2-user
ansible_ssh_private_key_file=key/mykey.pem

一応ここまでで実行はできちゃいますが、もう少しだけ続くんじゃ...

ここでは、各タスクについてご説明します。

./roles/make_infra/tasks/main.yml は単純にTerraformを実行しています。正直、$ terraform applyとなんら変わりません。ただ、今回はAnsibleからTerraformを実行してみたいという試みなのです。

実際、TerraformからAnsibleを動かすか、AnsibleからTerraformを動かすかは状況に応じて異なるかと思います。

仮に、今回の件が業務に関わるなら、まずAnsibleで要件のOS、必要なパッケージを携えたイメージをローカル環境で作成して、それをAWS 上にAMIとしてアップロードする。(ここまで、自動化)

その後そのAMIを利用してTerraformを実行する。

という手法を取るかと思います。(これも臨機応変

で、その下に120秒の待機があるのは、単純にインスタンスの起動を「ちょっと待ってー」という意味です。

  # ./roles/make_infra/tasks/main.yml
  - name: make infra terraform
    terraform:
      project_path: 'roles/make_infra/terraform'
      state: present
  - name: pause
    pause:
      seconds: 120
    register: result
  - name: show result
    debug:
      var: result

次に、minecraftサーバの実装です。

ファイルは、./roles/make_games/tasks/main.ymlになります。

しかし...まぁ...

ここが一番書くことがないですね...

ちなみに、ローカルからコピーしてきている、eula.txtというファイルとは、マイクラサーバを起動する際に、「承諾する」という意味のファイルになります。(ファイルは承諾済み)

なので、これを実行したとき、すでに「承諾している」ということですね♡(ゲス顔)

ついでに、マイクラサーバのjarファイルをダウロードしてきているS3には最新版はなかったのであしからず...

# ./roles/make_games/tasks/main.yml
- name: install java
  yum: name=java state=installed

- name: install screen
  yum: name=screen state=installed

- name: add a minecraft user
  user: name=minecraft password={{password}} state=present

- name: settings sudo user minecraft
  lineinfile: "dest=/etc/sudoers backup=yes state=present regexp='^minecraft' line='minecraft ALL=(ALL) NOPASSWD: ALL'"

- name: make minecraft directory
  file: path=/opt/minecraft state=directory owner=minecraft group=minecraft mode=0755

- name: get minecraft
  get_url: url="https://s3.amazonaws.com/Minecraft.Download/versions/{{version}}/minecraft_server.{{version}}.jar" dest=/opt/minecraft

- name: create symbolic link
  file: src=/opt/minecraft/minecraft_server.{{version}}.jar dest=/opt/minecraft/server.jar state=link

- name: copy eula.txt
  copy: src=eula.txt dest=/opt/minecraft/eula.txt

- name: start minecraft
  shell: /usr/bin/java -Xmx1024M -Xms1024M -jar /opt/minecraft/server.jar nogui &
  args:
    chdir: /opt/minecraft/
  async: 5
  poll: 0

参考というか、ほぼほぼパクリ

実行

実行しちゃう

以上のように実装したコードを実行していきます。

基本的には、プロジェクトのルートディレクトリで実行。

# ./ で実行
./ $ ansible-playbook build_infra.yml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [build infra] *******************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [make_infra : make infra terraform] *********************************************************************************************************************************************************************************************************************************************
changed: [localhost]

TASK [make_infra : pause] ************************************************************************************************************************************************************************************************************************************************************
Pausing for 120 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)
ok: [localhost]

TASK [make_infra : show result] ******************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "result": {
        "changed": false,
        "delta": 120,
        "echo": true,
        "failed": false,
        "rc": 0,
        "start": "2020-09-12 03:54:11.657614",
        "stderr": "",
        "stdout": "Paused for 120.0 seconds",
        "stop": "2020-09-12 03:56:11.657858",
        "user_input": ""
    }
}

PLAY RECAP ***************************************************************************************************************************************************************************************************************************************************************************
localhost                  : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

一応、インスタンスの確認。

./ $ ansible-inventory -i inventory --graph
@all:
  |--@aws_ec2:
  |  |--ec2-xx-xx-xx-xx9.ap-northeast-1.compute.amazonaws.com
  |--@tag_Name_minecraft_public_ap_northeast_1a:
  |  |--ec2-xx-xx-xx-xx9.ap-northeast-1.compute.amazonaws.com
  |--@target:
  |  |--ec2-xx-xx-xx-xx9.ap-northeast-1.compute.amazonaws.com
  |--@ungrouped:

インスタンスいますね。

最後に、マイクラサーバのサービス起動まで!

./ $ ansible-playbook -i inventory build_minecraft.yml

PLAY [build minecraft] ***************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************************************************************************************************************************************
The authenticity of host 'ec2-xx-xx-xx-xx9.ap-northeast-1.compute.amazonaws.com (xx.xx.xx.xx9)' can't be established.
ECDSA key fingerprint is SHA256:4zFNS8SaLRQtm08Hs87FOBqN1XPh2vEi3OPk9AWQDt0.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
[WARNING]: Platform linux on host ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
ok: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com]

TASK [make_games : install java] *****************************************************************************************************************************************************************************************************************************************************
changed: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com]

TASK [make_games : install screen] ***************************************************************************************************************************************************************************************************************************************************
ok: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com]

TASK [make_games : add a minecraft user] *********************************************************************************************************************************************************************************************************************************************
[WARNING]: The input password appears not to have been hashed. The 'password' argument must be encrypted for this module to work properly.
changed: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com]

TASK [make_games : settings sudo user minecraft] *************************************************************************************************************************************************************************************************************************************
changed: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com]

TASK [make_games : make minecraft directory] *****************************************************************************************************************************************************************************************************************************************
changed: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com]

TASK [make_games : get minecraft] ****************************************************************************************************************************************************************************************************************************************************
changed: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com]

TASK [make_games : create symbolic link] *********************************************************************************************************************************************************************************************************************************************
changed: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com]

TASK [make_games : copy eula.txt] ****************************************************************************************************************************************************************************************************************************************************
changed: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com]

TASK [make_games : start minecraft] **************************************************************************************************************************************************************************************************************************************************
changed: [ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com]

PLAY RECAP ***************************************************************************************************************************************************************************************************************************************************************************
ec2-18-183-143-139.ap-northeast-1.compute.amazonaws.com : ok=10   changed=8    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

はい、できました。

実行結果

awsインスタンスを確認して、

f:id:pabotesu:20200912043312p:plain

イクラ接続♡

f:id:pabotesu:20200912043329p:plain

f:id:pabotesu:20200912043353p:plain

できたわね!

ちなみに、インスタンスごと葬り去りたいときは...

# /roles/make_infra/
$ ansible-playbook infra_destroy.yml

で、お願いします。

あくまでAnsibleは運用の技術なので、全消しはあまり良くないかなーってことでひっそりと...(思想に支配されすぎてもだめだけどね)

Afterword

はい、お疲れ様です。

無事実装できましたね♪

しかし、まだまだ爪のあまい部分があるかと思います。(warningめっちゃ出てるし...)

これを読んで、おかしいと思うことやよくないわねって思うことは,

がしがし、Twitterにでもご指摘ください。(コメントでも良いですが) ※突然のTwitter宣伝乙

My_Linux_Environment [on Arch Linux](GUI編)

Introduction - デスクトップ環境を求めて...

だいぶ日が空きました...

その間に、メイン機のOSを再インストールしてたり、LightDMさんがグラフィックドライバーより早く起動してしまうという現象に悩まされたりしましたが、なんとか元気に生きてます...

今回はいい加減GUI環境の原版を設けようと思いまして...その記録です。

  • 環境

    • OS : Linux

    • ディストロ:Arch Linux

    • カラースキーム:tomowrrow night 参考

    • インストールしたパッケージの皆さん

      • ウィンドウシステム:X11

      • ディスプレイマネージャ:Light DM

      • ウィンドウマネージャ:i3-wm(gaps)

      • ステータスバー:i3-blocks

      • 日本語入力:mozc

      • ターミナル:xterm

      • エディタ:vim , vs-code

        とりあえず、これくらい...(追記あるかも...♡)

インストール

1.マウスで操作ができるまで

OSのインストール直後と仮定して、文を続けていきます。

まずはrootでログイン後、ユーザーを作りましょう。

# useradd -m -g users -G wheel -s /bin/bash ユーザー名
# passwd ユーザー名

​ 以下で、sudoを使えるようにしてあげて、

# visudo

...
## Uncomment to allow members of group wheel to execute any command
%wheel ALL=(ALL) ALL ←先頭の#を削除する。
...

時刻合わせをしましょう。確認もついでに...

# timedatectl set-ntp true

# vim /etc/systemd/timesyncd.conf

...
[Time]
NTP=ntp1.jst.mfeed.ad.jp ntp2.jst.mfeed.ad.jp ntp3.jst.mfeed.ad.jp
FallbackNTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org
...
systemctl -l status systemd-timesyncd.service
● systemd-timesyncd.service - Network Time Synchronization
     Loaded: loaded (/usr/lib/systemd/system/systemd-timesyncd.service; enabled; vendor p>
     Active: active (running) since Wed 2020-09-02 18:25:01 JST; 2h 9min ago
       Docs: man:systsystemctl -l status systemd-timesyncd.service
● systemd-timesyncd.service - Network Time Synchronization
     Loaded: loaded (/usr/lib/systemd/system/systemd-timesyncd.service; enabled; vendor p>
     Active: active (running) since Wed 2020-09-02 18:25:01 JST; 2h 9min ago
       Docs: man:systemd-timesyncd.service(8)
   Main PID: 488 (systemd-timesyn)
     Status: "Initial synchronization to time server 144.76.0.164:123 (2.arch.pool.ntp.or>
      Tasks: 2 (limit: 38432)
     Memory: 3.6M
     CGroup: /system.slice/systemd-timesyncd.service
             └─488 /usr/lib/systemd/systemd-timesyncd

Sep 02 18:25:00 arch-machine systemd[1]: Starting Network Time Synchronization...
Sep 02 18:25:01 arch-machine systemd[1]: Started Network Time Synchronization.
Sep 02 18:25:29 arch-machine systemd-timesyncd[488]: Initial synchronization to time serv>
lines 1-14/14 (END)emd-timesyncd.service(8)
   Main PID: 488 (systemd-timesyn)
     Status: "Initial synchronization to time server 144.76.0.164:123 (2.arch.pool.ntp.or>
      Tasks: 2 (limit: 38432)
     Memory: 3.6M
     CGroup: /system.slice/systemd-timesyncd.service
             └─488 /usr/lib/systemd/systemd-timesyncd

Sep 02 18:25:00 arch-machine systemd[1]: Starting Network Time Synchronization...
Sep 02 18:25:01 arch-machine systemd[1]: Started Network Time Synchronization.
Sep 02 18:25:29 arch-machine systemd-timesyncd[488]: Initial synchronization to time serv>
lines 1-14/14 (END)

X Window System環境を導入しましょう

# pacman -S xorg-server xorg-apps xorg-xinit xorg-xclock xterm xorg-twm

以下でグラフィックドライバーを確認して

lspci | grep VGA

インストールしましょう。(選択しましょう)

# pacman -S xf86-video-intel

だったり

# pacman -S nvidia

だったりします。(人によりけりです)

終わったら、利用するユーザにログインし直してXサービスの確認。

$ startx

で確認後、ネットワーク周りを見とくと良いかも

ここでは深く解説はしませんが、ラップトップだとdhcpcdは不便が多いのでNetworkManagerに頼ってしまいます。

dhcpcdNetworkManagerは衝突するので、どちらかをdisableにしましょう...

次にi3-wmをインストールします。

今回は、ウィンドウとウィンドウの間が空いてて、かっちょいいi3-gapsをチョイス。

一緒にLight Display Manger

# pacman -S lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings

上記は主にLight Display Manger本体とその周辺ツールのインストール。

で、下記の通りi3-wm(i3-gaps)と愉快な仲間たちもインストール。

# pacman -S i3-gaps i3status i3blocks

で、その他のツールもいっぺんに!(お好みで♡)

# pacman -S rofi dunst lxappearance ttf-dejavu otf-ipafont ranger xclip imagemagick peek feh xterm

で、ここで上記のツールを簡単に解説

  • rofi - マルチスイッチャー(osxSpotlight的なもの)
  • dunst - 通知デーモン
  • lxappearance - GTK+ アプリケーションのテーマ、アイコン、フォントを設定するためのユーティリティ
  • ttf-dejavu - Dejavuフォント(unicodeのラージフォント)
  • otf-ipafont - 日本語フォント
  • ranger - ターミナル内で利用できる、ファイルマネージャ(ありえん便利)
  • xclip - クリップボードツール
  • imagemagick - 画像処理のツール(スクショで使います)
  • peek - gifで撮影できちゃうスクリーンキャプチャ
  • feh - 軽量な画像表示ツール
  • xterm - ターミナル

で、ここで自分が最近ハマったとこ。

なぜか、ディスプレイマネージャを自動起動設定したあと、機器を再起動するとLight-DMが起動しなくなってしまいました。

くまった...くまった...

これは、グラフィックドライバーより先にLight-DMが起動してしまうのが原因です。

下記のように/etc/lightdm/lightdm.confを編集します

さすが、Archwiki...

[LightDM]
logind-check-graphical=true

参考

ディスプレイマネージャーの自動起動設定をしましょう

# systemctl enable lightdm

以上で、とりあえず終了。

再起動の前に、あとで紹介する設定ファイルをこのタイミングで加えても良いでしょう...

終わったら...reboot!!

2.設定ファイル

設定ファイルは以下においておきます。 かれこれ、2年ぐらいツギハギしてるかも...

設定ファイル

i3-gapsの設定ファイルは一応晒しておきます...

~/.config/i3/config
----------------------------------------------------------------------------------------------------------------------------
# This file has been auto-generated by i3-config-wizard(1).
# It will not be overwritten, so edit it as you like.
#
# Should you change your keyboard layout some time, delete
# this file and re-run i3-config-wizard(1).
#

# i3 config file (v4)
#
# Please see https://i3wm.org/docs/userguide.html for a complete reference!

set $mod Mod1

# Font for window titles. Will also be used by the bar unless a different font
# is used in the bar {} block below.
#font pango:monospace 8
font pango:Dejavu Sans,IPAPGothic 9

# This font is widely installed, provides lots of unicode glyphs, right-to-left
# text rendering and scalability on retina/hidpi displays (thanks to pango).
#font pango:DejaVu Sans Mono 8

# The combination of xss-lock, nm-applet and pactl is a popular choice, so
# they are included here as an example. Modify as you see fit.

# xss-lock grabs a logind suspend inhibit lock and will use i3lock to lock the
# screen before suspend. Use loginctl lock-session to lock your screen.
exec --no-startup-id xss-lock --transfer-sleep-lock -- i3lock --nofork

# NetworkManager is the most popular way to manage wireless networks on Linux,
# and nm-applet is a desktop environment-independent system tray GUI for it.
exec --no-startup-id nm-applet

# Use pactl to adjust volume in PulseAudio.
set $refresh_i3status killall -SIGUSR1 i3status
bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +10% && $refresh_i3status
bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -10% && $refresh_i3status
bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle && $refresh_i3status
bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle && $refresh_i3status

# Use Mouse+$mod to drag floating windows to their wanted position
floating_modifier $mod

# start a terminal
#bindsym $mod+Return exec i3-sensible-terminal
bindsym $mod+Return exec xterm

# kill focused window
bindsym $mod+Shift+q kill

# start dmenu (a program launcher)
#bindsym $mod+d exec dmenu_run
bindsym $mod+d exec rofi -show run
# There also is the (new) i3-dmenu-desktop which only displays applications
# shipping a .desktop file. It is a wrapper around dmenu, so you need that
# installed.
# bindsym $mod+d exec --no-startup-id i3-dmenu-desktop

# change focus
bindsym $mod+j focus left
bindsym $mod+k focus down
bindsym $mod+l focus up
bindsym $mod+semicolon focus right

# alternatively, you can use the cursor keys:
bindsym $mod+Left focus left
bindsym $mod+Down focus down
bindsym $mod+Up focus up
bindsym $mod+Right focus right

# move focused window
bindsym $mod+Shift+j move left
bindsym $mod+Shift+k move down
bindsym $mod+Shift+l move up
bindsym $mod+Shift+semicolon move right

# alternatively, you can use the cursor keys:
bindsym $mod+Shift+Left move left
bindsym $mod+Shift+Down move down
bindsym $mod+Shift+Up move up
bindsym $mod+Shift+Right move right

# split in horizontal orientation
bindsym $mod+h split h

# split in vertical orientation
bindsym $mod+v split v

# enter fullscreen mode for the focused container
bindsym $mod+f fullscreen toggle

# change container layout (stacked, tabbed, toggle split)
bindsym $mod+s layout stacking
bindsym $mod+w layout tabbed
bindsym $mod+e layout toggle split

# toggle tiling / floating
bindsym $mod+Shift+space floating toggle

# change focus between tiling / floating windows
bindsym $mod+space focus mode_toggle

# focus the parent container
bindsym $mod+a focus parent

# focus the child container
#bindsym $mod+d focus child

# Define names for default workspaces for which we configure key bindings later on.
# We use variables to avoid repeating the names in multiple places.
set $ws1 "1"
set $ws2 "2"
set $ws3 "3"
set $ws4 "4"
set $ws5 "5"
set $ws6 "6"
set $ws7 "7"
set $ws8 "8"
set $ws9 "9"
set $ws10 "10"

# switch to workspace
bindsym $mod+1 workspace number $ws1
bindsym $mod+2 workspace number $ws2
bindsym $mod+3 workspace number $ws3
bindsym $mod+4 workspace number $ws4
bindsym $mod+5 workspace number $ws5
bindsym $mod+6 workspace number $ws6
bindsym $mod+7 workspace number $ws7
bindsym $mod+8 workspace number $ws8
bindsym $mod+9 workspace number $ws9
bindsym $mod+0 workspace number $ws10

# move focused container to workspace
bindsym $mod+Shift+1 move container to workspace number $ws1
bindsym $mod+Shift+2 move container to workspace number $ws2
bindsym $mod+Shift+3 move container to workspace number $ws3
bindsym $mod+Shift+4 move container to workspace number $ws4
bindsym $mod+Shift+5 move container to workspace number $ws5
bindsym $mod+Shift+6 move container to workspace number $ws6
bindsym $mod+Shift+7 move container to workspace number $ws7
bindsym $mod+Shift+8 move container to workspace number $ws8
bindsym $mod+Shift+9 move container to workspace number $ws9
bindsym $mod+Shift+0 move container to workspace number $ws10

# reload the configuration file
bindsym $mod+Shift+c reload
# restart i3 inplace (preserves your layout/session, can be used to upgrade i3)
bindsym $mod+Shift+r restart
# exit i3 (logs you out of your X session)
bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -B 'Yes, exit i3' 'i3-msg exit'"

# resize window (you can also use the mouse for that)
mode "resize" {
        # These bindings trigger as soon as you enter the resize mode

        # Pressing left will shrink the window’s width.
        # Pressing right will grow the window’s width.
        # Pressing up will shrink the window’s height.
        # Pressing down will grow the window’s height.
        bindsym j resize shrink width 10 px or 10 ppt
        bindsym k resize grow height 10 px or 10 ppt
        bindsym l resize shrink height 10 px or 10 ppt
        bindsym semicolon resize grow width 10 px or 10 ppt

        # same bindings, but for the arrow keys
        bindsym Left resize shrink width 10 px or 10 ppt
        bindsym Down resize grow height 10 px or 10 ppt
        bindsym Up resize shrink height 10 px or 10 ppt
        bindsym Right resize grow width 10 px or 10 ppt

        # back to normal: Enter or Escape or $mod+r
        bindsym Return mode "default"
        bindsym Escape mode "default"
        bindsym $mod+r mode "default"
}

bindsym $mod+r mode "resize"

# Start i3bar to display a workspace bar (plus the system information i3status
# finds out, if available)
#bar {
#        status_command i3status
#}



set $background #1d1f21
set $foreground #c5c8c6
set $secondary #5c5c5c
set $black #373b41
set $red #cc6666
set $green #b5bd68
set $yellow #f0c674
set $blue #81a2be
set $magenta #b294bb
set $cyan #8abeb7
set $white #c5c8c6

bar {
    status_command i3blocks
    font pango:Dejavu Sans Mono 13px
    mode dock
    position top
    separator_symbol ""
    workspace_buttons yes
    strip_workspace_numbers yes
    binding_mode_indicator yes
    tray_output none
    tray_padding 0
    colors {
        background $background
        focused_background $background
        statusline $blue
        focused_statusline $blue
        separator $secondary
        focused_separator $secondary
        focused_workspace  $foreground $background $foreground
        active_workspace $background $background $foreground
        inactive_workspace $background $background $foreground
        urgent_workspace   $foreground $foreground $background
        binding_mode       $foreground $foreground $background
    }
}


#have gaps
gaps inner 22

#no_border
for_window [class="^.*"] border pixel 1

#run_fcitx
exec --no-startup-id fcitx

#wallpaper
exec --no-startup-id feh --bg-scale ~/Pictures/wallpaper.jpg

#Dunst
exec --no-startup-id dunst

# take a screenshot of a screen region and copy it to a clipboard
bindsym --release Shift+Print exec "~/.config/i3/scregcp.sh -s ~/Pictures/screenshots/"

# take a screenshot of a whole window and copy it to a clipboard
bindsym --release Print exec "~/.config/i3/scregcp.sh ~/Pictures/screenshots/"

#CapsLock 2 CTL
exec --no-startup-id xmodmap ~/.Xmodmap

※ "~/.config/i3/scregcp.sh"はスクショ用のスクリプトになります。

スクショ

f:id:pabotesu:20200902220614j:plain

Afterword

とまぁ...書いてみましたが、ガバガバですね...

海外の方とかはめちゃんこかっこよくしてたり、おしゃれだったり

泣きそうですね...

My_Linux_Environment [on Arch Linux](インストール編)

Introduction - ほんの出来心だったんです... -

最近、ラップトップのLinux環境がぶっ飛びました...

(自分がpamいじってrootの権限持ってかれたのが原因です...)

最悪です...(僕はクソ野郎)

まぁ...ぶっ飛んだものはしょうがないので、(pamの修正しても良いのですが、めんどくさいので...)

心機一転!!自分の環境を更新しようと思います。

ついでの記録。

ほんとはAnsibleとかでインストールすらも自動化したいですが、自分の力量と根気がゴミクズなので、普通に手動インストール。

  • 環境

    • ハードウェア:ThinkPad X280 (2018年購入)

      • CPU:intel Core i5-8250U(1.6GHz 6MB,4c8t)
      • RAM:8GB
      • ROM:SSD 512GB(特にメーカー名は書きません)
    • Linuxのディストロ:Arch Linux(ver. 5.4.15)

      • GUI環境:Light DM でi3-wm gaps

      • 他は適当に...

      • エディタはvscodeを使いますがここでは割愛。

      • ドライバ系も基本的には割愛。

あとはご想像におまかせします。

Procedure - ほとんど脳死です... -

1 . インストールメディアの作成、起動

適当にここからjaist.ac.jpなり、ftp.tsukuba.wide.ad.jpのものをダウンロードして、usbに焼きます。

biosのsecurebootはdisableにしておいて、usbぶっ刺して起動!

今回はUEFIモードで設定します。

以下が出力されるので、一番上の「Arch Linux archiso x84_64 UEFI CD」を選択。

Arch Linux archiso x84_64 UEFI CD
UEFI Shell x86_64 v1
UEFI Shell x86_64 v2
EFI Default Loader
Reboot Into Firmware Interface

コマンドプロンプトが起動するので、

# ls /sys/firmware/

apci dmi efi memmap

で「efi」があることを確認。

UEFIモードのインストールが確認できます。

ここで、jisキーボードを使う場合は以下のコマンドで配列を適用

# loadkeys jp106

あと、インターネットに接続できることを確認してください。

# ping -c3 google.com

2 . パーティションの設定

インストール先のディスクを確認しましょう。

# lsblk | grep -v "rom\|loop\|airoot"

NAME            MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda                     8:0    0    512G  0 disk
└─sda1            8:1    0    512G  0 part

ぼくは、「sda」ですね

こんなかんじでインストール先ディスク「sdX」を確認してください。

このとき、もしディスクにデータが残ってたら、消してしまいましょう。

。。。(僕の場合はめんどくさいので...)

# sgdisk --zap-all /dev/sdX

ここで今回は他のOSとの共存は考えてないです。

windowsは基本的にデスクトップで使うぐらいなので...(あとめんどい...)

パーティション フォーマット 用途 マウントポイント 容量
/dev/sda1 FAT32 UEFI System Partition /boot 512MB
/dev/sda2 swap swap領域 16GB
/dev/sda3 XFS / / 64GB
/dev/sda4 XFS ~/ ~/ REST

swapについててですが今回は脳死でRAM*2です。いろいろ意見はありますが基本的にめんどくさがりなので...

2GB以上だとハイバーネート的にswapがいらないようですね...

こんど検討しますね(追記あるかも...)

参考:パーティショニング - ArchWiki

あと、フォーマットのXFSですが色んな人からいろんなことを言われますが、基本今回は脳死です...

で、以下のようにパーティション割って

# gdisk /dev/sdX

GPT fdisk (gdisk) version 0.8.6

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

Creating new GPT entries.

Command (? for help): o  (oで、新しいパーティションテーブルを作る)
This option deletes all partitions and creates a new protective MBR.
Proceed? (Y/N): y (yで進む)

Command (? for help): n (nで、新しいパーティションを作る)
Partition number : 1
First sector: (デフォルトで2048から始まるようになっているので、何も入力せずにエンター)
Last sector: +512M
Hex code or GUID: ef00  (UEFI System partition用のパーティションなのでef00にする)

Command (? for help): n
Partition number: 2
First sector: (何も入力せずエンター)
Last sector: +16G
Hex code or GUID: 8200 (swap用は8200)

Command (? for help): n
Partition number: 3
First sector: (何も入力せずエンター)
Last sector: +64G
Hex code or GUID: (何も入力せずエンター、デフォルトが8300)

Command (? for help): n
Partition number: 4
First sector: (何も入力せずエンター)
Last sector: (何も入力せずエンターで、残りの領域すべてを使用)
Hex code or GUID: (何も入力せずエンター)

Command (? for help): w (wで、書き込みに移る)
Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed?: y (yで、書き込み実行)
OK; writing new GUID partition table (GPT) to /dev/sda.
The operation has completed successfully.

以下のように、フォーマット。

# mkfs.fat -F32 /dev/sdX1
# mkswap /dev/sdX2
# swapon /dev/sdX2
# mkfs.xfs -m crc=1 /dev/sdX3
# mkfs.xfs -m crc=1 /dev/sdX4

んで、指定のディレクトリをmkdirして、マウント。

# mount /dev/sdX3 /mnt (ルートパーティション(ここではsdX3)を、/mntにマウントする)
# mkdir /mnt/home
# mount /dev/sdX4 /mnt/home
# mkdir /mnt/boot
# mount /dev/sdX1 /mnt/boot

3 . 環境設定

以下で、tsukubaのサーバをサーバの優先度を一番上にして、

# vi /etc/pacman.d/mirrorlist

パッケージをインストール※

# pacstrap /mnt linux base base-devel cryptsetup device-mapper dhcpcd e2fsprogs inetutils jfsutils linux-firmware logrotate lvm2 man-db man-pages mdadm nano netctl perl reiserfsprogs s-nail sysfsutils texinfo usbutils vi xfsprogs

※:(baseパッケージ化に伴ってほとんどのパッケージはいらんようです。)

以下のようでよいそうです。便利ですね♡

# pacstrap /mnt base linux linux-firmware

参考:baseがパッケージ化

fstab※を生成して

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

※:(fstab〜ファイルはディスクパーティションや様々なブロックデバイス、リモートファイルをどうやってファイルシステムにマウントするかを記述します。)

参考:fstab - ArchWiki

以下で/mntの権限整理して

# arch-chroot /mnt /bin/bash

ロケールの設定しましょう。

# vi /etc/locale.gen

↑はen_US.UTF UTF-8とja_JP.UTF UTF-8コメントアウトを解除する。

ロケールを更新

# locale-gen

locale.confを生成します。※

# echo LANG=en_US.UTF-8 > /etc/locale.conf
# export LANG=en_US.UTF-8

※:X(GUI)と日本語フォントをインストールしたら、ja_JP.UTF-8に変更する。

ここで、キーマップも適用しましょう。

# vi /etc/vconsole.conf

タイムゾーンも設定。

# ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
# hwclock --systohc --utc

ホストネーム設定しちゃいましょう。

# echo 任意のホストネーム > /etc/hostname
# vi /etc/hosts

#
# /etc/hosts: static lookup table for host names
#

#  
127.0.0.1 localhost.localdomain localhost 任意のホストネーム 
::1  localhost.localdomain localhost 任意のホストネーム

# End of file

dhcpcdも自動起動しておいて、

systemctl enable dhcpcd.service

↑はNetworkManagerを衝突するので、役割を終えたら「disable」しましょう。(人の勝手)

ルートのパスワードを設定してしまいます。

# passwd

最新のパッケージがほしいので、パッケージのデータベースを更新。

# pacman -Syy

今回はintelのCPU※を使用してるので、以下で

# pacman -S intel-ucode

※:AMDなら「amd-ucode」

パッケージをマイクロコード更新したいのでインストール。

ブートローダをインストールする前準備として、、EFI System Partition を操作するための dosfstools パッケージと、.efiブータブルスタブを作成するためのefibootmgrをインストール※

# pacman -S dosfstools efibootmgr

※:EFI System Partition 〜 FAT32 でフォーマットされた物理パーティション (ディスクのメインのパーティションディスクで、LVM やソフトウェア RAID などとは異なります) でここから UEFI ファームウェアUEFI ブートローダやアプリケーションを起動します。OS とは独立したパーティションであり、UEFI ブートには必須のパーティションになります。

参考:EFI System Partition

※:.efiブータブルスタブ 〜 ブートローダではありませんブートローダとして動作するのはシステムの EFI ファームウェアそれ自体です。efibootmgrは、これを操作するためのツールです。efibootmgr を用いることで、ブートエントリを作成したり順序を変えたり削除したりすることが可能になります。

参考:efibootmgr

ここで、ブートローダをインストール

# pacman -S grub
# grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=arch_grub --recheck

/boot/EFI/bootにもブータブルスタブを作成しておく。

# mkdir /boot/EFI/boot
# cp /boot/EFI/arch_grub/grubx64.efi /boot/EFI/boot/bootx64.efi

grub.cfgを作成

# grub-mkconfig -o /boot/grub/grub.cfg

んで、環境からログアウトして、アンマウント、再起動しましょう。

# exit
# umount -R /mnt
# reboot

これで、一応Arch Linux自体のインストールは終わり。

再起動後こんな感じになれば、成功です。

Arch Linux バージョン-ARCH (tty1)
さっき設定したホスト名 login:

Afterword

とまぁ...やりましたが、書くのがめんどくさい!

どっかのタイミングででSSH入れてコピペでやるのがミスらないですね。

...GUI編に続く...かも...!

参考:

基本ここ...ほとんど丸パクリ...

「はい、僕はゴミクズです。」