稲枝の押入れ

いなえが適当なことを書いては、しまっておく場所

githubへのプロジェクト追加手順メモ

前提

この記事はプロジェクトをgithubで管理したい時の手順をメモとして残すものである。 今回はプロジェクトの作成工程については全く触れない。また、流れを記しておくことに重きを置くので詳細には立ち入らない。

また、公開鍵や秘密鍵の登録等は終わらせているものとする。

工程の列挙

新規プロジェクトの場合

既存プロジェクトの場合

整理

新規プロジェクトであっても既存プロジェクトであっても、ローカルリポジトリとリモートリポジトリを作ってそれらを紐付けるという点では変わらないので、それらの手順を見ていく

作業内容

ローカルリポジトリの作成

sourceTreeなら新規/クローンを作成する->リポジトリを作成リポジトリを作りたいディレクトリを指定すれば良い。コマンドでやる場合もgit initなんかで行けるはず

リモートリポジトリの作成

今回はgithubの使用を前提としているのでログインして右上の+マークからNew Repositoryを選択してリポジトリ名を入れたりしてCreate Repositoryを押せば終わり。

リモートリポジトリの作成自体はgit initで出来るらしい(参考 : 簡単解説】Gitリポジトリの新規作成するinitコマンドの使い方)が、githubコマンドラインから新規作成出来るのかは知識不足でわからない。

ローカルリポジトリとリモートリポジトリの紐づけ

github上で作成してsetupをしていない場合、quick setupの案内が出ているのでurlをコピーする。

sourceTreeの場合は上野ツールバーリポジトリ->リポジトリ設定を選び、開いたウィンドウのリモートタブで追加を押してパスにリモートリポジトリのurlを、名前のところに管理に使うための名前を適当に入力する

pushしてみる

適当な初期commitを済ませたら(既存プロジェクトなら不要)commitしてみる

pushしたいブランチを選んでpushしてみてうまく行けば成功

VSで警告レベルの変更項目が見つからない

ちょっとしたことだけど、10分位頭をひねっていたのでメモ。

状況

警告レベルを最大にしたかったのでプロジェクト作成時に設定しようとしたが、プロパティを見ても項目を見つけられなかった。

プロパティから設定するんじゃないっけ?と思いググったが、やはりプロジェクトプロパティから警告レベルの変更は出来るっぽい(こちら参照。ただ個人的には警告レベルを上げるならまだしも非表示にするのはやめたほうがいいと思う)。

[構成プロパティ] のカテゴリを選択し、[C/C++] のカテゴリを選択

とあるが、その[C/C++]カテゴリが見つからない

解決

あれ?と思ったけど空のプロジェクトで作ったのが原因だった(プロジェクトが[C/C++]を認識できてなかった)

プロジェクトにmain.cppみたいなプロジェクトを作成したら無事[C/C++]カテゴリがプロパティに追加されたのでC/C++->全般->警告レベルを変更して終了。

初心者がローカル上にmastodonサーバーを立てる練習をした話

目次

注意

経緯

本記事はLinuxについて「cdでディレクトリ移動できるらしい」くらいしか知らなかった初心者が恐れ多くも知る人ぞ知るおっさん幼女先輩クソ映画大好きおじさん監視のもと、shimaidonとかいう簡易イキボタンのあるmastodon(何度見ても訳わからん)の運営に参加する為に、最低限のことを出来るようになるためしごかれた教えていただいた際、出された課題を解決するまでの経過をまとめたものである。

非常に勉強になったので同じようなことをしている人がもしいたらと思い公開することにしたが、前述の通りかなりの初心者なので間違いが多い可能性があることはご容赦願いたい。また、間違いがあった場合は指摘をいただけるとありがたい。

課題の内容

今回は以下の課題を出されたのでそれを解決する事を目的としていた。

  • mastodonサーバをVM上に構築する
    • CentOS7のminimal上に構築する
    • パッケージマネージャの使用について制限を設ける
      • 原則、更新系のものにおいては以下のもの以外使用を禁止する
        • yum groupinstall "Base"
        • yum groupinstall "Development Tools"
      • 参照系のパッケージマネージャについては使用しても良い
      • Dockerのインストールに際してとそれ以降については例外的に更新系のパッケージマネージャの使用を許可する
    • webサーバはnginxを使用する
      • 初期設定終了後は基本的にssh接続をする
  • サーバ監視を入れる

チェックポイント

上記課題に対して、以下のようなチェックポイントが課されていた

  1. サーバに外部から接続できること
  2. nginxが正常に動作していること
  3. dockerが正常に導入できていること
  4. docker-composeが正常に導入できていること
  5. mastodonのトップページがみれてトゥートできること ※外部ってのはインターネット介してでなくていい(サーバ上じゃないローカルネットワーク)

概要

というわけなので本記事はざっくりいうと

  • windows上でVMを立てて
  • そこにCentOS7 minimalを立て
  • インストールマネージャに制限のある中で
  • nginxdockerをつかって
  • 外部からアクセスできるような
  • mastodonサーバを立てる 為に頑張ったといった内容になる。

環境

ホストOS

OS:Windows 7 Ultimate Service Pack 1

プロセッサ:Intel Core i7-4790 CPU @ 3.60GHz

実装メモリ: 16.0GB

システムの種類: 64ビット オペレーティングシステム

ゲストOS

今回はホストOS上にVMを立ててそこにサーバを構築する。VMを立てるのにはVirtualBoxを使用する。今回はVirtualBox グラフィカルユーザーインターフェース バージョン 5.2.6 r120293 (Qt5.6.2)を使用した。

ゲストOSとしてはCentOS-7-x86_64-Minimal-1708.isoをイメージとして使用してOSはCentOS7 Linux release 7.4.1708 (Core)を用いた。

ターミナルソフト

sshのターミナルソフトとしてはRLogin Version 2.23.1(2018/01/30)を使用した。

VM上にOSを立てる

VirtualBoxの導入

VirtualBoxのダウンロード

VirtualBox公式のダウンロードページからWindows platform packageをダウンロードする

VirtualBoxのインストール

VirtualBox-5.2.6-120293-Win.exeと言った感じの名前のファイルを実行して、インストーラに従ってインストールする。

インストールが終了したら起動する。

OSの入手

CentOSダウンロードページからMinimal ISOを選択してダウンロードする。

仮想マシンを作成する

名前とOS

上部メニューから「新規(N)」を選択し、好きな名前をつけ、「タイプ(T)」をLinuxに、「バージョン(V)」をRed Hat(64bit)にして次へを押す。名前をCentOS等にすると自動でタイプとバージョンは設定されるので基本それでいいはず。ここでは名前をCentOS7にする。

同名で作成できない

同名の仮想マシンを作成しようとすると「仮想マシンのフォルダー{仮想マシン名}を親フォルダ{仮想マシンの置かれるフォルダ名。C:/Users/***/VirtualBox VMsとか}に作成できません。 このフォルダーは既に存在し、ほかマシンに属している可能性があります」と出る。もし元の仮想マシンが既に必要ないなら、そこでVirtualBox上で「右クリック->除去」から「すべてのファイルを削除」すると新しく同名の仮想マシンを作成できるようになる。

モリーサイズ

ここでは余裕を持って8192MBメモリとする。

ハードディスク

「仮想ハードディスクを作成する」を選択して「作成」を押す。

ハードディスクのファイルタイプ

書いてある通り、他の仮想ソフトウェアで使用する必要がなければ設定はVDI(VirtualBox Disk Image)のままにして「次へ」を押す。

物理ハードディスクにあるストレージ

「可変サイズ」を選択して「次へ」を押す。

ファイルの場所とサイズ

名前はそのままでVM名とおなじになっていると思うのでそのままでいい。仮想ハードディスクは「20.00GB」にして「作成」を押すと、VMが作成される。

起動する

作成したVMをダブルクリックもしくは上部メニューの起動から起動する。「開始したい新しい仮想マシンを含むディスクのある、仮想高額ディスクか、ディスクが挿入されている物理光学ドライブを選択してください。 このディスクはコンピューターを起動することができ、仮想マシンにインストールしたいオペレーティングシステムを含んでいなければなりません。このディスクは仮想マシンをオフにした次の回に自動的に取り出されますが、必要であればデバイスメニューから取り出すこともできます」と出ていたらここでCentOS7のシステムイメージを設定する。CentOS-7-x86_64-Minimal-1708.isoと言った感じのもの。そうしたら「起動」を押してOSのインストールに進む

CentOSのインストール

Test this media & Install CentOS7を選択すると色々走った後にGUIが起動する。

言語は「日本語」を選択して次へ進む。

「システム」の「インストール先」を設定しないとインストールを開始できないが、クリックして設定画面に入ったら何もせず「完了」を押して元の画面に戻れば自動パーティションに自動で設定されるので「インストールの開始」を押して次に進む。

