Octopress Blog

自分のためのまとめブログ

Redmine

メモ書き

あまりに利用する人数が増えると負荷が問題になってくるみたい。その場合は有償のJIRAとか 使うことになりそう。ただ想定している利用人数は数名程度なのでRedmineでも十分なはず。

リンク

http://daipresents.com/2011/redmineが1000人のエンジニアに使われるまでのこと/

Python

Python入門 の勉強

開発環境の準備

PyDevをインストールして使う

Eclipseのインストール


Pythonのタイプとオブジェクト

特徴とぱっと分からないものだけ書いていく

  • オブジェクト -> Pythonのすべてのデータはオブジェクト
  • タイプ -> オブジェクトの一種

数値

整数型、浮動小数点型、複素数型などが使える

  • 余り
1
2
>>> 10%3
1
  • 複素数
1
2
>>> (1+2j) + (2+3j)
(3+5j)
  • 乱数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> import random

>>> random.random()
0.89164962407887893     * 0 - 1 の間の浮動小数がランダムに出力される

>>> L=[1,2,3,4,5]       * 1 - 5 の間の整数がランダムに出力される
>>> random.choice(L)
1
>>> random.choice(L)
1
>>> random.choice(L)
4
>>> random.choice(L)
5
  • mathモジュール
    数学的な演算ができる
1
2
3
>>> import math
>>> math.pi             * 円周率の計算
3.1415926535897931

文字列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
>>> a = 'ABCdE'
>>> a
'ABCdE'

>>> a[0]    * 先頭の文字
'A'
>>> a[4]
'E'
>>> a[-1]   * 最後尾の文字
'E'
>>> a[-5]
'A'
>>> a[1:2]  * 2文字目のみ表示
'B'
>>> a[1:3]  * 2-3文字目を表示
'BC'
>>> len(a)  * 文字数表示
5
>>> a.find('C')  * 文字列中にCが出てくるのが何文字目かを出す(出力結果+1文字目に出現する)
2
>>> a.upper()  * すべて大文字にする
'ABCDE'
  • アトリビュートの取得と関数のhelp表示
1
2
3
4
5
6
7
8
9
10
11
>>> dir(a)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

>>> help(a.join)
Help on built-in function join:

join(...)
    S.join(iterable) -> string

    Return a string which is the concatenation of the strings in the
    iterable.  The separator between elements is S.
  • フォーマット
1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> '{0} FG'.format(a)
'ABCdE FG'

>>> x = 10/3     * 計算結果は整数になる
>>> x
3
>>> x = 10.0/3   * 計算結果は浮動小数になる
>>> x
3.3333333333333335

>>> '{0:.3f}'.format(x)
'3.333'
>>> '{0:.1f}'.format(x)
'3.3'

リスト

かっこで要素をかこむ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
>>> L = [2,4,6,8,10]
>>> L[1:3]
[4, 6]

>>> M = L + [1,3,5]
>>> M
[2, 4, 6, 8, 10, 1, 3, 5]

>>> M.sort()
>>> M
[1, 2, 3, 4, 5, 6, 8, 10]

>>> M.append(100)
>>> M
[1, 2, 3, 4, 5, 6, 8, 10, 100]

>>> M.pop()
100
>>> M
[1, 2, 3, 4, 5, 6, 8, 10]

>>> len(M)
8

>>> [1,1,1,2,2,3].count(1)
3
>>> [1,1,1,2,2,3].count(2)
2

>>> L = [ 1, 'Hello', 3.14 ]
>>> L[1]
'Hello'
>>> L[1][1]
'e'

>>> N = [[1,2,3], 'Hello', {'name':'Keisuke Oyama','age':37}]
>>> N[1]
'Hello'

>>> N[2]
{'age': 37, 'name': 'Keisuke Oyama'}
>>> N[2]['age']
37
  • 内包表記(Comprehensions) 簡単にあるリストから条件に適合するリストを作成できる。
1
2
3
4
5
6
7
8
9
>>> L = [1,2,3,4,5]
>>> [x for x in L if x > 2]
[3, 4, 5]
>>> [3*x for x in L if x > 2]
[9, 12, 15]

