set setting reset

インフラ関連の小ネタと備忘録

富士そば 渋谷明治通り店

TLを眺めていたらなんだか目に止まってしまった富士そばアドベントカレンダー
18日めが空いていたので参加させていただきます。
富士そばしゅき度で言えば富士そばカレーうどんを1日3食したことがある程度の者です。 adventar.org

ぼくは google map にごはん写真が自動でアップロードされてしまう人なのですが、
もっとも閲覧回数の多い写真が 富士そば 渋谷明治通り店でいただいた赤富士 であり、
空腹と承認欲求を満たしてくれてシンプルに素晴らしいと思います。

というわけでおひひ富士そば

紅生姜天そば + いなりにしました。
美しポップなピンク色した紅生姜の爽やかな酸味と意外にオイリーな天ぷらと、どこにでもあるような質実剛健なおいなりさん、控えめに言って最強では。

また、渋谷明治通り店は老若男女問わない広い客層で、いつも店員さんが何やら楽しそうでとても雰囲気のよい店内となっております。
本日もごちそうさまでした。明日は musumi_takuma さんの担当です。よろしくおねがいします。

こちらからは以上です。

第35回 PostgreSQL 勉強会に行ってきました

初めて PostgreSQL 勉強会にお邪魔させていただきました。

connpass.com

殴り書きメモですが、記録として。

トランザクション入門

oss-db silver の出題範囲とのことでした

同時実行制御

  • 完了しない状態のデータが残ってしまう
    • 一連の処理が完了した上で COMMIT する
  • 一貫性がないデータが読めてしまう
  • 不正な更新データが書き込まれてしまう
    • dirty read
    • 一連の処理に割り込まない

トランザクションの使い方

  • 一貫した処理を保証するためのDB処理の集合
    • begin ~ commit or rollback
  • ACID 特性
    • 更新データは処理が完了した状態でのみ保存できる
    • 一貫性のあるで0多の読み書きを保証する
    • 同時に1つのトランザクションだけが実行しているように見える
    • 書き込んだデータは確実に保存する
  • begin は postgres 独自コマンド
  • トランザクションとエラー
  • SAVEPOINT による部分的 ROLLBACK
    • 使ってるアプリケーションはあるんだろうか。。
begin;
intert into ...
SAVEPOINT SP1;
insert into ...
-> ERROR
ROLLBACK TO SP1;
-> ROLLBACK

トランザクションの分離

  • 分離性
  • 分離レベル
    • Serializable
      • 遅い
    • Repeatable read
      • 直列化の失敗
    • Read committed
      • 反復不能読み取り
      • ファントムリード
        • 行の集合として見た場合、再度読み込むと1回目にはなかった行が読み込まれることがある
      • 直列化異常
  • 分離レベルの使い方
    • SET TRANSACTION ISOLATION LEVEL ****
  • 分離レベルと性能はトレードオフ

ロック


postgresql 10 がやってくる

logical replication

  • pgpool-II / slony-I
  • logical decoding
    • BDR(Bi-Direction Replication)
    • logical replication(postgresql10)
  • logical decoding
    • wal -> wal の変換プラグイン -> 論理ログ -> 論理ログの適用
  • logical replication
    • postgresql.conf
      • wal_level = logical
        • デカい
      • max_wal_senders
      • max_replicaiton_slots
    • pg_hba.conf
      • いつもの
    • create database
      • logical replication は DB 単位で設定
    • create table
    • logical replication の設定
      • 複製元
        • create publication
        • insert update delete が複製
        • 複製させない指定も可能
      • 複製元
        • create subscription
          • CONNECTION に接続文字列を書く
    • レプリケーション非対象
      • trancate
      • DDL
      • vacuum
    • meta-data
      • pg_stat_subscriptino
    • conflict
      • conflict が発生したら伝搬があぼーん
      • ぐえーむずい
    • 異なる構造間のレプリケーションが可能
      • ただし複製元にある列は複製先にもなければならない
      • 文字コード間の複製が可能
    • 応用編
  • declarative partitioning
  • others
    • GUC に多数いろいろ
    • パラレルクエリの改善
    • pg_hba_rules いいじゃん
    • hash index の wal 対応
      • uuid にはいいかも
      • イコール比較しかできない
    • JSON/JSONB + textsearch

togetter

ぬこ@横浜さんが当日の #jpug_study をまとめておられます。

togetter.com

vim のヤンクでクリップボードにコピーしたかった話、あるいは vim 8 へのアップグレード (mac)

環境

OS vim version
OSX 10.11.6 7.3