インストールしてるうちにrootパスワードとユーザを作成しておく。そうしたら「設定終了」を押す。

再起動しろと言われるのでそれに從う。

これでインストールは終了。

ネットにつなげる

ネットに繋がらない

$ nmcli device

でネットワークインターフェースを確認する(参考)と、

DEVICE  TYPE      STATE         CONNECTION
enp0s3  ethernet  disconnected  --

と表示されたら接続されていない。

自動起動設定をオンにする

# nmcli c mod enp0s3 connection.autoconnect yes

再起動

インターネットへの自動接続設定をしたなら、設定を反映させるためにネットワークデーモンを再起動する

$ service network restart

つながったか確認

$ nmcli device

を実行して

DEVICE  TYPE      STATE         CONNECTION
enp0s3  ethernet  connected     enp0s3

となっていたらOK。

SELinuxを永続的に無効にする

SELinuxとは

wikipediaによると

Security-Enhanced Linux (SELinux) は、アメリカ国家安全保障局 (NSA) がGPL下で提供しているLinuxカーネルに強制アクセス制御 (MAC) 機能を付加するモジュールの名称。

こいつが有効になっているとその強力なアクセス制限のせいで作業中に躓く事があるので切っておく。

有効無効を確認する

参考:SELinuxを無効化する

SELinuxが有効かを確認する

$ getenforce

を実行する。表示される内容によって現在の状態がわかる。

表示される内容 意味
enforcing SELinux機能、アクセス制御が有効
permissive SElinuxは警告を出力するが、アクセス制限は無効
disabled SElinux機能、アクセス制御が無効

永続的に無効にする

今回は永続的に無効にすることを考える。SELinuxの設定ファイルは/etc/selinux/configなので、

# vi /etc/selinux/config

でこれを開き、

SELINUX=enforcing

とある行を

SELINUX=disabled

と書き換える。設定を反映させるためにrebootコマンド等で再起動する。

sudoを使えるようにする

sudoとは?

sudoコマンドは他のユーザや他のグループの権限でコマンドを実行できるコマンド。特に指定せず実行した場合、スーパーユーザとして実行したことになる。

スーパーユーザとしてコマンドを実行したい場合、ユーザを変更出来るsuコマンドで一旦スーパーユーザになってから実行するという方法があるが、コマンド実行後また元のユーザに戻らなければならないのは煩雑だし、かといってスーパーユーザで作業をするのは危険だし…という問題があるが、こういう場合はsudoを使うと良い。

sudoがデフォルトで許可されているユーザグループに属す

CentOSではデフォルトでsudoできるグループとしてwheelグループが用意されているため、追加した一般ユーザーをwheelグループに追加し、sudoできるようにする。余談だが、Debianの場合は、sudoグループがデフォルトでsudo出来るグループとして用意されている(出典)。

# usermod -aG wheel {ユーザー名}

でサブグループを追加する。

アカウントが既にサブグループに入っているかわからなければidコマンド

$ id {ユーザ名}

とすれば確認できる。

クライアントからのssh接続での操作ができる環境を作る

参考: - Linux(CentOS7)でSSHを利用する。 - CentOS7.3でSSH接続(パスワード認証)する方法

前提

VM上からだと何かと使い勝手が悪いのでsshクライアント(ここではRLogin)を使ってゲストOSであるCentOSにアクセスするようにする。

SSHサーバーはプリインストールされているのでその先をやる。

SSHサーバ(CentOS)側の設定

SSHの設定

/etc/ssh/sshd_configを開いて

変更箇所 変更後
#PermitRootLogin yes PermitRootLogin no
#PasswordAuthentication yes PasswordAuthentication yes
#PermitEmptyPasswords no PermitEmptyPasswords no

と書き換え保存して終了する。

サービスの起動

以下のコマンドを実行してSSHのサービスを起動する

# systemctl start sshd.service

実行したら以下のコマンドでサービスが起動できているか確認する

# systemctl status sshd.service

緑の字でactive (runnning)と表示されていたらSSHのサービスが起動している。

ファイアウォールの設定

SSH用のポート(22番ポート)はMinimal ISOでも元から開放されているので、設定は不要。

もし開放されていなかったとしても、CentOS7ではsshdと同様firewalldsystemdで管理されているので

# systemctl stop firewalld.service

とすれば停止して取り敢えず接続確認は出来る。

一般ユーザの作成

先ほどrootユーザーによるリモートログインを禁止したので、リモートログインするための一般ユーザを準備する。とはいえ、既にリモートログインしたいユーザがあるのであればわざわざ追加する必要はない。

以下、一般ユーザが準備できていない場合について書く。

一般ユーザーを追加する

# useradd {ユーザー名}

追加した一般ユーザーにパスワードを設定する。

# passwd {ユーザー名}
  • New password:
  • Retype new password:

でパスワードを2回入力したら、パスワードの設定は完了。

IPアドレスの確認

$ ip a show enp0s3

IPアドレスをメモしておく

クライアント側の設定

ターミナルソフトはRLoginを使う

ホストOS側のipアドレスの確認

ホストOS(Windows)で、Windows+Rを押して出てきたウィンドウにcmdと入力してEnterを押してコマンドプロンプトを起動したら、ipconfigコマンドを実行する。

イーサネット アダプター ローカル エリア接続」みたいに書いてあるところの「IPv4 アドレス」をメモする。

VM(VirtualBox)の設定

参考:ローカルPCとVirtual Boxの仮想マシンとのネットワーク接続、どうなってる?

NATやポートフォーワードの設定をしないとゲストOSにはアクセスできないのでそれをやる。

環境設定

  1. ウィンドウ上部タブの「ファイル->環境設定」をクリックし、でてきたウィンドウの左カラムから「ネットワーク」をクリックする。
  2. 右カラムに、上に「NATネットワーク」と書かれた空のボックスがあるのでその右にある「+」のついたマーク(マウスオーバーすると、「新しいNATネットワークを追加します。」と出るところ)をクリックする。
  3. 空だったボックス内に新たに「NatNetwork」という名前のネットワークが作成されるので、それをダブルクリック、もしくは選択した状態で右の歯車の付いたマークをクリックして、編集(NATネットワーク詳細)ウィンドウを開く。
  4. ネットワーク名(N):」を好みのものに変え(今回は変更しない)、下にある「ポートフォワーディング(P)」と書かれたボタンをクリックする。
  5. また空のボックスの表示されたウィンドウが開く。上部タブの「IPv4」が選択されている事を確認し、右の「+」のついたマークをクリックする。

そうすると空のボックス内に「Rule 1」という新しいルールが追加されるので、

項目名
名前 わかり易い名前に任意に決める。ここでは「sshRule
プロトコル TCPのままにしておく
ホストIP ホストOS(Windows)のコマンドプロンプトipconfigコマンドを使って確認したアドレスを指定。今回は「192.168.2.100
ホストポート ウェルノウンポート(0~1023)を避けて指定する今回は「2022」にした
ゲストIP ゲストOS(CentOS)でip a showコマンドを実行して確認したアドレスを指定。今回は「10.0.2.15」にした
ゲストポート 22」を指定

としたらOKを押して「環境設定」は終了。

仮想マシンごとの設定

  1. 接続したい仮想マシンを選択し、上にある「設定(S)」をクリックするか、右クリックメニューから「設定(S)」を選択するとウィンドウが開くので、左カラムから「ネットワーク」をクリックする。
  2. 右カラムのタブが「アダプター1」になっているのを確認したら、「割り当て(A):」を「NATネットワーク」にする。そうすると下に「名前(N):」という項目が操作可能になるので、ここでさっき作成した「NatNetwork」を指定する。

OKを押したらこれでVM側の設定は終了なので、ターミナルソフト側の設定に移る。

ターミナルソフト(RLogin)の設定

左上の電源プラグの様なマークの「サーバー接続」をクリックすると「Server Select」ウィンドウが開くので、右のボタンから「新規(N)」をクリックする。そうするとサーバーエントリーを設定するウィンドウが開くので

|項目名|値| |:--|:--| |エントリー(上段)|任意の名前。今回はVM_CentOS7とした。| |プロトコル|sshを選択| |Server Address|ホストIPを入力。今回は「192.162.2.100」を入力| |Socket Port|VMでホストポートとして指定したポートを入力。今回は「2022」| |User Name|ユーザ名を入力。今回はinaenomaki| |Password/Phrase|ユーザのパスワードを入力| |Term|xtermを指定| |デフォルト文字セット|UTF-8を指定| 残りは空欄もしくはチェックは外しておく。

これで設定は完了。

英語に直す

ここを参考に

# localectl set-locale LANG=en_US.UTF-8

として再起動する。

[inaenomaki@localhost ~]$ localectl status
   System Locale: LANG=en_US.UTF-8
       VC Keymap: jp
      X11 Layout: jp

と英語になっている。

前準備

許可されているパッケージマネージャ

# yum groupinstall "Base"
# yum groupinstall "Development Tools"