>>> L = ['hello','world']
>>> [x.upper() for x in L]
['HELLO', 'WORLD']

タプル(Tuple)

  • 複数のオブジェクトをひとつにまとめたもの
  • ()でくくったものがタプルだが、必須ではない。でもかっこでくくったほうがわかりやすくて親切
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> A = ('Keisuke', 37)
>>> A
('Keisuke', 37)

>>> a, b = A
>>> a
'Keisuke'
>>> b
37

>>> A = ('Keisuke', )   * オブジェクト1個のタプルも作成可能
>>> A
('Keisuke',)

>>> A[0] = 'Shinya'     * 要素への代入ができないこところがリストと違う
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

ディクショナリ (dictionary)

  • マッピングタイプのひとつ
  • キーと値のペアを保持するオブジェクト
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
>>> D = {'name':'Keisuke Oyama', 'age':37}
>>> D['name']
'Keisuke Oyama'


>>> E['car'] = 'Sianna'
>>> E['make'] = 'Toyota'
>>> E
{'car': 'Sianna', 'make': 'Toyota'}

>>> dir(D)
['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']

>>> D.keys()
['age', 'name']
>>> D.values()
[37, 'Keisuke Oyama']

>>> D.has_key('name')
True
>>> D.has_key('address')
False

>>> 'name' in D    * 上と同じ
True
>>> 'address' in D
False
>>>

セット(set)

順序付けされていないユニークな要素で構成された、コレクション

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
>>> L = ['a', 'a', 'b', 'c', 'c', 'a']
>>> S = set(L)
>>> S
set(['a', 'c', 'b'])   * 重複がなくなっている

>>> M = set('Hello')
>>> M
set(['H', 'e', 'l', 'o'])  * 文字列からセットを作成


>>> A = set('Hello')
>>> B = set('World')
>>> A
set(['H', 'e', 'l', 'o'])
>>> B
set(['d', 'r', 'o', 'W', 'l'])

>>> A - B
set(['H', 'e'])

>>> A | B
set(['e', 'd', 'H', 'l', 'o', 'r', 'W'])

>>> A & B
set(['l', 'o'])

>>> A ^ B
set(['e', 'd', 'H', 'r', 'W'])  * ABそれぞれに存在しているものを表示
 loAB両方に含まれているので表示しない。それ以外は表示

JSONファイルの利用

リンク

デコレータ

roles

権限を設定できる。実行時にホスト名やユーザ名などの引数指定を無くすことが目的。

1環境1サーバ

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/python
# coding: utf-8

from fabric.api import run, env
from fabric.decorators import roles

env.roledefs['dev'] = ['devserver1']

@roles('dev')
def host_name():
        run('uname -n')

実行結果

1
2
3
4
5
6
7
8
9
10
$ fab -f fabfile_roles.py -u ftakao2007 host_name
[devserver1] Executing task 'host_name'
[devserver1] run: uname -n
[devserver1] Login password for 'ftakao2007':
[devserver1] out: devserver1
[devserver1] out:


Done.
Disconnecting from devserver1... done.

1環境複数サーバ

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/python
# coding: utf-8

from fabric.api import run, env
from fabric.decorators import roles

env.roledefs['dev'] = ['devserver1', 'devserver2']

@roles('dev')
def host_name():
        run('uname -n')

実行結果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ fab -f fabfile_roles.py -u ftakao2007 host_name
[devserver1] Executing task 'host_name'
[devserver1] run: uname -n
[devserver1] Login password for 'ftakao2007':
[devserver1] out: devserver1
[devserver1] out:

[devserver2] Executing task 'host_name'
[devserver2] run: uname -n
[devserver2] out: devserver2
[devserver2] out:


Done.
Disconnecting from devserver2... done.
Disconnecting from devserver1... done.

複数環境複数サーバ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/python
# coding: utf-8

from fabric.api import run, env
from fabric.decorators import roles

env.roledefs = {
    'dev': ['devserver1', 'devserver2'],
    'stg': ['stgserver1', 'stgserver2']
}