目的

macvim でヤンクしてクリップボードにいれたかった。

記事にしようと思ったきっかけ

よくある設定を .vimrc に書いてみましたが、有効にならず。

set clipboard=unnamed,autoselect
$ vim --version | grep clipboard
-clientserver -clipboard +cmdline_compl +cmdline_hist +cmdline_info +comments
 -xterm_clipboard -xterm_save

記録しておこうと思いました。


ぐぐった

homebrew を update して、 vim をインストールしなおすのが手っ取り早いようでした。 http://djangoapplab.com/43/


homebrew の update

まず、sudo brew update してみたら怒られました。

Error: Running Homebrew as root is extremely dangerous and no longer supported.
As Homebrew does not drop privileges on installation you would be giving all
build scripts full access to your system.

そうなんですね。ごめんなさい。
なので一般ユーザで update してみます。

$ brew update
Error: /usr/local is not writable. You should change the
ownership and permissions of /usr/local back to your
user account:
  sudo chown -R $(whoami) /usr/local

そうなんですね。
では、と chown して update すると進みはじめ、どかどか色々とインストールされていきます。

$ brew update
==> Homebrew has enabled anonymous aggregate user behaviour analytics.
Read the analytics documentation (and how to opt-out) here:
  http://docs.brew.sh/Analytics.html

Updated 3 taps (caskroom/cask, homebrew/binary, homebrew/core).
==> Cleaning up /Library/Caches/Homebrew...
Removing: /Library/Caches/Homebrew/gcc-5.3.0.tar.bz2... (91M)
Removing: /Library/Caches/Homebrew/gmp-6.1.0.el_capitan.bottle.tar.gz... (1M)
Removing: /Library/Caches/Homebrew/isl-0.15.el_capitan.bottle.tar.gz... (1.2M)
Removing: /Library/Caches/Homebrew/mpfr-3.1.3.el_capitan.bottle.tar.gz... (862.5K)
Removing: /Library/Caches/Homebrew/openssl-1.0.2g.el_capitan.bottle.tar.gz... (3.6M)
Removing: /Library/Caches/Homebrew/packer-0.10.0_1.el_capitan.bottle.tar.gz... (8.4M)
Removing: /Library/Caches/Homebrew/pkg-config-0.29.1.el_capitan.bottle.tar.gz... (235.8K)
Removing: /Library/Caches/Homebrew/ruby-build-20160330.tar.gz... (43.7K)
Removing: /Library/Caches/Homebrew/sshrc-0.5.tar.gz... (3.4K)
Removing: /Library/Caches/Homebrew/terraform-0.6.14.el_capitan.bottle.tar.gz.incomplete... (94.2M)
Removing: /Library/Caches/Homebrew/tig-2.1.1.el_capitan.bottle.2.tar.gz... (154.4K)
==> Migrating /Library/Caches/Homebrew to /Users/rriifftt/Library/Caches/Homebrew...
==> Deleting /Library/Caches/Homebrew...
中略

/Library/ からホームディレクトリにマイグレーションしています。とても親切です。
さらに Formulae も新しくなっているようでした。

==> Migrating d-bus to dbus
==> Unlinking d-bus
Moving to: /usr/local/Cellar/dbus
==> Linking dbus
Error: Could not link:
/usr/local/share/doc/homebrew

Please delete these paths and run `brew update`.
==> Migrating HOMEBREW_REPOSITORY (please wait)...
Error: Could not link:
/usr/local/share/doc/homebrew

Please delete these paths and run `brew update`.
==> Migrated HOMEBREW_REPOSITORY to /usr/local/Homebrew!
Homebrew no longer needs to have ownership of /usr/local. If you wish you can
return /usr/local to its default ownership with:
  sudo chown root:wheel /usr/local

最後には ↑ のログが出力されました。
ご案内の通りにします。

$ rm -rf /usr/local/share/doc/homebrew
$ brew update
Already up-to-date.

成功しました。
さらにご案内の通り /usr/local の権限を元に戻しておきます。

$ sudo chown root:wheel /usr/local

vim のインストール

vim は upgrade すればいいでしょと思ってやってみるとインストールされていないって言われました。

$ brew upgrade vim
Error: vim not installed

clipboard が有効にならないのはこれが原因っぽいような。
ないなら install します。

