特定のポート番号で動いているWebサーバーをKillする

例えば5000番のポートで動いているWebサーバーをKillしたいときは

fuser -k 5000/tcp

とすればKillできる。今まで

ps ax | grep hoge

でプロセス番号を確認してからKillしてたからこれで時間短縮ができる。

ちなみにfuserはファイルやソケットを使用しているプロセスを特定するのに使われるらしい。

Don’t break the chain メソッドを参考にチェーンドライブというiOSアプリをリリースしました。

突然ですが,二ヶ月ほど前にApp Storeに提出したチェーンドライブというiPhoneアプリの告知をします。 (告知が遅れたのはPush通知周りの不具合の修正のためです…)

きっかけはライフハッカーのDon’t break the chain について 書かれていた記事(日本でもこちらの記事で言及されています) を読んで、早速自分でも実践したいけど適切なアプリが市場に出回ってなかったという些細なものでした。

Don’t break the chain とは自分が毎日の習慣にしたいと考えていることを選んで、それを実行した日はチェックオフしていくだけというシンプルなもの。 その習慣がなるべく途絶えないようにやるうちに、いつのまにか習慣が身につくという方法です。

チェーンドライブは特徴を列挙するとこんな感じです。

  • 当日チェックマークをつけるのを忘れてしまったら、もうチェックマークを付けることができなくなる。(Don’t break感を出したい)
  • 複数のタスクを登録できることができる。
  • その日のうちにチェックマークがついていないと、Push通知で知らせてくれる。
  • 継続日数に応じてタスクの色が変更する。

2ヶ月間自分が使ってみた感想

このアプリをリリースしてから約二ヶ月の間毎日使い続けているのですが、自分が習慣にしたいことを目に見える形にしてそれをこなすとチェックをつけるという 行為は想像以上に自分の意識が高くなるのが実感出来ましたし、特にチェックマークをその日つけ忘れたらそのタスクはもうチェックを付けることができなくなる という機能が効果的でした。このおかげでより「毎日するんだ!」という意識を高く持てています。

ちなみに自分が毎日続けられているタスクは

  • プログラミング
  • 英語のPodcastを聞く
  • ペンと紙を使う

です。このアプリを使うようになって、実際に毎日続けられているので始める前より確実にレベルが上がったことを実感しています。 無料ですのでもしよかったらチェーンドライブをダウンロードしてタスクを習慣化してみてください。

Alembicで変更したテーブルのカラムを自動で検知してマイグレーションファイルを生成する

Alembicを使ってDBのマイグレーションを行っているけど、自動で変更されたカラム名を判定して勝手にmigrationファイルを作ってる

alembic revision --autogenerate -m "upgrade"

という–autogenerateというオプションが有るんだけど、そのままだと動作しない。

動作させるにはenv.pyを以下の様なコードを追記しないといけない。

env.py

# create_appはFlaskのappを返すメソッド
from basic_app import db, create_app

app = create_app()
config = context.config

app.config[“SQLALCHEMY_DATABASE_URI”] = "your_db_path"
config.set_main_option(“sqlalchemy.url”,app.config[“SQLALCHEMY_DATABASE_URI”])
target_metadata = db.metadata

あとは

alembic upgrade head

でデータベースに変更を適用するだけ。

とても便利なライブラリだけど、 注意点としてカラム名の変更やunique等、制約の追加を判定することはできないので 、その時は手動で更新しないといけない。

Flask-SQLAlchemyの使い方

最近仕事でFlask-SQLAlchemyをよく使うので自分のためにメモしておく。

Setup

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)

...
db.create_all()

Basic (Insert,Update,Delete)

Insert

user = User(name="foo")
db.session.add(user)
db.session.commit()

Update

user = db.session.query(User).get(1)
user.name = "foooo"
db.session.flush()

Delete

user = db.session.query(User).get(1)
db.session.delete(user)
db.session.commit()

//Delete children of the user
user.posts.remove()

Queryの例

all()

users = db.session.query(User).all()

filter_by(**kwargs)

user = db.session.query(User).filter_by(name="foo").first()

get(id)

user = db.session.query(User).get(1)

Relationshipの例

One to Many (一対多)

ユーザーが複数の投稿を持っているケースを想定。

class User(db.Model):
    __tablename__ = "users"
    id = db.Column(db.Integer, primary_key=True)
    posts = db.retionship("Post",backref="uesr",lazy="dynamic")


class Post(db.Model):
    __tablename__ = "posts"
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

Many To Many (多対多)

投稿した記事がタグを持っていて、タグは複数のタグを持っているケースを想定。

posttags = db.Table("posttags",
        db.Column("post_id",db.Integer,db.ForeignKey("posts.id")),
        db.Column("tag_id",db.Integer,db.ForeignKey("tags.id"))
        )

class Post(db.Model):
    __tablename__ = "posts"
    id = db.Column(db.Integer, primary_key=True)
    tags = db.relationship("Post",secondary=posttags,backref="posts")


class Tag(db.Model):
    __tablename__ = "tags"
    id = db.Column(db.Integer, primary_key=True)

GunicornをFabric経由で操作する

Gunicornで動いているアプリをサーバー側で起動、再起動ができるようにした。 プロセスを止めるにはpidを指定してkillすればいいということを学んだ。

gunicorn.conf.py

usr/bin/python
gunicorn.conf.py

bind = "0.0.0.0:5000"
workers = 2
worker_class = 'sync'
max_requests = 1000
timeout = 30
keep_alive = 2
preload = True
daemon = True

start.sh

GUNICORN=/usr/bin/gunicorn
ROOT=/your/app/path
PID=/var/run/gunicorn/your.pid
APP=run:app

if [ -f $PID ]; then rm $PID; fi
    cd $ROOT
    source venv/bin/activate
    exec $GUNICORN -c $ROOT/gunicorn.conf.py –pid=$PID $APP

fabfile.py

#coding: utf-8
from fabric.api import run,env,local,settings
from fabric.operations import sudo
from fabric.context_managers import cd
import os
import subprocess

from fabric.api import env, run
env.use_ssh_config = True
env.hosts = ["your ip address"]
env.key_filename = "/root/.ssh/authorized_keys"
env.user = "username"
env.password = "password"


def start():
    with settings():
        with cd("/your/path"):
            sudo("""
            source start.sh
            """,pty=False)

def stop():
    with settings():
        pid = get_pid()
        sudo("kill {}".format(pid))

def restart():
    try:
        stop()
    except:
        print("There isn't pid")
    start()

これで fab start/stop/restartで自由に再起動を行うことができる。

メモ

  • タスクをバックグラウンドで実行させたい時は pty=False としないと動作しない。