を実行する

作業ディレクト

以下は /home/inaenomaki 下で行った

Webサーバーを立てる

nginxに必要なものを予め用意しておく

nginxとは

「nginx(えんじんえっくす)とは、ロシア人のIgor Sysoe氏によって作られたメモリ使用量の少ない高速なオープンソースのWebサーバー」だ(出典)。今回はこれを使う。

PCREの用意

ダウンロード

$ wget http://sourceforge.net/projects/pcre/files/pcre/8.36/pcre-8.36.tar.gz

展開

$ tar xvzf pcre-8.36.tar.gz

zlibの用意

ダウンロード

$ wget http://zlib.net/zlib-1.2.11.tar.gz

展開

$ tar xvzf zlib-1.2.11.tar.gz

nginxの用意

ダウンロード

$ wget http://nginx.org/download/nginx-1.7.7.tar.gz

展開

$ tar xvzf nginx-1.7.7.tar.gz

nginxのインストール

configure

構成としては

となっているので、

$ cd ~/nginx-1.7.7/

してひとつ下のディレクトリに入った後

$ ./configure --prefix=/usr/local/lib/nginx-1.7.7 --with-pcre=../pcre-8.36 --with-zlib=../zlib-1.2.11

としてソースディレクトリを指定する。

make

$ make

make install

$ sudo make install

実行ファイルのパスを通す

/usr/local/bin/がスーパユーザ・一般ユーザ共にパスが通っているので

 $ sudo ln -s /usr/local/lib/nginx-1.7.7/sbin/nginx /usr/local/bin/

としてnginxの実行ファイルへのシンボリックリンクを貼る

sudo時にもパスが通るようにする

visudosudoersを開き、

Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/lib/nginx-1.7.7/sbin/

こうしてsudoersを保存してlessでちゃんと変更されていることを確認する。

sudoで実行してみると

[inaenomaki@localhost ~]$ sudo nginx -v   
[sudo] password for inaenomaki:    
nginx version: nginx/1.7.7   

ちゃんとsudoでも実行できるようになった。

nginxをサービス化する

定義ファイルを作成する

公式サイトの提供している定義ファイルを少し変えて使う(参考)。

/etc/systemd/systemに定義ファイルを置く。

$ sudo vi /etc/systemd/system/nginx.service

として

[Unit]   
Description=The NGINX HTTP and reverse proxy server   
After=syslog.target network.target remote-fs.target nss-lookup.target   
   
[Service]   
Type=forking   
PIDFile=/usr/local/lib/nginx-1.7.7/logs/nginx.pid   
ExecStartPre=/usr/local/lib/nginx-1.7.7/sbin/nginx -t   
ExecStart=/usr/local/lib/nginx-1.7.7/sbin/nginx   
ExecReload=/bin/kill -s HUP $MAINPID   
ExecStop=/bin/kill -s QUIT $MAINPID   
PrivateTmp=true   
   
[Install]   
WantedBy=multi-user.target

とする。

Unitがサービスとして認識されたか確認する

$ sudo systemctl list-unit-files --type=service | grep nginx

nginx.serviceが表示されていれば認識されている。

サービスを有効化する

$ sudo systemctl enable nginx

実行すると

Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /etc/systemd/system/nginx.service.

と出てシンボリックが作成される。

サービスを有効化出来たか確認する

$ sudo systemctl list-unit-files --type=service | grep nginx

nginxを起動する

$ sudo systemctl start nginx

起動できたか確認する

$ sudo systemctl status nginx

Active: active (running)となっていれば大丈夫。

ポートフォワーディングを設定する

VM上ではnginxは起動したように見えるので、きちんとそこに接続できるか試す。本来ならnginxの起動しているPCのアドレスにアクセスすればそれで済むのだが、今回はゲストOS上でnginxを動かしていて、ホストOSのブラウザからnginxにアクセスして接続できるか・正常に動いているかを確認したいので、ssh接続の時と同じくポートフォーワーディングを設定する。

VirtualBoxの設定を変更する

前回と同じく、ファイル->環境設定から開いたウィンドウの左カラムでネットワークを選択し、右カラムでssh接続する時に作ったNatNetworkをダブルクリックもしくは選択してOKを押す。またウィンドウが開いたらポートフォーワードをクリックして更にウィンドウを開き、IPv4タブになっているのを確認したら、右のプラスマークの新規ポートフォワーディングルールを追加します。からルールを追加し、

項目名
名前 ルールの名前。ここではhttpRuleとした
プロトコル TCP
ホストIP ホストOSのIPアドレス。ここでは192.168.2.100
ホストポート ポートフォワーディングするホストOSのポート。ここでは8888とした
ゲストIP ゲストOSのIPアドレス。ここでは10.0.2.15
ゲストポート ゲストOSの転送先のポート。http接続をするつもりなので80を指定

としたらOKを押して閉じる。(参考:外部からVirtualBox内のサーバにアクセス)

ポート開放する

デフォルトだとfirewalldがアクセスさせてくれないのでTCPの80番ポートを開ける。

$ sudo firewall-cmd --zone=public --add-service=http --permanent

として恒久的に開く設定にし、

$ sudo firewall-cmd --reload

で設定を反映する

$ sudo firewall-cmd --list-all

serviceshttpが追加されていれば大丈夫。

接続できるか確認する

ブラウザ上からhttp://192.168.2.100:8888/と指定してアクセスする

Welcome to nginx! If you see this page, the nginx web server is successfully installed and working. Further configuration is required.

For online documentation and support please refer to nginx.org. Commercial support is available at nginx.com.

Thank you for using nginx.

と出れば上手くいっている。

PC内からアクセス確認したいのであれば

$ curl localhost:80

とすればいい。

Dockerの導入

Dockerとは?

Wikipediaによると

Docker(ドッカー)はコンテナ型の仮想化環境を提供するオープンソースソフトウェアである。

雑に読んだ感じ、物理的に1つのサーバ上に、無駄を少なく複数のアプリケーションを走らせたいという要請から考えられた概念がコンテナ型の仮想化であり、これを提供するソフトウェアがDockerという感じ。

今回はMastdonをコンテナとして扱う事を目指すのでこれを使う

古いバージョンの確認

古いバージョンのdockerが入っているとうまくいかないことがあるらしいので入っていない事を確認する。

$ yum list installed | grep docker

として何も表示されなければ問題ない。

厳密にやりたいのであれば

$ yum list installed | egrep 'docker(|-(client(|-latest)|common|latest(|-logrotate)|logrotate|selinux|engine(|-selinux)))' 

とする。(-Eオプションは拡張正規表現の使用参考)

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

$ sudo yum install -y yum-utils device-mapper-persistent-data lvm2

をして必要なパッケージをインストールする

リポジトリの追加

$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

を実行してリポジトリを追加する。

無事/etc/yum.repos.d/docker-ce.repoリポジトリが保存されれば成功。

リポジトリの更新

$ sudo yum makecache fast

ここではyumリポジトリが最新である事を確認して更新している。

Docker CEのインストール

リポジトリ(/etc/yum.repos.d/docker-ce.repo)の設定も終わったので、インストールをする。

$ sudo yum install docker-ce

Dockerを起動する

$ sudo systemctl start docker.service

としてDockerを起動する。 Active: active (running)となっていれば

正しくインストールされているか確認する

dockerが正しくインストールされているのを確認するため、hello-worldイメージを実行する。

$ sudo docker run hello-world   

上手く行けば良い感じのメッセージが表示される。

Docker Composeの導入

参考: - 複数のDockerコンテナを自動で立ち上げる構成管理ツール「Docker Compose」(Dockerの最新機能を使ってみよう:第7回) - docker-composeを使うと複数コンテナの管理が便利に - Docker Compose - Docker Compose のインストール

公式でも必要としているのでDocker Composeを入れる。

Docker Composeって?

複数のコンテナを使うDockerアプリケーションを定義・実行するためのツール(参考)で、コマンドを1つ実行するだけで、設定した全てのサービスを作成・起動する事ができる(参考)

設定された依存関係に応じて適切な順番でコンテナが起動されるようになっており、コマンド1つで簡単に必要なサービスを開始できたり、逆にコンテナを停止させる際も、自動的に適切な順番でコンテナを停止させるようになっている。

Docker Composeのダウンロード

GitHub上にあるComposeリポジトリのリリース・ページに移動し、指示に従いcurlコマンドを実行する。

$ sudo curl -L https://github.com/docker/compose/releases/download/1.20.0-rc2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

としたらうまくいった。

権限の追加

参考:パーミッションなどを設定する!chmodコマンドの詳細まとめ【Linuxコマンド集】

$sudo chmod +x /usr/local/bin/docker-compose

sudo時にもパスが通るようにする

docker-compose/usr/local/binにあるので一般ユーザにはパスは通っているが、sudo時のパスは通っていないので通す。visudosudoersを開き、

Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/lib/nginx-1.7.7/sbin/:/usr/local/bin/

