富士そば 渋谷明治通り店
TLを眺めていたらなんだか目に止まってしまった富士そばアドベントカレンダー。
18日めが空いていたので参加させていただきます。
富士そばしゅき度で言えば富士そばのカレーうどんを1日3食したことがある程度の者です。
adventar.org
ぼくは google map にごはん写真が自動でアップロードされてしまう人なのですが、
もっとも閲覧回数の多い写真が 富士そば 渋谷明治通り店でいただいた赤富士 であり、
空腹と承認欲求を満たしてくれてシンプルに素晴らしいと思います。
というわけでおひひ富士そば。
おひひ富士そば pic.twitter.com/DBRRuVwXgl
— ~/ (@rriifftt) 2017年12月18日
紅生姜天そば + いなりにしました。
美しポップなピンク色した紅生姜の爽やかな酸味と意外にオイリーな天ぷらと、どこにでもあるような質実剛健なおいなりさん、控えめに言って最強では。
また、渋谷明治通り店は老若男女問わない広い客層で、いつも店員さんが何やら楽しそうでとても雰囲気のよい店内となっております。
本日もごちそうさまでした。明日は musumi_takuma さんの担当です。よろしくおねがいします。
こちらからは以上です。
第35回 PostgreSQL 勉強会に行ってきました
初めて PostgreSQL 勉強会にお邪魔させていただきました。
殴り書きメモですが、記録として。
トランザクション入門
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回目にはなかった行が読み込まれることがある
- 直列化異常
- Serializable
- 分離レベルの使い方
- SET TRANSACTION ISOLATION LEVEL ****
- 分離レベルと性能はトレードオフ
ロック
- トランザクションを実現する仕組み
- ロックはDBMSが自動で獲得、開放する
- 明示的ロックもあるよ
- ロックの種類
- http://www.postgresql.jp/document/9.3/html/explicit-locking.html
- レベル
- 表、行、ページなど
- モード
- 共有(share)
- 複数のトランザクションでアクセスできる
- 占有(exclusive)
- 排他モード
- 共有(share)
- 表レベルロック
- Share update
- share update exclusive
- access exclusive
- 行レベルロック
- FOR UPDATE
- FOR NO KEY UPDATE
- FOR SHARE …
- デッドロック
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
- wal_level = logical
- pg_hba.conf
- いつもの
- create database
- logical replication は DB 単位で設定
- create table
- logical replication の設定
- 複製元
- create publication
- insert update delete が複製
- 複製させない指定も可能
- 複製元
- create subscription
- CONNECTION に接続文字列を書く
- create subscription
- 複製元
- レプリケーション非対象
- trancate
- DDL
- vacuum
- meta-data
- pg_stat_subscriptino
- conflict
- conflict が発生したら伝搬があぼーん
- ぐえーむずい
- 異なる構造間のレプリケーションが可能
- ただし複製元にある列は複製先にもなければならない
- 異文字コード間の複製が可能
- 応用編
- マルチマスタ
- マルチバージョン
- マルチプラットフォーム
- postgresql.conf
- declarative partitioning
- others
- GUC に多数いろいろ
- パラレルクエリの改善
- pg_hba_rules いいじゃん
- hash index の wal 対応
- uuid にはいいかも
- イコール比較しかできない
- JSON/JSONB + textsearch
togetter
ぬこ@横浜さんが当日の #jpug_study をまとめておられます。
vim のヤンクでクリップボードにコピーしたかった話、あるいは vim 8 へのアップグレード (mac)
環境
OS | vim version |
---|---|
OSX 10.11.6 | 7.3 |
目的
mac の vim でヤンクしてクリップボードにいれたかった。
記事にしようと思ったきっかけ
よくある設定を .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 の設定が元に戻ってしまう
環境
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
表題のことをする
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