Technology Engineering

178inaba の技術ブログ

npm loginは空いているユーザ名を指定するとアカウントを作成する

inabaです。

npm owner addで自分のパッケージにオーナーを追加できると知り、
試すためにログインが必要だったのでnpm loginでログインした時の話。

$ npm login
Username: foobar
Password: 
Email: (this IS public) foobar@example.com

上記を見てもらうとわかりますが、ユーザ名、パスワードの次にEmailの入力があります。
「なんでユーザ名入力してるのにEmailの入力も必要なのかな〜」という疑問が湧いてきたので調べてみた。

実はnpm loginは取得されていないユーザ名を指定すると新しいアカウントを作る挙動になっていた。

github.com

loginという名前だったのでこの挙動にはちょっと驚いた。

loginはnpm adduserエイリアスなんだそう。
上記issueではloginとadduserは別々のコマンドに分割する方向で考えているというような事が書いてあった。

今日はここまで。

git mergeのとき、デフォルトでno-ffになるようにする設定

inabaです。

ブランチのマージ時にマージ対象のブランチでどんな変更があったか知るためにマージコミットが欲しいので--no-ff(No Fast-forward)オプションをつけていました。

$ git merge --no-ff foobar

ですが、設定でデフォルトをno-ffにできることを知りました。

設定

$ git config --global merge.ff false

上記設定をすることでgit merge foobarのみでno-ffのマージになります。

$ git merge foobar
...

$ git log --graph --oneline
*   f84d525 Merge branch 'foobar'
|\  
| * 2d68cba Fix B.
|/  
* a3159f3 Fix A.

参考サイト: Git - git-merge Documentation

問題

しかし、上記のみだとpull時もno-ffでマージコミットができてしまいます。

$ git pull
...

$ git log --graph --oneline
*   73018f7 Merge branch 'master' of github.com:178inaba/test
|\  
| *   f84d525 Merge branch 'foobar'
| |\  
|/ /  
| * 2d68cba Fix B.
|/  
* a3159f3 Fix A.

よく言われることですがpullというのはfetchとリモートブランチのmergeの組み合わせなのでリモートブランチをマージする時に上記no-ffの設定が適用されてしまいます。
これを防ぐためにpull時にはFast-forwardでマージするように設定します。

$ git config --global pull.ff only
$ git log --graph --oneline 
* c7356cb Fix C.

$ git pull
...

$ git log --graph --oneline 
* bdbb39c Fix D.
* c7356cb Fix C.

pullでマージコミットが作られないようになりました。

まとめ

$ git config --global merge.ff false
$ git config --global pull.ff only
$ cat ~/.gitconfig
[merge]
    ff = false
[pull]
    ff = only

今日はここまで。

HomebrewでインストールしたMariaDBをStrictモードに設定

inabaです。

MariaDBをHomebrewでインストールして使っていたのですが、
NOT NULL制約のカラムにDEFAULT NULLが設定されていると、INSERT時に値を設定していないカラムにNULLが入ってしまうという事がありました。
これはStrictモードが設定されていると起きないそうなので、Strictモードの設定をします。

デフォルトのsql_mode

Strictモードはmysqlにログイン後、sql_modeの値で設定されているか確認できます。

MariaDB [(none)]> SELECT @@SQL_MODE, @@GLOBAL.SQL_MODE;
+--------------------------------------------+--------------------------------------------+
| @@SQL_MODE                                 | @@GLOBAL.SQL_MODE                          |
+--------------------------------------------+--------------------------------------------+
| NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION | NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+--------------------------------------------+--------------------------------------------+
1 row in set (0.00 sec)

デフォルトではNO_AUTO_CREATE_USERNO_ENGINE_SUBSTITUTIONが設定されており、
Strictモードの設定値であるSTRICT_ALL_TABLESまたはSTRICT_TRANS_TABLESが設定されていません。

my.cnfのパス

my.cnfのパスを調べます。