とする。

動いていることを確認

$ docker-compose --version

$ sudo docker-compose --version

として、バージョンが表示されれば大丈夫

Mastdonを導入する

前提

これからダウンロードするMastdonプロジェクトには、Dockerfiledocker-compose.ymlが含まれていて、これはDocker Composeの少なくともバージョン1.10.0で必要とされる。これらの関係については、Dockerで雑にMastodonを起動する方法にわかりやすい図があるので良さげ。以下その図

いい図

入れるバージョン

最新版Mastodonはローカルに立てるのは非常に面倒くさい。よってここではMastodonv2.0.0を入れる。

参考

v2.0.0の最新コミットは2017/10/19だったので、最新版ではなく2017/10/27にコミットされた際の過去のDocker-Guideを参考に

v2.0.0をclone

cloneする。

$ git clone -b v2.0.0 https://github.com/tootsuite/mastodon mastodon_v2

移動

$ cd mastodon_v2/

以下特に断りが無ければここで作業

checkout

cloneの際にメッセージが出ていたのでcheckout(参考)

$ git checkout refs/tags/v2.0.0

設定ファイルのコピー

$ cp .env.production.sample .env.production

設定ファイルを変更する

.env.productionLOCAL_HTTPSfalseにする。ついでにLOCAL_DOMAINsaigoudon.netにする

# Federation
# Note: Changing LOCAL_DOMAIN or LOCAL_HTTPS at a later time will cause unwanted side effects.
# LOCAL_DOMAIN should *NOT* contain the protocol part of the domain e.g https://example.com.
LOCAL_DOMAIN=saigoudon.net
LOCAL_HTTPS=false

こうなったら大丈夫。

docker-compose.ymlの変更

docker-compose.yml

image: gargron/mastodon

となっている所を

image: gargron/mastodon:v2.0.0

としておいた。ここについてはcloneしてくるバージョンを指定するだけでいいのかこれも必須なのか要確認。

log保存用ディレクトリの作成

今更だがlog保存用ディレクトリを作って、以降ここにlogを残しておく。

$ mkdir mylogs

| tee mylogs/docker-compose_build.logを後ろにつけてlog保存用ディレクトリにも結果を残す。teeコマンドは、標準入力で受け取ったものを、標準出力と指定された出力先にそれぞれ出力するコマンド。

イメージのビルド

$ sudo docker-compose build | tee mylogs/docker-compose_build.log

secretsの生成と設定

以下を三回実行してそれぞれ生成されたsecretを何処かにメモしておく

$ sudo docker-compose run --rm web rake secret

その後

$ sudo vi .env.production

して.env.productionを開き、

# Application secrets
# Generate each with the `RAILS_ENV=production bundle exec rake secret` task (`docker-compose run --rm web rake secret` if you use docker compose)
PAPERCLIP_SECRET=f3fa3a(略)a220c7f
SECRET_KEY_BASE=96304(略)e848323
OTP_SECRET=1933c7(略)79b21e5

  • PAPERCLIP_SECRET
  • SECRET_KEY_BASE
  • OTP_SECRET

のそれぞれ=の右に入力した。

VAPID_keysの生成と設定

今度は

$ docker-compose run --rm web rake mastodon:webpush:generate_vapid_key

を実行してVAPID_PRIVATE_KEY=の右側とVAPID_PUBLIC_KEY=の右側をメモしておき、.env.production

  • VAPID_PRIVATE_KEY
  • VAPID_PUBLIC_KEY

にそれぞれ書き込む

# VAPID keys (used for push notifications
# You can generate the keys using the following command (first is the private key, second is the public one)
# You should only generate this once per instance. If you later decide to change it, all push subscription will
# be invalidated, requiring the users to access the website again to resubscribe.
#
# Generate with `RAILS_ENV=production bundle exec rake mastodon:webpush:generate_vapid_key` task (`docker-compose run --rm web rake mastodon:webpush:generate_vapid_key` if you use docker compose)
#
# For more information visit https://rossta.net/blog/using-the-web-push-api-with-vapid.html
VAPID_PRIVATE_KEY=VBOB(略)qX_l1NgSLA=
VAPID_PUBLIC_KEY=BHLWTwr9MW_QE74n8_b(略)C8g=

データベースの作成

$ sudo docker-compose run --rm web rake db:migrate

うまくいかない時は

バージョンは違うが、v2.3.0のリリースノートもしくはその日本語訳を見ると、