@roles('dev')
def host_name():
       run('uname -n')

@roles('stg')
def host_name2():
       run('uname -n')

実行結果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$ fab -f fabfile_roles.py -u ftakao2007 host_name
[devserver1] Executing task 'host_name'
[devserver1] run: uname -n
[devserver1] Login password for 'ftakao2007':
[devserver1] out: devserver1
[devserver1] out:

[devserver2] Executing task 'host_name'
[devserver2] run: uname -n
[devserver2] out: devserver2
[devserver2] out:


Done.
Disconnecting from devserver2... done.
Disconnecting from devserver1... done.

$ fab -f fabfile_roles.py -u ftakao2007 host_name2
[stgserver1] Executing task 'host_name2'
[stgserver1] run: uname -n
[stgserver1] Login password for 'ftakao2007':
[stgserver1] out: stgserver1
[stgserver1] out:

[stgserver2] Executing task 'host_name2'
[stgserver2] run: uname -n
[stgserver2] out: stgserver2
[stgserver2] out:


Done.
Disconnecting from stgserver1... done.
Disconnecting from stgserver2... done.

ユーザも設定

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/python
# coding: utf-8
from fabric.api import run, env
from fabric.decorators import roles

env.roledefs['dev'] = ['devserver1']
env.user = 'ftakao2007'

@roles('dev')
def host_name():
        run('uname -n')

実行結果

1
2
3
4
5
6
7
8
9
10
$ fab -f fabfile_roles.py host_name
[devserver1] Executing task 'host_name'
[devserver1] run: uname -n
[devserver1] Login password for 'ftakao2007':
[devserver1] out: devserver1
[devserver1] out:


Done.
Disconnecting from devserver1... done.

リンク


task

fabricが実行できるタスクを色々制御できる

基本

1
2
3
4
5
6
7
8
9
#!/usr/bin/python
# coding: utf-8

from fabric.api import run
from fabric.decorators import task

@task
def host_type():
        run('uname -s')

エイリアス設定

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/python
# coding: utf-8

from fabric.api import run
from fabric.decorators import task

@task
def host_type():
        run('uname -s')

@task(alias='remote_host_name')
def host_name():
        run('uname -n')

実行結果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
$ fab -f fabfile_task.py --list
Available commands:

    host_name
    host_type
    remote_host_name

 エイリアスで登録したコマンドが実行可能になっている

$ fab -f fabfile_task.py -H devserver1 -u ftakao2007 host_type
[devserver1] Executing task 'host_type'
[devserver1] run: uname -s
[devserver1] Login password for 'ftakao2007':
[devserver1] out: SunOS
[devserver1] out:


Done.
Disconnecting from devserver1... done.

$ fab -f fabfile_task.py -H devserver1 -u ftakao2007 host_name
[devserver1] Executing task 'host_name'
[devserver1] run: uname -n
[devserver1] Login password for 'ftakao2007':
[devserver1] out: devserver1
[devserver1] out:


Done.
Disconnecting from devserver1... done.

$ fab -f fabfile_task.py -H devserver1 -u ftakao2007 remote_host_name
[devserver1] Executing task 'remote_host_name'
[devserver1] run: uname -n
[devserver1] Login password for 'ftakao2007':
[devserver1] out: devserver1
[devserver1] out:


Done.
Disconnecting from devserver1... done.
 host_nameと同じ実行結果

リンク


モジュール分割

rolesとtaskを組み合わせてモジュール分割

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[fabfile.py]
#!/usr/bin/python
# coding: utf-8

import dev_mod


[dev_mod.py]
from fabric.api import run, env
from fabric.decorators import task, roles

env.roledefs['dev'] = ['devserver1']
env.user = 'ftakao2007'

@task
@roles('dev')
def host_name():
        run('uname -n')

ファイル名を「fabfile.py」にするとコマンド実行時にファイルを引数として与えなくてもよくなる。
実行結果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ fab --list
Available commands:

    dev_mod.host_name