$ brew install vim
==> Installing dependencies for vim: perl, readline, libyaml, openssl, ruby, pkg-config, sqlite, gdbm, python
==> Installing vim dependency: perl
==> Downloading https://homebrew.bintray.com/bottles/perl-5.24.0_1.el_capitan.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring perl-5.24.0_1.el_capitan.bottle.1.tar.gz
略
==> Pouring vim-8.0.0329.el_capitan.bottle.tar.gz
🍺  /usr/local/Cellar/vim/8.0.0329: 1,713 files, 23.3M

vim 8 が降ってきました。


バイナリの切替

clipboard が有効になっているか確認してみると、変わっていません。

$ vim --version | grep clipboard
-clientserver -clipboard +cmdline_compl +cmdline_hist +cmdline_info +comments
 -xterm_clipboard -xterm_save

vim インストール時のログを見ると別の場所にインストールされたようです。
こちらのバイナリで確認してみると有効になっています。

$ /usr/local/Cellar/vim/8.0.0329/bin/vim --version | grep clipboard
+clipboard       +job             +path_extra      +user_commands
+eval            +mouse_dec       +statusline      -xterm_clipboard

入れ替える必要がありそうなので入れ替えてみます。

$ mv /usr/local/bin/vim{,.bk}
$ ln -s /usr/local/Cellar/vim/8.0.0329/bin/vim /usr/local/bin/vim

vim を起動する

と、エラーが出ました。

$ vim

Command terminated

Error detected while processing /Users/rriifftt/.vim/bundle/open-browser.vim/plugin/openbrowser.vim:
line   19:
E484: Can't open file /var/folders/g5/hsvhp9155l1c6sdc01rgqd4jwp37f2/T/v7qsLTu/0
Press ENTER or type command to continue

さらに iTerm で新しいタブを開くとローカルホストにログインできなくなりました。

Last login: Tue Feb 14 11:15:10 on ttys019
dyld: Library not loaded: /usr/local/opt/readline/lib/libreadline.6.dylib
  Referenced from: /usr/local/bin/bash
  Reason: image not found

やさしい人に readline を切り替えるとよくなるかもしれないと教えてもらいました。
確かに brew update した時に readline が更新されています。

==> Pouring readline-7.0.1.el_capitan.bottle.tar.gz
==> Caveats
This formula is keg-only, which means it was not symlinked into /usr/local.

macOS provides the BSD libedit library, which shadows libreadline.
In order to prevent conflicts when programs look for libreadline we are
defaulting this GNU Readline installation to keg-only.


For compilers to find this software you may need to set:
    LDFLAGS:  -L/usr/local/opt/readline/lib
    CPPFLAGS: -I/usr/local/opt/readline/include

==> Summary
🍺  /usr/local/Cellar/readline/7.0.1: 46 files, 2M
==> Installing vim dependency: libyaml
==> Downloading https://homebrew.bintray.com/bottles/libyaml-0.1.7.el_capitan.bottle.tar.gz

readline の切替

readline を切り替えてみます。

$ brew switch readline 7.0
Error: readline does not have a version "7.0" in the Cellar.
Versions available: 6.3.6, 6.3.8, 7.0.1

コマンドエラーになってしまいましたが、3 つのバージョンがあることがわかりました。
そして現在のバージョンは以下です。

$ brew list readline
/usr/local/Cellar/readline/7.0.1/include/readline/ (8 files)
/usr/local/Cellar/readline/7.0.1/lib/libhistory.7.0.dylib
/usr/local/Cellar/readline/7.0.1/lib/libreadline.7.0.dylib
/usr/local/Cellar/readline/7.0.1/lib/ (6 other files)
/usr/local/Cellar/readline/7.0.1/share/doc/ (3 files)
/usr/local/Cellar/readline/7.0.1/share/info/ (3 files)
/usr/local/Cellar/readline/7.0.1/share/man/ (2 files)
/usr/local/Cellar/readline/7.0.1/share/readline/ (15 files)

最新版は色々とアレなんでしょうか。
6.3.8 に切り替えてみます。

$ brew switch readline 6.3.8
Cleaning /usr/local/Cellar/readline/6.3.6
Cleaning /usr/local/Cellar/readline/6.3.8
Cleaning /usr/local/Cellar/readline/7.0.1
Opt link created for /usr/local/Cellar/readline/6.3.8

再度 vim を起動する

と、エラーなく起動できました。
iTerm の新規タブも問題なく開くことができています。

いまのところはこれで問題なさそうです。

boto3 で指定された日付以前の snapshot を削除する

という python script を晒してみます。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
指定された日付以前の snapshot を削除します
ただし ami に紐付いている snapshot は削除しません

example:
    $ python delete_expired_snapshots.py -p profile_name -o owner_id -e expire_date (--dry-run True|False)