Troubleshooting
If you are using Docker with docker-compose and are getting a PG::ConnectionBad: could not translate host name "db" to address: Name does not resolve, you might have to do docker-compose down (make sure you were using volumes so you won't lose data!) before you can run any further docker-compose commands.

トラブルシューティング Dockerでdocker-composerを使用し、PG::ConnectionBad: could not translate host name "db" to address: Name does not resolveが出る場合、docker-composeコマンドを走らせる前に、docker-compose down(Volumesを使用し、データを失わないようにしてください!)を実行する必要があるかもしれません」 とある。

プリコンパイル

$ sudo docker-compose run --rm web rake assets:precompile | tee mylogs/asetts_precompile.log

起動

$ sudo docker-compose up -d

errorが出てうまくいかない時は

別にmastodonを構築しようとしていたなら、それが邪魔をしている可能性があるのでそれらをdocker-compose downする。

状態の確認

$ sudo /usr/local/bin/docker-compose ps

動いていれば全てのStateUpになっているはず。

接続テスト

ポートフォワードのmastodonRuleはホストポート3333、ゲストポート3000にした。 Chromeからhttp://192.168.1.3:3333/に接続する。

内部から接続すると

[inaenomaki@localhost mastodon_v2]$ curl localhost:3000
<html><body>You are being <a href="http://localhost:3000/about">redirected</a>.</body></html>

起動までに時間がかかることもあるので注意。

起動したかを確認するのには、docker-compose logs

$ sudo docker-compose logs -f

として起動したことを確認すると良い。

こうして、無事立てることに成功した。

Mackerelでmastodonサーバを監視する

参考:Mackerelをはじめる

Mackerelとは?

Mackerelは複数のサーバーのリソース状況やサービスのパフォーマンスを可視化、監視するためのサービスのこと。

Mackerelでは、mackerel-agentと呼ばれるプログラムをサーバーにインストールすることでホストを登録する。協調してはたらくホストをまとめる『サービス』、サービス内のホストの役割である『ロール』によってホストを管理し、エージェントが収集したホストの状況をウェブ上で視覚的に確認できる

またMackerelでは、ユーザはオーガニゼーション(団体、組織)に所属し、複数人で共同で管理を行うことができる。

オーガニゼーションの作成

ページ左上あたりからオーガニゼーションの作成をする。

ここではmylocal-mastodonという名前でオーガニゼーションを作成した。

プランはTrialにしたが、Freeでもよさそう。(要確認)

オーガニゼーションのトップページのinstructionによると、


1. 最初のオーガニゼーションを作成

{自分の登録メールアドレス}さんが所属するひとつめのオーガニゼーションをつくります。


2. 新規ホストを登録する

Mackerelにホストを登録するには、登録したいホストにmackerel-agentをインストールする必要があります。


3. サービスをつくってみましょう

Mackerelでは、協調してはたらくホスト群をまとめる『サービス』と、
サービス内の役割である『ロール』を使ってホストを管理します。
サービスをつくることで、複数台のホストの状態を一画面で素早く確認できるようになります。


4. ロールをつくる

エージェントをインストールしたホストを実際にサービスの一員として認識させるためには、
ホストのサービスにおける役割である『ロール』が必要です。
サービスのページから新しいロールを作成できます。


5. ホストにロールを紐付ける

作成したロールにホストをひもづけてみましょう。
ホストの一覧から、ロールを設定してください。あるいは、各ホストの設定画面から紐付けることもできます。


おめでとうございます!

ここまでの操作で基本的なMackerelにおけるリソース監視ができるようになりました。
ここからは、もう一歩進んだ使い方を紹介します。


ホストやサービスなどの監視をする

監視対象がどのような条件を満たした時に異常な状態であるかを決める監視ルールを設定できます。
監視ルールの条件をもとに発生したアラートはアラート一覧画面から確認できます。


アラートの通知先を振り分ける

発生したアラートの通知先を特定のサービスや監視ルールごとに自由に分類・設定できます。
プロジェクトチームや職種別チームなど、組織の開発スタイルに合わせた通知先の運用に便利です。


共同管理者を招待する

Mackerelでは、オーガニゼーションごとに共同の管理者を指定・招待できます。
オーガニゼーションの詳細ページから招待メールを送信してください。


という手順で進んでいくのでこれに從う。

新規ホストの登録

「新規ホストの登録」を押すと、使用OSを聞かれるのでCentOS/RedHatを選択してプルダウンメニューに書いてある

$ curl -fsSL https://mackerel.io/file/script/setup-all-yum-v2.sh | MACKEREL_APIKEY='(略)' sh

を実行する。

動作の確認がしたければ

$ sudo journalctl -u mackerel-agent.service

とする。

サービスを作る

「新しいサービスを作成」からサービスを作る。ここではサービス名はmastodonにした。

ロールを作る

「新規ロールを作成する」からロールを作る。ここではロール名はwebにした。

ホストにロールを紐つける

左カラムの「Hosts」を選択するとホスト一覧が表示されるが、さっき追加したホストの「サービス/ロール」の所に「ロールを設定」ボタンがあるのでこれを押す。そうしたらさっき作ったロール(mastodon: web)が表示されるので選択して「更新」を押す。

dockerのメトリクスをとれるようにする

参考:Dockerをモニタリングする

エージェントが基本的なメトリクスについてはとるようにするので、dockerのメトリクスを設定して取れるようにする。

Dockerコンテナの消費リソースを把握するには、Dockerが利用しているリソースの統計情報を参照する。Dockerのリソースの統計情報はAPIを利用して取得する。技術的な詳細は公式ドキュメントを参照のこと。

Mackerelではmackerel-plugin-dockerを利用することで、各コンテナのリソース消費の統計情報を取得しカスタムメトリックグラフとして可視化することができる。 mackerel-plugin-dockerは公式プラグイン集に含まれてるので、まずは公式プラグイン集をインストールする。

公式プラグイン集のインストール

参考ミドルウェアのメトリック可視化に公式プラグイン集を使う

$ sudo yum install mackerel-agent-plugins

でインストールする。

[inaenomaki@localhost ~]$ sudo yum install mackerel-agent-plugins
[sudo] password for inaenomaki: 
Loaded plugins: fastestmirror, langpacks

(略)

Installed:
  mackerel-agent-plugins.x86_64 0:0.46.0-1.el7.centos

Complete!

となったら成功。

プラグイン/usr/binにインストールされているので、mackerel-agentの設定ファイルに、利用するプラグインに合わせて以下のような設定を追加する。設定の反映には、mackerel-agentの再起動が必要となる。

設定の追加

プラグイン集がインストール出来たら、以下の設定を/etc/mackerel-agent/mackerel-agent.confに追記する。

[plugin.metrics.docker]
command = "mackerel-plugin-docker -name-format name"

これにより、そのホスト上で動作するDockerコンテナのCPU使用率メモリ消費量IO使用量(IOPS、転送バイト数とキュー長)が可視化される。

設定の反映には、mackerel-agentの再起動が必要なので再起動する。

$ systemctl restart mackerel-agent.service 

これでHostsのカスタムメトリックにDockerのメトリックが表示されるようになる。

ログ監視を行う

参考:ログ監視をおこなう

目標

/var/log/messageserrorという文字列が出力されたかどうかを監視したい。

公式チェックプラグイン集のインストール

参考:チェック監視に公式チェックプラグイン集を使う

$ sudo yum install mackerel-check-plugins

を実行する。

[inaenomaki@localhost etc]$ sudo yum install mackerel-check-plugins
[sudo] password for inaenomaki: 
Loaded plugins: fastestmirror, langpacks

(略)

Installed:
  mackerel-check-plugins.x86_64 0:0.18.0-1.el7.centos

Complete!

とでたら成功

check-logを使う

check-logを使ってログ監視を行う。特定ファイルの特定文字列の出現について検出したい場合、/etc/mackerel-agent/mackerel-agent.confを開き、

[plugin.checks.access_log]
command = "check-log --file {監視したいファイル名} --pattern {検出したい文字列}"

と追記する。つまり、--fileオプションに監視対象のファイルを、--patternオプションに、エラー文言を検出したいパターンを正規表現で指定する。

今回は/var/log/messageserrorという文字列が出力されたかどうかを監視したいので、/etc/mackerel-agent/mackerel-agent.confを開き

[plugin.checks.access_log]
command = "check-log --file /var/log/messages --pattern error"

と追記する。

設定の反映には、mackerel-agentの再起動が必要なので再起動する。

$ systemctl restart mackerel-agent.service 

ログ監視が無事追加されていれば「Hosts」で「Host」を選んだ時の右の「Monitors」に

 access_log
LOG OK: 0 warnings, 0 criticals for pattern /error/.

と表示される。

Monitorsの方から見ても見えないのが何故かわかっていないので要確認。

アラートが自動クローズされないようにする

追加したログ監視について、アラートがでた時に自動でクローズしないようにしたい。

そのためには/etc/mackerel-agent/mackerel-agent.confのログ監視の項目にprevent_alert_auto_closeのオプションを追加するといい(参考1,参考2)。

よって、

[plugin.checks.access_log]
command = "check-log --file /var/log/messages --pattern error"
prevent_alert_auto_close = true

とさっき編集したところをprevent_alert_auto_close = trueを追加する形で書き換える。

設定を反映させるためにmackerel-agentを再起動する。

[inaenomaki@localhost log]$ systemctl restart mackerel-agent.service 

これでアラートが自動クローズされなくなった。

VSCodeの簡単な紹介(Markdown)

目次

経緯

今までmarkdownエディタとしてAtomを使ってきていたのだが、とにかく重くなる為に10分毎にソフトを再起動する必要があり、そのストレスが酷かったのでVSCodeに乗り換えてみたら、思っていた以上にいいエディタだった。今更感はあるものの簡単に紹介しようと思う。

また、文中の埋め込み動画について、編集中に撮ったものなので、映っている文章等がこの記事の本文と違う所もあるが気にしないで欲しい。

VSCodeって?

Wikipediaによると

Visual Studio Codeソースコードエディタである。マイクロソフトにより開発され、WindowsLinuxmacOS上で動作する。デバッグ、Gitクライアントの統合、シンタックスハイライト、インテリセンス、スニペットリファクタリングなどの機能を持つ。カスタマイズもでき、利用者はエディタのテーマやキーボードショートカット等を変更できる。

Visual Studio CodeはElectronフレームワークを使用しており、Node.jsを使ったBlinkで描画されるデスクトップアプリケーションである。なお、Electronを使用したテキストエディタとしてAtomが有名であるが、そこからの派生ではなく、Visual Studio Online のエディタ(コードネーム "Monaco")が基になっている。また、Visual Studioとは名称に共通点があり、使われている技術にも共有されている部分があるものの、直接的な派生関係は無い。

Visual Studio CodevscodeGitHub上のリポジトリ名)は完全に同一のものと思われがちだ。しかし、Visual Studio Codeオープンソースvscodeを元に作成されたものでありライセンスを含め違ったものである。

Visual Studio統合開発環境であるのに対して、Visual Studio Codeソースコードエディタ、つまりはテキストエディタであることなどがわかる。

個人的に述べさせてもらうと、Visual Studio Codeは、

といった感じ。なんでさっきからテキストエディタと言っているかというと、僕個人がマークダウンを書くのにしか使っておらず、ソースコードエディタとしての真髄をまだ体験していないと思っているから。

しかし、デバッグ周りの機能がVisual Studioと同じ感じで備わっているのを見ると、こちらもなかなか優秀そうなので、いつか使った時には記事を書くか、追記したい。

VSCodeのインストール

公式サイトのトップページから、Download for ******に自分の使っているOSが自動識別されて表示される様なので、あっていたらそこをクリックする。

f:id:makiofinae:20180322141940p:plain

あっていなければ、その右の矢印の様なマークをクリックしてドロップダウンした選択肢の中から自分の使っているOSを選択する。

f:id:makiofinae:20180322141955p:plain

もしくは、ダウンロードページから自分のOSにあったものをダウンロードする。

f:id:makiofinae:20180322142008p:plain

インストールはインストーラに従って適当にすれば大丈夫。非常に簡潔で、特に変わったことは聞かれなかったと思う。

共通部分はあるとは思うが、ここからはOSはWindows前提で話を進めていく。

VSCodeの強み

以下、VSCodeの強みについて書いていこうと思う。

とにかく軽い

もうこれが強すぎるが、非常に軽い。起動が早ければ動作も早い。何かあったとしても再起動が直ぐなのでストレスがない。

ショートカットキー

参考: - キーバインディング - 【Windows版】VS Code キーボードショートカット一覧 (オススメ付き)

(2018/8/12 追記 : ショートカットが変更されたようで、この記事におけるショートカットキーが必ずしも同様に動作するとは限らないことを確認した。上部のメニューバーから「Help->Keyboard Shotrcuts Reference」から現行のショートカットキーが確認できるのでそちらを確認いただきたい)

VSCodeには豊富な機能が存在しており、それらの殆どはショートカットキーで使用可能だ。Visual Studio(以下、単にVS)を普段遣いしている身としては、同じキーバインドで同じ様な機能が使えるのが非常に嬉しい。しかし勿論完全互換というわけではなく、VSCode独自の機能に対応するためVSと違うキーバインドになっているものもある。