$ fab dev_mod.host_name
[devserver1] Executing task 'dev_mod.host_name'
[devserver1] run: uname -n
[devserver1] Login password for 'ftakao2007':
[devserver1] out: devserver1
[devserver1] out:


Done.
Disconnecting from devserver1... done.

メインのファイルがものすごくシンプルになりました。
いずれはモジュールからパッケージにしたほうがいいのかな。

リンク

定数の実装

参考リンクのとおり

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[const.py]
class _const:
    class ConstError(TypeError): pass
    def __setattr__(self,name,value):
        if self.__dict__.has_key(name):
            raise self.ConstError, "Can't rebind const(%s)"%name
        self.__dict__[name]=value
import sys
sys.modules[__name__]=_const()

[fabfile.py]
#!/usr/bin/python
# coding: utf-8

from fabric.api import run
import const

const.DEV_SSH_PATH = "/usr/bin"
const.DEV_SUDO_PATH = "/usr/local/bin"

def check_df():
  run("{SUDO_PATH}/sudo {SSH_PATH}/ssh nasserver1 df -h vol_takao".format(SSH_PATH=const.DEV_SSH_PATH,SUDO_PATH=const.DEV_SUDO_PATH))

実行結果

1
2
3
4
5
6
7
8
9
10
11
12
$ fab -H devserver1 -u ftakao2007 check_df
[devserver1] Executing task 'check_df'
[devserver1] run: /usr/local/bin/sudo /bin/ssh nasserver1 df -h vol_takao
[devserver1] Login password for 'ftakao2007':
[devserver1] out: Filesystem               total       used      avail capacity  Mounted on
[devserver1] out: /vol/vol_takao/         2764MB      117MB     2647MB       4%  /vol/vol_takao/
[devserver1] out: /vol/vol_takao/.snapshot      307MB      224KB      306MB       0%  /vol/vol_takao/.snapshot
[devserver1] out:


Done.
Disconnecting from devserver1... done.

ディクショナリを使えばformatの中身がきっとすっきりする。

リンク

Python で定数のようなものを使う


リンクメモ

Heroku

初期設定例

公式そのまま

1
2
3
4
5
git clone git://github.com/heroku/ruby-sample.git
cd ruby-sample
heroku create
git push heroku master
heroku open

ruby-sampleに入っているファイル

Gemfile
1
2
3
source :rubygems
gem 'sinatra', '1.1.0'
gem 'thin'
Gemfile.lock
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
GEM
  remote: http://rubygems.org/
  specs:
    daemons (1.1.9)
    eventmachine (0.12.10)
    rack (1.4.1)
    sinatra (1.1.0)
      rack (~> 1.1)
      tilt (~> 1.1)
    thin (1.4.1)
      daemons (>= 1.0.9)
      eventmachine (>= 0.12.6)
      rack (>= 1.0.0)
    tilt (1.3.3)

PLATFORMS
  ruby

DEPENDENCIES
  sinatra (= 1.1.0)
  thin
Procfile
1
web: bundle exec ruby web.rb -p $PORT
web.rb
1
2
3
4
5
require 'sinatra'

get '/' do
  "Hello, world"
end

heroku create したあとにheroku上にできたもの

limitless-hollows-2098のリンク

git push heroku master したあとにheroku上にできたもの

limitless-hollows-2098のリンク先「Dynos」web bundle exec ruby web.rb -p $PORTの項目


HerokuにRedmineをインストール

Redmineをherokuにデプロイする この手順を参考に

手順以外にやったこと

  • パッケージをインストール(CentOS6.4)
1
sudo yum install mysql-devel ImageMagick ImageMagick-devel postgresql

これをやらないとbundle installでエラーになる
その他エラーが出る場合は、メッセージをググって適宜必要なパッケージをyumで入れればいいと思う。

  • 以下のエラーがでたのでknown_hostsをリセット
1
 ! [remote rejected] 2.1-stable -> master (pre-receive hook declined)

~/.ssh 配下のknown_hostsを適当にリネームしました。

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

  • パスワード変更 デフォルトはadmin:adminなのでパスワードを変更
    言語を日本語にしてタイムゾーンをTokyoに変更