mariadb.com

上記には/etc/my.cnfが一番上に書いてありますが、/etc/my.cnfに設定ファイルを置いてみても反映されませんでした。

qiita.com

上記の方法を試します。

$ mysql --help | grep my.cnf
/usr/local/etc/my.cnf ~/.my.cnf 
                      order of preference, my.cnf, $MYSQL_TCP_PORT,

$ cat /usr/local/etc/my.cnf
#
# This group is read both both by the client and the server
# use it for options that affect everything
#
[client-server]

#
# include all files from the config directory
#
!includedir /usr/local/etc/my.cnf.d

/usr/local/etc/my.cnfに設定ファイルmy.cnfがありました。

設定

先程の設定に!includedir /usr/local/etc/my.cnf.dとあるので、/usr/local/etc/my.cnfを直接編集するのではなく、/usr/local/etc/my.cnf.dに設定ファイルを新しく作るようにします。

設定値にはデフォルトで設定されていたNO_AUTO_CREATE_USERNO_ENGINE_SUBSTITUTIONも含めておきます。
含めないとデフォルトで設定されていた上記2つは消えてしまいます。

Strictモードの設定値はSTRICT_ALL_TABLESSTRICT_TRANS_TABLESがあります。
違いについてはDifference between strict_all_tables and strict_trans_tablesがわかりやすいです。
自分は間違った値が入ってほしくなかったのでSTRICT_ALL_TABLESを使用するようにしました。
InnoDBだと違いは無いようなのでInnoDBの場合はどちらを選んでも良いでしょう。

$ emacs /usr/local/etc/my.cnf.d/my.cnf
$ cat /usr/local/etc/my.cnf.d/my.cnf 
[mysqld]
sql_mode = NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,STRICT_ALL_TABLES

# MariaDBの再起動
$ mysql.server restart
Shutting down MySQL
.. SUCCESS! 
Starting MySQL
.170105 01:51:36 mysqld_safe Logging to '/usr/local/var/mysql/i.local.err'.
 SUCCESS! 

設定値を確認してみます。

MariaDB [(none)]> SELECT @@SQL_MODE, @@GLOBAL.SQL_MODE;
+--------------------------------------------------------------+--------------------------------------------------------------+
| @@SQL_MODE                                                   | @@GLOBAL.SQL_MODE                                            |
+--------------------------------------------------------------+--------------------------------------------------------------+
| STRICT_ALL_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION | STRICT_ALL_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+--------------------------------------------------------------+--------------------------------------------------------------+
1 row in set (0.00 sec)

STRICT_ALL_TABLESが設定されている事が確認できました。

これでNOT NULL制約が厳密に適用されます。

今日はここまで。

Raspberry PiのTimezoneをAsia/Tokyoに変更する

inabaです。

前回、GitLabのバックアップ設定を行いました。

inaba.hatenablog.com

この中で、cronで毎日バックアップをするように設定しているのですが、現状はUTC時間を基準に動くようになっています。
ですので、Timezoneの設定をAsia/Tokyoに変更していきます。

  • sudo raspi-configを実行。
  • 4 Localisation Optionsを選択。
  • I2 Change Timezoneを選択。
  • Asiaを選択。
  • Tokyoを選択。
  • Finishを選択。

Finishを選択した後、コンソールに下記が表示されます。

Current default time zone: 'Asia/Tokyo'
Local time is now:      Sun Dec 25 04:00:28 JST 2016.
Universal Time is now:  Sat Dec 24 19:00:28 UTC 2016.

これでdateコマンドがJSTになったと思います。

$ date
Sun 25 Dec 04:01:00 JST 2016

今日はここまで。

GitLabの定期バックアップ設定

inabaです。

先日、バックアップ用のHDDをセットアップしました。

inaba.hatenablog.com

今度はGitLab側に定期バックアップの設定をしていきます。

GitLabではアプリケーションと設定のバックアップを別で行います。