以下コマンド例。

キー 動作 コマンドID
Ctrl+X 行の切り取り (未選択時) editor.action.clipboardCutAction
Ctrl+C 行のコピー (未選択時) editor.action.clipboardCopyAction
Ctrl+Shift+K カーソル行削除 editor.action.deleteLines
Ctrl+Enter 下に行追加 editor.action.insertLineAfter
Ctrl+Shift+Enter 上に行追加 editor.action.insertLineBefore
Alt+Down カーソル行を下に移動 editor.action.moveLinesDownAction
Alt+Up カーソル行を上に移動 editor.action.moveLinesUpAction
Shift+Alt+Down カーソル行を下にコピー editor.action.copyLinesDownAction
Shift+Alt+Up カーソル行を上にコピー editor.action.copyLinesUpAction
Ctrl+D 次のマッチを選択に追加 editor.action.addSelectionToNextFindMatch
Ctrl+K Ctrl+D 次のマッチに移動 editor.action.moveSelectionToNextFindMatch
Ctrl+U カーソル動作のUndo cursorUndo
Ctrl+Shift+L 選択部分の全マッチを選択 editor.action.selectHighlights
Ctrl+F2 選択ワードの全マッチを選択 editor.action.changeAll
Ctrl+Alt+Down カーソルを下に追加 editor.action.insertCursorBelow
Ctrl+Alt+Up カーソルを上に追加 editor.action.insertCursorAbove
Ctrl+Shift+] 対応する括弧に移動 editor.action.jumpToBracket
Ctrl+] 行にインデントを追加 editor.action.indentLines
Ctrl+[ 行のインデントを削除 editor.action.outdentLines
Home 行の先頭に移動 cursorHome
End 行の末尾に移動 cursorEnd
Ctrl+End ファイルの末尾に移動 cursorBottom
Ctrl+Home ファイルの先頭に移動 cursorTop
Ctrl+K Ctrl+C 行コメント記号を追加 editor.action.addCommentLine
Ctrl+K Ctrl+U 行コメント記号を削除 editor.action.removeCommentLine
Ctrl+/ 行コメント記号をトグル editor.action.commentLine
Shift+Alt+A ブロックコメント記号をトグル editor.action.blockComment
Ctrl+F 検索 actions.find
Ctrl+H 置換 editor.action.startFindReplaceAction
F3 次を検索 editor.action.nextMatchFindAction
Shift+F3 前を検索 editor.action.previousMatchFindAction
Ctrl+M タブでフォーカス切り替えモードをトグル editor.action.toggleTabFocusMode

特におすすめのものについては以下でも個別に見ていくのでその時にも示そうと思う。

ディレクトリ単位で開ける

VSCodeは複数のファイルをタブ形式で同時に開くことが出来るのだが、それらのファイルを特定のフォルダに入れておくことで、それを一つの単位として開くことが出来る。こうすると、フォルダ内のファイルがエクスプローラーに表示されるようになる。タブで開いておくと次回開いた際にも同様に開いてくれる。エクスプローラーについては左のメニューのファイルマークみたいなのを選択 or Ctrl+Shift+Eで出せる。以降はCtrl+Bでサイドメニューの表示をトグル出来る。

フォルダとして開くにはまだフォルダを開いていない状態でエクスプローラーのサイドバーを開き、「フォルダーを開く」を選択して、開いたウィンドウで開きたいフォルダを指定する。

f:id:makiofinae:20180322142113g:plain

タブでファイルを開いた際はCtrl+TabもしくはCtrl+Shift+Tabでタブを切り替え出来る。

マルチカーソルが便利

VSCodeでは、マルチカーソルといって、複数箇所に同時入力することが出来る機能がある。簡単なものをリストアップするとこういった感じだ。

機能 使い方
マルチカーソルを追加 Alt+Click
マルチカーソルの拡大 Ctrl+Alt+Up(Down)
マルチカーソルの解除 Esc
選択範囲と同じ文字列を追加選択 Ctrl+D

マルチカーソルの追加 f:id:makiofinae:20180322142202g:plain

マルチカーソルの拡大 f:id:makiofinae:20180322142206g:plain

選択範囲と同じ文字列を追加選択 f:id:makiofinae:20180322142208g:plain

これが結構便利なので是非使いこなして欲しい。

選択が楽

VSCodeではVS同様Ctrl+Left(Right)で文字列単位もしくは英単語単位で移動ができるので、この時Shiftを押しておけば文字列単位もしくは英単語単位で選択ができる。

f:id:makiofinae:20180322142400g:plain

また、Alt+Shiftを押した状態でドラッグアンドドロップすることで矩形選択をすることも出来る(VSではAlt+Shift+矢印キーで矩形選択できたが、VSCodeではAlt+Shift+Up(Down)が「上(下)に現在の行をコピー」になっているので出来ない。またVSと違い矩形選択に対する置換は出来ない模様)。

f:id:makiofinae:20180322142415g:plain

コメントアウトが楽

VSCodeではCtrl+/で行のコメントアウトが出来る。VSと同じくCtrl+K,Ctrl+CコメントアウトCtrl+K,Ctrl+Uコメントアウト解除が出来るが、VSと違いこちらは行コメントアウトのコマンドになる。

f:id:makiofinae:20180322142432g:plain

選択箇所などブロックでのコメントアウトにはShift+Alt+Aを使う。

f:id:makiofinae:20180322142440g:plain

全体の表示

編集場所の右にはコード全体を縮小したものが表示されていて、全体の構成がどの様になっているのか大まかに知ることができる。また、マウスオーバーすることでそのうち画面に映っている場所がどこかも教えてくれる。

f:id:makiofinae:20180322142452g:plain

行ごと移動

Alt+Up(Down)でカーソルがある行を上下に移動させることが出来る。移動する時は移動先と行を交換する形で移動する。

f:id:makiofinae:20180322142805g:plain

インデントの追加(削除)

Ctrl+]([)でインデントの追加(削除)を行える。

f:id:makiofinae:20180322142825g:plain

gitとの連携

git使用時に行番号の右の色のついた部分をクリックすると差分を確認できたりと、gitとの連携も取れていて便利。

変更前と変更後を左右に並べて、全体の変更点について確認も出来る。

拡張機能

VSCodeではユーザーが公開した拡張機能を使うことが出来る。これは所謂他のソフトでアドオンやプラグインと言われる機能だが、これによってデフォルトのままでは痒いところに手が届かずとも、何処かの誰かが作ってくれた便利な拡張機能のおかげで自分の好きな環境を構築することが出来るようになる。

markdownに便利な機能

言語モード

VSCodeでは、言語モードに基づいてその言語にあったシンタックスハイライト等をつけたりする。また、Ctrl+K,M(Ctrl+K,Ctrl+Mではない事に注意)を押すと検索窓が開き使用する言語モードを明示に指定できる。基本的に自動検出されると思うが、シンタックスハイライトがおかしい時等はこれでMarkdownを選択する。

f:id:makiofinae:20180322142552g:plain

プレビュー

markdownのプレビューを見るにはCtrl+Shift+Vで開く。プレビューはリアルタイムに更新されるので、プレビューを表示しながら編集したければ、プレビューを開きそれをCtrl+Alt+Right(右に画面を分割して追加)等で横に移すか、Ctrl+K,Vでプレビューを横に開く。タブで切り替えをしてもその表示されたタブのプレビューを表示してくれるので便利。

f:id:makiofinae:20180322142612g:plain

また、プレビューで何処かを選んでダブルクリックするとエディタ内のその箇所にジャンプすることが出来る。

インジケータ

編集時にプレビュー側に編集箇所を示すインジケータが出るので、そのおかげでプレビューでいうところのどの部分を編集しているのかがわかりやすい。

目次の自動生成

参考:vscodeの AlanWalk/markdown-toc extensionで目次の自動生成すると捗るぞ

markdownの目次を手動で管理するのは流石にアホらしい。自動で生成したいが、デフォルトのままではそういった機能は今の所ない。そこで目次を自動生成する拡張機能を入れる。

右のメニューの一番下の拡張機能マークを押して拡張機能サイドバーを開いたら、その中にある検索窓にmarkdown-tocと入力する。そうしたら恐らく一番上に出てくるAlanWalkさんのMarkdownTOCをインストールする。

インストール出来たら、目次を生成したい所で右クリックしてメニューからMarkdown TOC:Insert/Updateを選択するか、Ctrl+M,Tと押す。するとその位置に目次が生成され、ファイルが保存される度に自動で更新されるようになる。

もしも全ての項目にセクション数を追加したいのであれば(例えばこのセクションは4.8.3になる)、右クリックして出したメニューからMarkdown Sections:Insert/Updateを選択するか、Ctrl+M,Sと押す。

これで目次の自動管理が可能になった。

因みに拡張機能の設定を変更することで目次に表示する項目の深さ(デフォルトだと1から6まで)を変更できるが、これは以下のようにすることでファイルごとにも変更できる。

<!-- TOC depthFrom:2 orderedList:true -->

<!-- /TOC -->

詳しくはこの拡張機能OverView等を参照のこと。

なお、この記事の目次ははてな記法で自動生成しているのでこれは使っていない。

入力補完

VSと同様、入力中にCtrl+Spaceと押すことで入力を自動補完出来る。ただし、IntelliSenseのみならずスニペット等も合わせて表示される。

f:id:makiofinae:20180322142849g:plain

スニペット

スニペットとは、一般的には「切れ端」「断片」という意味の英語である。IT用語としては、プログラミング言語の中で簡単に切り貼りして再利用できる部分のこと 引用元

自動補完で表示が可能なことは先程示したが、VSCodeではこれも自分で定義できる。

自作スニペット

参考:独自のスニペットを作成

自作のスニペットを作るには上のメニューから「ファイル->基本設定->ユーザースニペット」と選択する。そうすると検索窓が出てくると思うので、markdownと入力してmarkdown.jsonを選択する。するとmarkdown.jsonが開くのでここに入力していくことになる。markdownに限らずスニペット(languageId).jsonに保存する。

形式は

 "スニペットの名前":{
        "prefix": "自動補完の際にトリガーとなる文字列",
        "body":["置き換えられる文字列"],
        "description": "説明文",
    }

となっていて、これをデフォルトで書き込まれている{}のブロックの中に追記すればスニペットが追加できる。

bodyの置き換えられる文字列については

"body":[
            "1行目",
            "2行目",
            "3行目"
        ],

のように行にまたがって指定することが出来る。

例えば、横2縦3のテーブルに置き換えるスニペットであれば

 "create table":{
        "prefix": "table",
        "body":[
            "|col1|col2|",
            "|:--|:--|",
            "|ele1|ele2|",
            "|ele1|ele2|"
        ],
        "description": "2x3 table",
    }

と追加して、tableと入力して自動補完からスニペットを選択すると

|col1|col2|
|:--|:--|
|ele1|ele2|
|ele1|ele2|

と入力されるわけだ。スニペットの機能自体はもう少し特殊な構文もあり、色々とやれることはあるのだが、ここでは割愛するので参考ページを参考のこと。

みんなちがってみんないい(本当か?)

すごく簡単なことだけど、人は皆違っている。生まれた時や、過ごしてきた時間や場所、その他とても多くの要素が思考や、もしかすると身体をも形作る。ある人とある人の歴史が違うから、それらの人は違う、という論だとそれはどうだか怪しい気もしてくるが(客観的体験が違うからと言って主観的体験も違うか、またそこから生じる思考も違うかというとそれを論理的に裏付けるのは難しそうだ)、少なくとも全く同じ思考が築かれるよりは皆が違っているほうがよっぽど妥当だと僕は思っている。仮に全員が違わないとしても、違う思考を持つ人がいる、というのはわかるだろう。全員が完全に同じ思考をもっているのだとしたら、通信技術はここまで発展しただろうか。考え始めると色んな矛盾が出始める。よってここでは仮に全員が違わないとしても、少なくとも全員が同じではなく、違う思考を持った人がいる、と考える。

しかし、私たちはそのことを忘れがちである。自分が特定の道を通って体得した何かについて、他者がそれを体得できないことについて疑問を抱いたり、自分が当然に理解できることが他者には理解できない時に戸惑ったりする。さらに奢りが生まれると、自分ができることについては当たり前に「みんな」が出来ることだと思い始めるのである。人に得意不得意があることを忘れたりする。例えば、コミュニケーション能力を要求されるとキレる割に、調べて問題解決する能力がない人やそうやって解決できる事を知らない人に「それくらいやれ」と断じたりする。だから世界に争いはなくならない(すぐにスケールを無駄に大きくした事を言いたがる)。

タイトルに「みんなちがってみんないい」と書いた。「みんなちがって」の部分は以上の通りだ。立証できないので仮説に過ぎないが、僕はこれについては確信している。これを忘れなければ、非常に不合理な押しつけなどはなくなるだろう。

「みんないい」の部分については更に難しい。ここで僕がいいたかったのは違いがあるということはそこが強みになりうるということだ。1次ソースが確認できないので真偽は定かではないが、任天堂の岩田前社長のものとされる言葉に

「自分の長所を見つけるには、自分が楽にできることを探すこと」

というものがある。人は苦労して何かを身に付けると、それにすごい価値があると思い込みたがる。しかし、実は自分は何気なくやってるけど他の人は結構苦労してる物があって、そういうものこそ価値を生む、という事が言いたかったとして紹介されている。

僕はこれに関してその通りだと思う。一生懸命苦労して身につけたものが無駄だと言いたいのではない。人には違いがあって、つまりは得手不得手があって然るべきだ。だから、そのことを忘れず、自分の得意を活かし、他人の不得意を慮る、そういうことが全員がうまく生きられる経済的(ここではいわゆる社会経済の経済というよりは、限られた財を適切に分配すると言ったような経済学等に使われる方の意味の経済)な方法だと思うのだ。

だから僕は題を「みんなちがってみんないい」と書いた。本当か、とつけたのは、みんないい、というわけではないからだ。違いがあることが強みになるとしても、その強みにも程度がある。そしてそれが社会にどの程度評価されるかということもものによって違う。場合によっては社会に評価されないが他人と違う事によってあることについてとても秀でているということがあるかもしれない(寸分違わず狙った場所に輪ゴムを飛ばせる、とか)。それがいいとか悪いとかは正直僕にはわからない(よって本当か?とつけた。みんなよかったら社会に苦しい人はいない)。ただ僕がいいたかったのは、人は違うから、自分にとっての当たり前を他人に押し付けてしまう前に疑おう、みたいなそういう話なのだ。

但しこれを「全員に考えてくれ」、と言うことに関しては問題がある。これは常に思考をして、最善ではなくとも改善をしていこうとする時に常にぶつかるメタな問題だ。それは「以上のことを考えながら生きる」という主張は、思考コストが高い人々への押しつけになり、それこそ人の得意不得意を考えない非合理的な押し付けになってしまうということだ。この主張は、「最善へ向けて改善をすることを目指して常に考え続けたい思考コストの低い人間」のエゴであるとも言えてしまう。コミュニケーション能力の低い人物に無理にコミュニケーションを強いることは許されるだろうか。正当化をしようとすることは出来るかもしれないが、僕はそれは良くないことだと思う。自分が支払うコストが小さいからといって、相手にも同じものを強いるのは安全圏からマウントをとっているようなものになりえないだろうか。そういったことを危惧してしまうのである。 同様に、こういった問題への思考コストが高い、ぶっちゃけていうと面倒くさいと考えている人物に、こういった意見をぶつけてこれからはこういったことを考えながら思考を改めよ、というのは良くないのではないだろうか。

だが、強制しないにしても、こういったことを誰かが言わないと気付けない、という面もあるかもしれないなと思い、思ったものをそのまま書き殴る形になったが、少し吐き出してみた。皆さんはどう思うだろうか。

チャールズ・ケリー氏著の『入門ゲームプログラミング』を読んで

チャールズ・ケリー氏著の『入門ゲームプログラミング』を読了しました。記録として、そして他の方の参考のために感想を書いておこうかと思います。

まず、自分はこの本をDirectXの勉強のために購入しました。しかしDirectXと言っても、DirectX11や12へどういった変遷をしていったのかを知りたい、また、DirectX11や12に直接初心者が入門する為の書籍等は少ないがDirectX9からステップアップする書籍等は幾らかあるといった理由から、現在多く使われている様なDirectX11や12ではなく、DirectX9を勉強したい思いで購入しました。DirectX9を勉強する上で有名なDirectX 9 シェーダプログラミングブックは現在既に絶版になってしまっているらしく、新品が多く流通していない現状のため、取り敢えずDirectX9を使っているらしいことと「入門」と銘打っている事からこの書籍を購入しました。

読んでみた正直な感想としては、

  • どの層をターゲットにしているのかイマイチわからない
  • どこまでがDirectXの話でどこからが本書で使っている自作クラス・関数の話なのかが区別が非常につき辛い
  • 見やすくまとめようと言った配慮はあまりない
  • 本書掲載分だけではなく、サンプルコード全体を見ないと理解しづらい場所がある

と感じました。

まず、どの層をターゲットにしているのかイマイチわからない、ということについてですが、この本はタイトル通り基本的にゲームプログラミングの基礎的なことに触れていくのみで、本当にそれを超えたことはあまりしないのですが、その割には初学者にとっては敷居が高いDirectXをフワッとした説明のみで使い、少し置き去り感があります。どうしたって本書以外で補完しないと、DirectXが「よくわからないもの」にしかならないと思います。おそらく少しDirectXには触ったことがある人間が読んで初めて違和感がないのではないでしょうか。 しかしそれに反して、それなりのゲームを作ったことがある人にとってはあまり新規性のない事ばかりが書かれています。具体的にゲームを作っていく過程を追っていく感じなのですが、ゲーム制作経験のない人にとっては良いものかもしれないですが、経験がある人からするとほぼ全て知っていることなので時間の無駄になると思います。 こうなると、「ゲームは作ったことはないけどDirectXはわかっている人間」が対象になるのですが、こういった人って非常に限られていると思うのでまさかこれをメインターゲットにしているとは思えなく、どの層をターゲットにしているのかイマイチわからないなあ、という風に思いました。

次に、どこまでがDirectXの話でどこからが本書で使っている自作クラス・関数の話なのかが区別が非常につき辛い、ということについてですが、これはそのままで、作者が作ったクラスの説明も本書ではされるのですが、それがDirectXの機能として提供されているものなのか、勝手に作者が作ったものなのかの判別が付きづらく、DirectXを勉強したいだけであって作者の趣味に付き合いたい訳ではない読者にとっては非常に厄介な存在となっています。この点に関しては本当に致命的なのでもっとしっかり明示するようにしていただきたいなと思いました。

次に、見やすくまとめようと言った配慮はあまりないという点についてですが、なんというか、あくまでも説明はプレーンテキスト風から離れないぞという意思の感じられる構成になっていて、読めなくはないもののここはもっとこうした方が読みやすいよなという所が満載で、そこまでは手が回っていないんだろうなというのを全体から感じました。

次に、本書掲載分だけでなく、サンプルコード全体を見ないと理解しづらい場所がある、ということについてですが、本書では本書で順を追って作成していくプログラムについて、公式のサポートから無料ダウンロード出来るようになっています。本書にもソースコードが必要な分引用して記載されていますが、正直必要最低限という感じがある所が幾らかあって、全容をつかむにはやはりそのダウンロードしたソースコードで全体を見る必要があると感じました。おそらくそういった形で学習を進めてほしいというのが本書の意図でしょう。もし書籍のみで取り敢えずの概観を掴みたいという方がいるのであれば、本書はあまりオススメしません。

と、ここまで書いてきてネガティブな話ばかりになってしまったのですが、名前の通りゲームプログラミングをするにあたっての入門的な事は一応ひとしきりしているように感じるので、初心者の人が斜め読みして雰囲気をつかむ分には良いのではないでしょうか。それにしてはボリュームとお値段がなかなかな気はしますが…

それと、数カ所誤訳なのかソースコードでしていることと説明文とが一致していないところがありました。そういった意味でも斜め読み推奨です。

得たものがないかというとあるにはあるのですが、それにしたってもっとコストをかけずに得られたのではないか、と思わせられてしまう一冊でした。

多倍長整数をstd::stringを使ってゴリ押し実装してみた

目次


初めに

前置き

どうも、いなえのまきです。

この記事はCCS Advent Calendar 2017の6日目として書かれた記事です。

前日の記事 by ユーマ

次の人→珈琲王子

どうも今年は裏アドベントカレンダーなるものもあるらしいので気になる方はそちらも是非。

去年はCCS Advent Calenter 2016にも参加しました。記事はこちら


動機

さて、別に何をやるとも決めていなかったので、「コンピュータ上での文字周りのことについて勉強してまとめて、それを記事にしてあげるかなあ」くらいのノリでアドベントカレンダーに参加してしまったのですが、思ったよりもやることがあったのと、少し調べてみると結構な分量と労力になりそうな事がわかったので、文字周りの話は余裕がある時にまた記事をあげることにして断念しました。

そこで、何か楽に書けるふさわしい題材がないかと思った時に、過去に楽しそうと思って書いてみた多倍長整数のコードを思い出した感じです。

多倍長整数自体は結構色々なライブラリで実装されてたり、言語によってはデフォルトでサポートされてたりするそうなので、そもそも自分で作る意味がない(車輪の再発明)なわけなんですが、面白そうなので作ってみたという経緯があります。その為、新規性はないです(1年ぶり2回目)が、個性を出せるように頑張ってみたのでどうぞ。

多倍長整数

多倍長整数って?

Wikipediaを見ると、

任意精度演算とは、数値の精度を必要ならいくらでも伸ばしたりできるような演算システム(実際上は利用可能なメモリ容量に制限されるが)による演算である。

とした上で、

多倍長整数などを内部処理に利用し、必要な桁数の浮動小数点計算を行う

という風に書かれています。

何となくイメージはつかめるかと思いますが、こちらのサイトにあるように

多倍長整数とは、コンピュータに巨大な整数を扱わせるための仕組みである。

こういったものです。

Cなんかでいうint型なんかは扱える数の大きさに定められた制限があります。これはハード側で高速に演算等を行う為らしいのですが、そのせいでその制限以上の大きさの値を扱うことが出来ず困る場面もあります。これを解決する為に用いられるのが多倍長整数といったものです。多倍長整数は、制限なく大きな整数を扱うことを可能にしてくれるのです(実際にはメモリの容量等ハードの制限はありますが)。

よくある方針

ここここここここ当たりを見てる感じ、基本方針としては、整数の配列やリスト等を用意してやって、それらを1つの数として扱うアルゴリズムを実装していく感じが多いみたいですね。

どうやったの?

以前僕が書いたものも内部的にはこれに結構近い感じのものだったのですが、少し特色付けたいなと思って僕が目指したのが、std::stringを使って多倍長整数を実装するという方法です。

何故これにしたかというと、

  • std::stringが勝手に長さを調整してくれるので、メモリの確保や解放の処理を自分で書かなくていいので楽な上メンテナンスしなくていいから
  • いくら大きな値を扱えるようにしてもBigInt a=9999999999999999999999;みたいに書くと定数が大きすぎるとして怒られてしまうが、BigInt a="9999999999999999999999";という風に書けるようにすればこの問題は解決する。その上で内部で数字を文字列で持てば、初期化や代入周りの処理が超楽に書ける
  • str_var[i]とすることでi番目のcharを取り出せるので、n桁目を取得するのが楽*1

みたいな目論見はあったわけですが、正直一桁あたりにchar分の1バイト使ってるのでとてもメモリが無駄になる上に、高速な計算も特に思いついていたわけではなかったので、正直な所演算子オーバーロードを手で書いて覚える練習がしたかったみたいな色合いが強かったです。内心実用には耐えないだろうなあとか思いながらも楽しそうだからというだけで書いてました、ハイ。

ただ、インターフェースを綺麗にするというか、ユーザーが違和感なく使えるようなクラスを考えるのって難しいんだなあとか、あっちを立てるとこっちが立てるでどうにもならんなあというところとかが出てきて、ライブラリ開発者様等の神の凄さを実感して、そこは勉強になりました。

実装

全体の方針

最終目標は、std::string型で保持している整数(以下文字列整数)を持つ自作クラスを、int型と同じ使用感で使えることになります。

そのためにまず、文字列整数をint型と同様に扱えるようにすることを考えます。

そのためにまず文字列整数同士の加算と減算、比較をする関数を用意します。そしてその必要最低限の関数を使って演算子オーバーロードしていきます。

その他雑記

注意すべきは内部処理でint型に変換してしまうと、実質精度がint型と同じなってしまう点に気をつけることです。

演算子オーバーロードでは、他のオーバーロードを出来る限り内部で呼ぶ形にすることでDRY原則に従い、メンテナンスのコストを下げようとしたのですが、加算と減算は場所によってはその場で定義してしまってます(別の演算子呼ぶより早いかな?とか思ったので。もしかしたらコンパイラが最適化してくれるから気にしなくていい系案件かもしれませんが…)。よって少し統一感の無いコードになってます。

あと、char型の数字(文字の内部的な数値ということではなく'1'とかのこと)を単純にint型にするのが地味にどうしようか迷いました。

加えて、実は

BigInt x = BigInt(0) +"2";

みたいな記法を許せるように「BigIntとstd::stringの+演算子」もオーバーロードしてたんですが、intへのキャストを暗黙のキャストも許可して定義した(これはintと同じく自然に使えるようにするため)影響でBigInt(0)が暗黙にint型にキャストされた場合というのも考えないといけなくなってしまい、組み込み演算である「integerとpointer-to-objectとの+演算」とどちらの演算子を使っているのかというのがコンパイラが判断できずエラーを吐くという結果になったので、これについては断念しました。

もう後は見ておくれ

正直そんなに語る所もない内容なのでソースコードだけ貼っつけとくので後はご自由に御覧ください(丸投げ)

多倍長整数bigintbignumといったような名前にする慣習があるらしいのですが、なんかそこまで言うのがおこがましい感じがしたのでちょいデカ目のintくらいのつもりでlonger_intという名前にしました。

何か不足している所や間違っている所があったら教えてください。

以下ソースへのリンク

*1:だと思っていたがそうでもなかった