"""

import boto3
import pytz
from argparse import ArgumentParser
from datetime import datetime, timedelta


def delete_expired_snapshots(profile, owner_id, expire_date, dry_run=False,):
    session = boto3.Session(profile_name=profile)
    client = session.client("ec2")
    snapshots = client.describe_snapshots(OwnerIds=[owner_id])
    """
    response example:
        "Snapshots": {
            u'Description': '***********',
            u'Encrypted': True,
            u'VolumeId': 'vol-*****',
            u'KmsKeyId': 'arn:aws:kms:region:*******:key/***********',
            u'State': 'completed',
            u'VolumeSize': **,
            u'Progress': '100%',
            u'StartTime': datetime.datetime(yyyy, mm, dd, hh, MM, SS, tzinfo=tzutc()),
            u'SnapshotId': 'snap-************',
            u'OwnerId': '*******'
        },...
    """
    expired_snapshot_ids = [ s["SnapshotId"] for s in snapshots["Snapshots"]
        if s["StartTime"] < expire_date ]
    for expired_snapshot_id in expired_snapshot_ids:
        try:
            res = client.delete_snapshot(SnapshotId=expired_snapshot_id, DryRun=dry_run)
            if res["ResponseMetadata"]["HTTPStatusCode"] == 200:
                print("INFO. delete Succeed id:{0}".format(expired_snapshot_id))
            else:
                print("ERROR. delete Failed id:{0} status_code:{1}".format(
                    expired_snapshot_id, res))
        except Exception as e:
            print("ERROR. exception occurd id:{0}".format(expired_snapshot_id))
            print("Exception. {0}".format(e))


def arg_parse_for_delete_expired_snapshots():
    parser = ArgumentParser()
    parser.add_argument(
        "-p", "--profile", dest="profile",
        type=str, required=True,
        help="specify snapshots aws profile"
    )
    parser.add_argument(
        "-o", "--owner-id", dest="owner_id",
        type=str, required=True,
        help="specify snapshots owner_id"
    )
    parser.add_argument(
        "-e", "--expire-date", dest="expire_date",
        type=int, required=True,
        help="specify expire date"
    )
    parser.add_argument(
        "--dry-run", dest="dry_run",
        type=bool,
        default=False,
        help="dry run switch"
    )
    return parser.parse_args()
    

if __name__ == "__main__":
    p = arg_parse_for_delete_expired_snapshots()
    expire_date = datetime.now(pytz.utc) - timedelta(p.expire_date)
    delete_expired_snapshots(p.profile, p.owner_id, expire_date, p.dry_run)

argparse をつかってコマンドライン引数をよしなにする

よくつかうのでメモとして残してみます。

argparse とは

python の組み込みライブラリで、引数をよしなにしてくれるいい人です。
python 2.7 から追加されました。

15.4. argparse — コマンドラインオプション、引数、サブコマンドのパーサー — Python 2.7.x ドキュメント

よくやること

コマンドラインで実行する系のスクリプトでオプションを指定するときなどに便利なので、そのように使うことが多いです。
ロングオプションを指定したり、変数に自動で格納してくれたり、位置をきにしなくて良かったり、 --help で Usage を自動で生成したりしてくれます。

例えば以下のようなコードを動かしてみます。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from argparse import ArgumentParser

def argument_parser():
    parser = ArgumentParser(description="this is description")
    parser.add_argument(
          "-n", "--neko", dest="neko",
          type=str,
          help="specified neko")
    return parser.parse_args()


if __name__ == '__main__':
    p = argument_parser()
    print(p.neko)

help を表示してみます。

$ python test.py --help
usage: test.py [-h] -n NEKO

this is description

optional arguments:
  -h, --help            show this help message and exit
  -n NEKO, --neko NEKO  specified neko

オプションを正しく指定すると以下の様に普通に print() されます。

$ python test.py -n saba
saba
$ python test.py --neko mike
mike

必須オプションをつくる

require=True を指定すると必須オプションをつくれます。

          "-n", "--neko", dest="neko",
          type=str,
+          required=True,
          help="specified neko")

引数を与えずに実行すると、エラーになります。

$ python test.py
usage: test.py [-h] -n NEKO
test.py: error: argument -n/--neko is required

オプションの選択肢を固定する

choices=[] を使うと選択肢を固定できます。

          "-n", "--neko", dest="neko",
          type=str,
          required=True,
+          choices=["saba", "mike"],
          help="specified neko")

正しく実行すると、普通です。

$ python test.py --neko saba
saba
01:50:41 ~
$ python test.py --neko mike
mike

choices にないオプションを与えるとエラーになります。

$ python test.py --neko kuroneko
usage: test.py [-h] -n {saba,mike}
test.py: error: argument -n/--neko: invalid choice: 'kuroneko' (choose from 'saba', 'mike')

順番をきにしなくてよい

2 つのオプションを定義してみます。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from argparse import ArgumentParser

def argument_parser():
    parser = ArgumentParser(description="this is description")
    parser.add_argument(
          "-n", "--neko", dest="neko",
          type=str,
          required=True,
          choices=["saba", "mike"],
          help="specified neko")
    parser.add_argument(
         "-i", "--inu", dest="inu",
         type=str, help="specified inu")
    return parser.parse_args()


if __name__ == '__main__':
    p = argument_parser()
    print(p.neko)
    print(p.inu)

help を見てみると、オプションが自動で追加されています。

$ python test.py --help
usage: test.py [-h] -n {saba,mike} [-i INU]

this is description

optional arguments:
  -h, --help            show this help message and exit
  -n {saba,mike}, --neko {saba,mike}
                        specified neko
  -i INU, --inu INU     specified inu

引数の位置を変えて実行しても結果は同じになります。らくちん。

$ python test.py -n mike --inu shiba
mike
shiba

$ python test.py -i shiba --neko saba
saba
shiba

おわり。
次は流行りの click を触ってみます。

CentOS7 で再起動後に vm.swappiness の設定が元に戻ってしまう

環境

AWS EC2 の CentOS 公式 AMI です。

CentOS 7 (x86_64) - with Updates HVM on AWS Marketplace

事象

  • デフォルトは vm.swappiness = 30
  • sysctl -w vm.swappiness=任意の値 すると任意の値に変更可能
  • sysctl -p するも reboot 後に元に戻ってしまう

原因

こちらで言及されていました。

CentOs7 vm.swappiness cannot be set on boot - CentOS

tuned によって上書きされるようです。

対応

tuned の設定ファイルは /usr/lib/tuned 配下にあるそうですので grep してみます。

#  find /usr/lib/tuned -name '*.conf' -type f -exec grep "vm.swappiness" {} \+
/usr/lib/tuned/latency-performance/tuned.conf:vm.swappiness=10
/usr/lib/tuned/throughput-performance/tuned.conf:vm.swappiness=10
/usr/lib/tuned/virtual-guest/tuned.conf:vm.swappiness = 30

デフォルトでは 30 に設定されていましたので、 /usr/lib/tuned/virtual-guest/tuned.conf の値を変更したところ、意図した通りに設定されました。 一応、編集したファイルを下記に記載します。

#
# tuned configuration
#

[main]
include=throughput-performance

[sysctl]
# If a workload mostly uses anonymous memory and it hits this limit, the entire
# working set is buffered for I/O, and any more write buffering would require
# swapping, so it's time to throttle writes until I/O can catch up.  Workloads
# that mostly use file mappings may be able to use even higher values.
#
# The generator of dirty data starts writeback at this percentage (system default
# is 20%)
vm.dirty_ratio = 30

# Filesystem I/O is usually much more efficient than swapping, so try to keep
# swapping low.  It's usually safe to go even lower than this on systems with
# server-grade storage.
- vm.swappiness = 30
+ vm.swappiness = 5

python でディレクトリ配下の最新のファイル名(フルパス)を取得する

前提

最新かどうかはファイルの最終変更日時 = mtime で判定します。

準備

こんな感じでファイルを作成します

$ for ((i=0;i>10;i++)); do touch $i.txt; sleep 5; done

最終変更日は以下の様になりました。
9.txt の最終変更日時が最も新しいものになっています。

$  stat -f "%N %m" *.txt
0.txt 1465450197
1.txt 1465450202
2.txt 1465450207
3.txt 1465450212
4.txt 1465450217
5.txt 1465450222
6.txt 1465450227
7.txt 1465450232
8.txt 1465450237
9.txt 1465450242

表題のことをする

python スクリプトはこんな感じです。

import os
from glob import glob


def get_latest_modified_file_path(dirname):
  target = os.path.join(dirname, '*')
  files = [(f, os.path.getmtime(f)) for f in glob(target)]
  latest_modified_file_path = sorted(files, key=lambda files: files[1])[-1]
  return latest_modified_file_path[0]


if __name__ == '__main__':
  dirname = "/hoge"
  print(get_latest_modified_file_path(dirname))

実行するとフルパスが取得できます。

$  python get_latest_modified_file_path.py
/hoge/9.txt