バックアップディレクトリ作成

バックアップディレクトリをバックアップ用HDDのマウントディレクトリ下に作成します。

バックアップ用HDDをマウントしたディレクトリは/mnt/backupsですのでその下にgitlab用のディレクトリを作ってバックアップします。
ディレクトリ構成はこんな感じになります。

mnt/
└── backups
    └── gitlab
        ├── app
        └── config

appディレクトリはアプリケーションデータのバックアップ用、configディレクトリは設定データのバックアップ用とします。

作成コマンドはこちら。

$ sudo mkdir /mnt/backups/gitlab
$ sudo chown git /mnt/backups/gitlab
$ sudo chgrp git /mnt/backups/gitlab
$ sudo mkdir /mnt/backups/gitlab/config

/mnt/backupsはrootユーザ所有なのでsudo mkdirで作成しますが、バックアップコマンドはgitユーザで動きますので、作ったままだとErrno::EACCES: Permission denied @ dir_s_mkdir - /mnt/backups/gitlabというエラーが出ます。
なので、バックアップディレクトリのユーザとグループをchownchgrpで変更しておきます。
appディレクトリはバックアップコマンドを実行すると自動で作ってくれるので作らないでおきます。

逆に設定ファイルのバックアップディレクトconfigは自動では作られませんので作ります。
こちらはrootのままで大丈夫です。

アプリケーションバックアップ

アプリケーションのデータをバックアップします。

バックアップコマンド

GitLabにはバックアップコマンドが用意されています。

$ sudo gitlab-rake gitlab:backup:create

このコマンドを実行すると設定したバックアップディレクトリに(Unixタイムスタンプ)_gitlab_backup.tarというバックアップファイルが作成されます。
バックアップディレクトリのパスを設定していなければ、デフォルトのバックアップパス/var/opt/gitlab/backupsにバックアップファイルが作成されます。

基本的にはこのコマンドをcronで毎日決まった時間に実行するだけです。

設定

/etc/gitlab/gitlab.rbを編集します。

## For setting up backups

# ...
gitlab_rails['backup_path'] = "/mnt/backups/gitlab/app"
gitlab_rails['backup_keep_time'] = 604800

backup_pathは文字通り、バックアップディレクトリのパスの設定です。

backup_keep_timeはバックアップファイルを保持する期間の秒数です。
この後のcron設定で毎日バックアップする設定にしますので、バックアップファイルが無限に増えないようにします。
上記だと一週間でバックアップファイルが消える設定になりますので、バックアップファイルは7つまでになります。

編集後、GitLabの再設定を行います。

$ sudo gitlab-ctl reconfigure

cron設定

cronで毎日バックアップするように設定します。

$ sudo crontab -e -u root
# 下記を追記します。
# 0 3 * * * /opt/gitlab/bin/gitlab-rake gitlab:backup:create CRON=1
# (空行)

CRON=1

The CRON=1 environment setting tells the backup script to suppress all progress output if there are no errors. This is recommended to reduce cron spam.

と書かれているので、ログ出力の抑制をしてくれるようです。

また、cronを書くときは最後の行に空行を入れておかないとダメなようです。

ngyuki.hatenablog.com

これでUTC3時にバックアップを行うように設定できました。
(一旦UTCのまま行きます。)

設定バックアップ

設定のバックアップを行います。

cron設定

設定もcronで毎日バックアップするように設定します。

$ sudo crontab -e -u root
# 下記を追記します。
# 0 3 * * * umask 0077; tar cfz /mnt/backups/gitlab/config/$(date "+etc-gitlab-\%s.tgz") -C / etc/gitlab
# (空行)

空行を入れるのはアプリケーションのバックアップと同じです。

また、cronでは%をエスケープしなければならないようです。

blog.manabusakai.com

アプリケーションと同じようにUTC3時にバックアップを行うように設定しました。

これで毎日バックアップができるようになりました。

参考: gitlab.com gitlab.com

今日はここまで。

【Raspberry Pi】バックアップ用のHDDをセットアップする。

inabaです。

GitLabのバックアップ用にとHDDを買っていました。
そのHDDのセットアップをします。

また、Swap領域も今までのHDDのファイルから新HDDのパーティションに変更します。

Swap領域の削除

今まで使っていたSwapファイル及びSwap起動サービスを削除します。

# Swap起動サービスの停止
$ sudo /etc/init.d/dphys-swapfile stop

# Swap起動サービスパッケージの削除
$ sudo apt-get purge dphys-swapfile 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following package was automatically installed and is no longer required:
  dc
Use 'apt-get autoremove' to remove it.
The following packages will be REMOVED:
  dphys-swapfile*
0 upgraded, 0 newly installed, 1 to remove and 5 not upgraded.
After this operation, 85.0 kB disk space will be freed.
Do you want to continue? [Y/n] Y
(Reading database ... 98423 files and directories currently installed.)
Removing dphys-swapfile (20100506-1) ...
Purging configuration files for dphys-swapfile (20100506-1) ...
Processing triggers for man-db (2.7.0.2-5) ...

# 不要になったと示されたdcパッケージの削除
$ sudo apt-get purge dc
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages will be REMOVED:
  dc*
0 upgraded, 0 newly installed, 1 to remove and 5 not upgraded.
After this operation, 111 kB disk space will be freed.
Do you want to continue? [Y/n] Y
(Reading database ... 98408 files and directories currently installed.)
Removing dc (1.06.95-9) ...
Purging configuration files for dc (1.06.95-9) ...
Processing triggers for install-info (5.2.0.dfsg.1-6) ...
Processing triggers for man-db (2.7.0.2-5) ...

# Swapファイルの削除
$ sudo rm -rf /var/swap 

フォーマット

フォーマットは以前Raspberry PiにHDDを追加した時とだいたい同じです。

# 対象ディスクの確認
$ sudo fdisk -l
# ...
Disk /dev/sdb: 931.5 GiB, 1000204886016 bytes, 1953525168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

# フォーマット
$ sudo fdisk /dev/sdb

# Swap領域用のパーティション(16GiB)を切る。
Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): 

Using default response p.
Partition number (1-4, default 1): 
First sector (2048-1953525167, default 2048): 
Last sector, +sectors or +size{K,M,G,T,P} (2048-1953525167, default 1953525167): +16G # +16Gでサイズ指定(16GiB)のパーティションが切れる。

Created a new partition 1 of type 'Linux' and of size 16 GiB.

Command (m for help): p # パーティションができたことを確認。
Disk /dev/sdb: 931.5 GiB, 1000204886016 bytes, 1953525168 sectors
# ...

Device     Boot Start      End  Sectors Size Id Type
/dev/sdb1        2048 33556479 33554432  16G 83 Linux

# バックアップ用のパーティションを切る
Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): 

Using default response p.
Partition number (2-4, default 2): 
First sector (33556480-1953525167, default 33556480): 
Last sector, +sectors or +size{K,M,G,T,P} (33556480-1953525167, default 1953525167): # デフォルトで最大のパーティションが作れるのでEnterを押すだけで良い。

Created a new partition 2 of type 'Linux' and of size 915.5 GiB.

Command (m for help): p # パーティションができたことを確認。
Disk /dev/sdb: 931.5 GiB, 1000204886016 bytes, 1953525168 sectors
# ...

Device     Boot    Start        End    Sectors   Size Id Type
/dev/sdb1           2048   33556479   33554432    16G 83 Linux
/dev/sdb2       33556480 1953525167 1919968688 915.5G 83 Linux

Command (m for help): t # Swap領域に使うパーティションのパーティションタイプIDを82(Linux swap)に設定。
Partition number (1,2, default 2): 1
Hex code (type L to list all codes): 82

Changed type of partition 'Linux' to 'Linux swap / Solaris'.

Command (m for help): p # パーティションタイプIDが変更された事を確認。
Disk /dev/sdb: 931.5 GiB, 1000204886016 bytes, 1953525168 sectors
# ...

Device     Boot    Start        End    Sectors   Size Id Type
/dev/sdb1           2048   33556479   33554432    16G 82 Linux swap / Solaris
/dev/sdb2       33556480 1953525167 1919968688 915.5G 83 Linux

Command (m for help): w # 保存して終了。

The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

Swap領域作成&Swap開始

# Swap領域作成
$ sudo mkswap -c /dev/sdb1 
0 bad pages
Setting up swapspace version 1, size = 16777212 KiB
no label, UUID=50945b0a-3c30-4de5-a95d-223bb0f6415a

# Swap開始
$ sudo swapon /dev/sdb1

# 再起動しても自動でSwap開始するように設定
$ sudo nano /etc/fstab
$ cat /etc/fstab 
# ...
/dev/sdb1       swap            swap    defaults          0       0

バックアップ領域をマウント

# バックアップ領域のファイルシステムをext4にする。
$ sudo mkfs.ext4 /dev/sdb2
mke2fs 1.42.12 (29-Aug-2014)
Creating filesystem with 239996086 4k blocks and 60006400 inodes
Filesystem UUID: 50945b0a-3c30-4de5-a95d-223bb0f6415a
Superblock backups stored on blocks: 
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
    4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968, 
    102400000, 214990848

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

# 念のためディスクチェック
$ sudo e2fsck -f /dev/sdb2
e2fsck 1.42.12 (29-Aug-2014)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/sdb2: 11/60006400 files (0.0% non-contiguous), 3817299/239996086 blocks

# マウントポイントの作成
$ mkdir backups

# マウント
$ sudo mount -t ext4 -o defaults /dev/sdb2 /mnt/backups

# 確認
$ df -kh
Filesystem      Size  Used Avail Use% Mounted on
# ...
/dev/sdb2       902G   72M  856G   1% /mnt/backups

# 不要ファイル削除(後述)
$ sudo rm -rf  /mnt/backups/lost+found

# マウント永続化
$ sudo nano /etc/fstab 
$ cat /etc/fstab 
# ...
/dev/sdb2       /mnt/backups    ext4    defaults          0       0

マウントしたディスクにlost+foundというディレクトリがありますが、これはe2fsckコマンドでできたディレクトリのようです。
削除してもかまわないようです。

ja.stackoverflow.com

今日はここまで。

GitLab visibility設定とSign-up制限

inabaです。

引き続きGitLabの設定をします。

バージョン

バージョンは8.7.9です。

Raspbian Jessie向けのパッケージは多少古いようです。
これに関しては下記issueで議論されています。

gitlab.com

最新を入れる方法もあるようです。
自分はとりあえずそのままにしてあります。

設定

設定はWebからAdminでログインして行います。
設定画面は右上のレンチのアイコン -> 左のメニューの一番下のSettingsをクリックして行きます。

visibility設定

f:id:i178inaba:20161218171928p:plain

  • Default group visibilityはグループを作るときのデフォルトのvisibilityを設定します。

    • デフォルトでは設定されていないのでPrivateに設定します。
  • Restricted visibility levelsはユーザがプロジェクト等を作る時に設定できるvisibilityを制限します。

    • 自宅サーバでインターネットに公開しないので、念のためPrivateに制限しておきます。

Sign-up制限

Restricted visibility levelsと同様の理由で念のため制限しておきます。
Sign-upを制限すると新規ユーザを登録できなくなると思われるかもしれませんが、新規でユーザを追加するのはAdminでもできるので大丈夫です。

f:id:i178inaba:20161218171933p:plain

Sign-up enabledのチェックを外します。
これでログインページからSign-upフォームが消えます。

今日はここまで。