ラベル Linux の投稿を表示しています。 すべての投稿を表示
ラベル Linux の投稿を表示しています。 すべての投稿を表示

2012年11月6日

アスキーアートロゴを作成してみる

概要

現在「tweepy のAPI 1.1 対応フォーク」を作成している。
変な所が無いか知人に見てもらった時、いくつかの指摘の中で、READMEファイルのアスキーアートロゴに関して質問があった。
そこで、このようなアスキーアートロゴの作成方法に関してメモしておく。

bannerコマンド

Mac OS Xで標準的に利用できるコマンドだと「banner」が存在する。「-w」オプションで幅を指定する。

banner -w 30 Hello

「banner」コマンドは自由度がほとんど無いので、あまり便利ではない。

FIGlet

FIGlet」はこの分野でかなり利用されていると思われる。MacPorts や Homebrew で簡単にインストールできる。

sudo port install figlet

brew install figlet

使い方は簡単。

figlet Hello

フォントの変更も可能なので、参考サイト参照。

FIGletのPython実装「pyfiglet」が存在する。

pip install pyfiglet

pyfigletはモジューで提供されて、コマンドがインストールされない。
以下のようにするとコマンドでも利用できるが、普通は import して利用する物だと思われる。

/path/to/pyfiglet/__init__.py "Hello"

TOIlet

色付きでアスキーアートロゴが生成できる。名前やサイトデザインが結構酷いが、品質に問題はないようだ。
これも MacPorts や Homebrew で簡単にインストールできる。

sudo port install TOIlet

brew install TOIlet

使い方は FIGlet とほとんど同じで、色を付けるパターンが存在している。

参考サイト

以下のサイトが詳しい。

2012年10月19日

Ubuntu に munin 2 をインストールする手順メモ

概要

Munin」はサーバリソースグラフツール。
最新版は2.0.7だが、Ubuntu だと munin 1.x 系しかインストールできない模様なので、インストール手順をメモする。

muninの概要

munin は サーバのリソースをグラフ化するツール。似たようなツールは cacti 等が存在する。

muninの利点は以下

  • MySQL 等のデータベース不要
  • データ記録に RRDtool を利用
  • RRDtool で生成したデータファイルは、容量が初期生成時から増えることはないので、サーバの容量管理が容易
  • Perl で記述されているので、多くの環境で動作する
  • plugin の作成のためのプログラム言語はなんでも良く、書き方も比較的容易

munin は「master」と「node」が存在する。ここでは一つのサーバに「master」と「node」をインストールしているが、通常は「node」しかインストールしないサーバ等も存在することになる。

インストール

インストール手順を書いた fabfile は以下。「fab install」でインストールできる。
この記事を書いた時点では、deb ファイルがまだ 2.0.6 しかなかったので、2.0.6 をインストールしている。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from fabric.decorators import task
from fabric.api import (
    sudo,
    run,
    cd,
    env,
)


@task
def install():
    """
    munin 2.0 インストール
    """
    # 依存ファイルのインストール
    sudo('apt-get update')
    sudo('apt-get -y install librrds-perl '
         'rrdtool '
         'liblog-log4perl-perl '
         'ttf-dejavu '
         'libdate-manip-perl '
         'libcgi-fast-perl '
         'libfile-copy-recursive-perl '
         'libio-socket-inet6-perl '
         'librrd4 '
         'libfcgi-perl '
         'libyaml-syck-perl '
         'libsocket6-perl '
         'liblist-moreutils-perl '
         'libnet-server-perl '
         'libio-multiplex-perl '
         'libnet-cidr-perl '
         'libnet-snmp-perl '
         'libhtml-template-perl '
         'liburi-perl '
         'gawk ')

    etc_dict = {
        'urlpath': 'http://ftp.jp.debian.org/debian/pool/main/m/munin/',
        'ver': '2.0.6-1',
    }
    with cd(env.path):
        deb_tpl = (
            'munin-common_{ver}_all.deb'.format(**etc_dict),
            'munin_{ver}_all.deb'.format(**etc_dict),
            'munin-plugins-core_{ver}_all.deb'.format(**etc_dict),
            'munin-node_{ver}_all.deb'.format(**etc_dict),
        )
        # ダウンロード
        for deb in deb_tpl:
            run('wget {urlpath}/{deb}'.format(deb=deb, **etc_dict))

        # インストール
        for deb in deb_tpl:
            sudo('dpkg -i {deb}'.format(deb=deb))

起動

基本的には自動起動するはず。

「/etc/init.d/munin-node」および、「/etc/cron.d/munin」、「/etc/cron.d/munin-node」を確認する。

ディレクトリ

ディレクトリを確認しておく必要がある。

  • 設定ファイル:/etc/munin
  • 記録ファイル:/var/lib/munin
  • HTMLファイル:/var/cache/munin/www
  • ログ:/var/log/munin
  • pid:/var/run/munin

細かい設定は、設定ファイルで実施するが、とりあえずこの記事ではインストールまでとする。

nginxの設定

http 経由でグラフを見えるように設定する。
以下のような設定を nginx の設定に追加すれば、「http://ip/munin/」でグラフを見ることが可能になる。

# munin
location ^~ /munin/ {
    alias   /var/cache/munin/www/;
}

以上

2012年10月18日

nginx で自己署名証明書(オレオレ証明書、self signed certificate)を設定する

概要

ngin で 自己署名証明書(オレオレ証明書)を設定する。自己署名証明書でも暗号化はされるので、自分で利用する分には問題ない。

証明書作成

fabfile の該当箇所は以下。コピペして実行しても良い。途中でパスワードなど聞かれるが、全部空で良い。

@task
def setup_ssl():
    """
    オレオレ証明書の作成
    """
    work_dir = '/opt/nginx/conf/'
    with cd('{0}'.format(work_dir)):
        # pass hoge
        sudo('openssl genrsa -des3 -out server.key 1024')
        sudo('openssl req -new -key server.key -out server.csr')
        sudo('cp server.key server.key.org')
        sudo('openssl rsa -in server.key.org -out server.key')
        sudo('openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt')

nginxの設定

設定ファイルは以下のようになる。

daemon off;
worker_processes  5;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    error_log /opt/nginx/var/log/nginx-error.log debug;

    sendfile        on;

    keepalive_timeout  65;

    gzip  on;

    gzip_comp_level 2;
    gzip_proxied    any;
    gzip_types      text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    server {
        listen       80;
        # 443 ポートを有効にする
        listen       443;
        server_name  localhost;

        # SSL を有効にして、証明書のパスを指定
        ssl          on;
        ssl_certificate /opt/nginx/conf/server.crt;
        ssl_certificate_key /opt/nginx/conf/server.key;

        charset  utf-8;

        location / {
            root   /opt/www/html;
            index  index.html index.htm index.php;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # nginx status
        location ^~ /nginx_status {
            stub_status on;
            access_log  off;
        }

    }
}

ファイアーウォールの設定等している場合は 443 ポートを開放する。
あとは再起動して、https でアクセスすれば良い。

以上

2012年10月17日

プロセス管理に daemontools ではなく Supervisor を利用してみませんか

概要

サーバでは様々なプロセスを実行する必要があるが、これをどう管理するかは悩み所になる。
ここでは強力で柔軟なプロセス管理ツール「Supervisor」に関して記述する。

Supervisorに関して

Supervisor」は Python で記述された、プロセス管理ツール。
プロセス管理ツールと言うと「upstart」や「daemontools」が利用されていると思われる。
「upstart」は強力ではあるが、柔軟性がまだそれほど無いため、高度なプロセス管理はまだ難しい状況だと思われる。
「daemontools」は ノウハウが蓄積されており、強力で柔軟性が高いツールだが、2001年以降公式では更新されておらず、動作が不安定にってしまう環境も存在している。パッチを当てれば良いが、環境によって動作が変化してしまう場合もあり、安心して利用できない状況になってしまった。
Supervisor」は積極的に開発され、非常に安定したツールとなっている。
機能的には「daemontools」とほぼ同様の事が可能。
Python で記述されることで、Unix互換システムにおいて、快適に動作する。当然 Mac でも動作する。
現在の Linux サーバは Python はほぼ必須でインストールされている、という状況なので、ツールが Python で記述されていることは利点の一つになりえる。

Supervisorの利点は以下となる。全機能はマニュアル「Supervisor」を参照。

  • 積極的に開発されている
  • 設定ファイルが比較的簡単
  • プロセスのグループ化が容易
  • プロセスの状態により処理を実行することが可能
  • サブプロセスの管理も可能
  • ログを高度に処理できる
  • Webインターフェースが存在する
  • XMP-RPCインターフェースが存在する

インストール

Supervisorをインストールする場合、通常virtualenvにより環境を構築する。
参考に、以下インストール手順を示した fabfile を配置した。以下のスクリプトはインストールディレクトリは「/opt/python」で、作業ディレクトリは「/opt/supervisor」として記述してある、また、この fabfile はあまり、汎用的には記述していない、あくまで参考である。

実行は「fab install」で実行可能

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from fabric.decorators import task
from fabric.api import (
    sudo,
    run,
    cd,
    put,
    env,
)
from fabric.contrib.files import exists


@task
def install():
    """
    Supervisor
    """
    setup_venv()
    install_supervisor()
    setup_bin()
    setup_conf()
    setup_upstart()


@task
def setup_venv():
    """
    virtualenv による Python 環境構築
    """
    with cd(env.path):
        run('wget https://raw.github.com/pypa/virtualenv/master/virtualenv.py')
        sudo('python virtualenv.py --distribute /opt/python')


@task
def install_supervisor():
    """
    Supervisor インストール
    """
    run('source /opt/python/bin/activate')
    sudo('/opt/python/bin/pip install Supervisor')


@task
def setup_bin():
    """
    実行ファイル設定
    """
    work_dir = '/opt/supervisor/bin'
    if not exists('{0}'.format(work_dir)):
        sudo('mkdir -p {0}'.format(work_dir))
    put('./fabfile{0}/*'.format(work_dir),
        '{0}/'.format(work_dir), use_sudo=True)
    sudo('chown root:root {0}/*'.format(work_dir))
    sudo('chmod 755 {0}/*'.format(work_dir))


@task
def setup_conf():
    """
    設定ファイル
    """
    work_dir = '/opt/supervisor'
    if not exists('{0}'.format(work_dir)):
        sudo('mkdir -p {0}/etc'.format(work_dir))
        sudo('mkdir -p {0}/var/log'.format(work_dir))
        sudo('mkdir -p {0}/var/run'.format(work_dir))

    work_dir = '/opt/supervisor/etc'
    conf_file = '{0}/supervisord.conf'.format(work_dir)
    if not exists('{0}'.format(work_dir)):
        sudo('mkdir -p {0}'.format(work_dir))
    put('./fabfile{0}'.format(conf_file),
        '{0}'.format(conf_file), use_sudo=True)

    work_dir = '/opt/supervisor/etc/supervisor.d'
    conf_file = '{0}/*.conf'.format(work_dir)
    if not exists('{0}'.format(work_dir)):
        sudo('mkdir -p {0}'.format(work_dir))
    put('./fabfile{0}'.format(conf_file),
        '{0}'.format(conf_file), use_sudo=True)


@task
def setup_upstart():
    """
    upstart 設定
    """
    conf_file = '/etc/init/supervisor.conf'
    put('./fabfile{}'.format(conf_file),
        '{0}'.format(conf_file), use_sudo=True)
    sudo('chown root:root {0}'.format(conf_file))

管理用スクリプトの配置

Supervisor をインストールすると、インストール場所の「bin」以下に「supervisord」と「supervisorctl」の2ファイルが生成される。
これを直接利用しても良いが、自分は、一つのサーバで複数のSupervisorを起動する要件が発生する場合があるため、以下のようにスクリプトを作成している。
このスクリプトは実行する Python の指定と、設定ファイルの指定をしているだけだが、用途によっては便利だろう。

以下が「supervisord」と同じ機能のファイル

#!/opt/python/bin/python
# -*- coding: utf-8 -*-
import os
import sys

SRC_DIR=os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
sys.argv.extend(['-c', '{0}/etc/supervisord.conf'.format(SRC_DIR)])

import supervisor.supervisord

if __name__ == '__main__':
    supervisor.supervisord.main()

以下が「supervisorctl」と同じ機能のファイル。

#!/opt/python/bin/python
# -*- coding: utf-8 -*-
import os
import sys

SRC_DIR=os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
sys.argv[1:1] = ['-c', '{0}/etc/supervisord.conf'.format(SRC_DIR)]

import supervisor.supervisorctl

if __name__ == '__main__':
    supervisor.supervisorctl.main(sys.argv[1:])

設定ファイル

設定ファイルの雛形は「echo_supervisord_conf」プログラムによって生成可能。
とりあえず以下のように記述すると最低限の動作はする。「%(here)s」は設定ファイルのあるディレクトリを示す。
「include」の「file」は現在のバージョンではまだ「%(here)s」が使えない。

[supervisord]
childlogdir = %(here)s/../var/log
logfile = %(here)s/../var/log/supervisor.log
logfile_maxbytes = 50MB
logfile_backups = 10
loglevel = info
pidfile = %(here)s/../var/run/supervisor.pid
umask = 022
nodaemon = false
nocleanup = false

[inet_http_server]
port = 127.0.0.1:9001
username =
password =

[supervisorctl]
serverurl = http://127.0.0.1:9001
username =
password =

[rpcinterface:supervisor]
supervisor.rpcinterface_factory=supervisor.rpcinterface:make_main_rpcinterface

[include]
files = /opt/supervisor/etc/supervisor.d/*.conf

upstartの設定

Supervisor自身をSupervisorで管理することはできないので、Supervisorは upstartで管理する。
以下のようなファイルを「/etc/init」以下に「supervisor.conf」として配置する。

description     "supervisor"

start on runlevel [2345]
stop on runlevel [!2345]

respawn

chdir /opt/supervisor
exec sudo -i /opt/python/bin/python /opt/supervisor/bin/supervisord -n -d /opt/supervisor

pre-stop exec sudo -i /opt/python/bin/python /opt/supervisor/bin/supervisorctl stop all

プロセス管理設定

これで Supervisor は起動している。「supervisorctl status」を実行するとまだ管理対象が存在しないことがわかる。
とりあえず、nginx の管理を設定してみる。

管理対象のプロセスはフォアグラウンドで起動させる必要がある。nginx の設定を変更する。

daemon off;

Supervisor の設定ファイルで「include」の「files」で指定したディレクトリに以下のようなファイルを「nginx.conf」のような名前で配置する。

[program:nginx]
command=/opt/nginx/sbin/nginx -c /opt/nginx/conf/nginx.conf
redirect_stderr=true
stdout_logfile=%(here)s/../var/log/%(program_name)s_stdout.log
stderr_logfile=%(here)s/../var/log/%(program_name)s_stderr.log
autostart=true
autorestart=true

ここで注意すべきなのは「%(here)s」は、元設定ファイルのカレントディレクトリになるということ。パスには注意する。
以下のようにすることで、有効になる。

# 設定読み込み
supervisorctl reread
# 設定反映
supervisorctl update
# 確認
supervisorctl status

設定を反映するまでは、有効にならない。

以下のように、起動、終了、再起動が可能。

supervisorctl stop nginx
supervisorctl start nginx
supervisorctl restart nginx

「autostart=true」を設定しているので、Supervisor が起動すると自動起動する。
「autorestart=true」を設定しているため、異状終了しても管理対象プロセスは復旧してくる。kill などして、確認してみると良い。

Webインターフェース、XML-RPC

SupervisorはHTTPのWebインターフェエースをもっている。また XML-RPC による管理も可能。
HTTPSを利用したい場合は、nginx などの HTTPサーバを経由させれば良い。
上の設定ファイルを利用している場合はポート9001になる。

その他機能

他の機能はマニュアルを読むのが良い。機能は高機能なので、いろいろできる。

2012年10月16日

Ubuntu Server 12.04 LTS に nginx を Install したメモ

概要

Ubuntu Server 12.04 LTS に apt-get で nginx をインストールしようとしたら、nginx のバージョンが古かったのでコンパイルしてインストールした。とりあえずメモしておく。

fabfile

Fabric」で設定を書いてコンパイルした。
この fabfile だとインストール先は「/opt」の下にしてある。
ユーザは nginx ユーザを想定して作成している。
あまり綺麗な fabfile ではないが、そこまで綺麗に書いても意味ないかも。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from fabric.decorators import task
from fabric.api import (
    sudo,
    run,
    cd,
    put,
    env,
)


@task
def install():
    """
    nginx のインストール
    """

    # 依存ファイルのインストール
    sudo('apt-get install -y gcc')
    sudo('apt-get install -y make')
    sudo('apt-get install -y libpcre3-dev')
    sudo('apt-get install -y libssl-dev')

    # nginx
    with cd(env.path):
        etc_dict = {
            'urlpath': 'http://nginx.org/download/',
            'ver': '1.2.4',
            'data_dir': '/opt/nginx',
            'user': 'nginx',
            'group': 'nginx',
        }

        # ディレクトリ用意
        sudo('mkdir -p %(data_dir)s/conf' % etc_dict)
        sudo('mkdir -p %(data_dir)s/module' % etc_dict)
        sudo('mkdir -p %(data_dir)s/var' % etc_dict)
        sudo('mkdir -p %(data_dir)s/var/log' % etc_dict)
        sudo('mkdir -p %(data_dir)s/var/run' % etc_dict)
        sudo('mkdir -p %(data_dir)s/var/lock' % etc_dict)
        sudo('mkdir -p %(data_dir)s/var/tmp' % etc_dict)

        # ユーザ作成
        sudo('useradd -s /bin/false nginx -d /opt/nginx')

        # nginx コンパイル
        nginx = 'nginx-{ver}'.format(**etc_dict)
        run('wget {urlpath}/{nginx}.tar.gz'.format(nginx=nginx, **etc_dict))
        run('tar xvfz {nginx}.tar.gz'.format(nginx=nginx))
        with cd('{nginx}'.format(nginx=nginx)):
            run('./configure '
                '--prefix=%(data_dir)s '
                '--conf-path=%(data_dir)s/conf/nginx.conf '
                '--error-log-path=%(data_dir)s/var/log/nginx-error.log '
                '--http-log-path=%(data_dir)s/var/log/nginx-access.log '
                '--pid-path=%(data_dir)s/var/run/nginx.pid '
                '--lock-path=%(data_dir)s/var/lock/nginx.lock '
                '--user=%(user)s '
                '--group=%(group)s '
                '--with-debug '
                '--with-poll_module '
                '--with-http_gzip_static_module '
                '--with-http_realip_module '
                '--with-http_ssl_module '
                '--with-http_stub_status_module '
                % etc_dict)
            run('make')
            sudo('make install')

        # パーミッションの設定
        sudo('chown -R nginx:nginx /opt/nginx')


@task
def setup_nginx():
    """
    nginx 設定
    """
    # 設定ファイルのアップロード
    conf_path = '/opt/nginx/conf/nginx.conf'
    put('./fabfile/{conf_path}'.format(conf_path=conf_path),
        '{conf_path}'.format(conf_path=conf_path), use_sudo=True)
    # パーミッションの設定
    sudo('chown -R nginx:nginx {conf_path}'.format(conf_path=conf_path))

nginxの設定ファイル

「nginx.conf」の中身はいいかげんだが以下な感じ。

daemon on;
worker_processes  5;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    error_log /opt/nginx/var/log/nginx-error.log debug;

    sendfile        on;

    keepalive_timeout  65;

    gzip  on;

    gzip_comp_level 2;
    gzip_proxied    any;
    gzip_types      text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    server {
        listen       80;
        server_name  localhost;

        charset  utf-8;

        location / {
            root   /opt/www/html;
            index  index.html index.htm index.php;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # nginx status
        location ^~ /nginx_status {
            stub_status on;
            access_log  off;
        }

    }
}

コンパイルとインストール

fabfileの実行は以下のようにする。

fab -H ホスト install
fab -H ホスト setup_nginx

起動

nginx の起動は以下

sudo su /opt/nginx/sbin/nginx -c /opt/nginx/conf/nginx.conf

このままだと root ユーザでの起動になってしまう。本当は nginx ユーザで起動したいので、後で設定する。

動作確認

FW設定している場合はポートを開放する。

sudo ufw allow 80/tcp

「http://hostip/」でアクセスして、表示されたら成功。

2012年10月14日

Ubuntu の Firewall ツール UFW メモ

概要

Ubuntuでは通常Firewallの設定をする場合、「UFW(Uncomplicated Firewall)」を利用した方が簡単。
UFW は iptables のラッパで、基本的な事は ufw コマンドから設定することができる。

マニュアル

基本は「man ufw」と「UFW(Uncomplicated Firewall)」を参照すると良い。

設定ファイル

Ubuntuのバージョンによって多少設定ファイルのディレクトリが異なる。
ufwコマンドにて設定された値は「/lib/ufw」もしくは「/var/lib/ufw」以下の「user.rules」に保存される。
ufwコマンドで設定できない項目は「/etc/ufw」以下のファイルで設定する。

ufwコマンドで設定可能な項目

ufwコマンドでは「allow」、「deny」、「reject」、「limit」しか設定できない。「hashlimit」等を設定したい場合は、「/etc/ufw/before.rules」等に設定する。

ufwコマンドの使い方

「man ufw」と本家のマニュアル「UFW(Uncomplicated Firewall)」でほとんどわかる。
注意点は ufw で設定した物は設定順に読まれるという事。例えば「deny」して「allow」すると、「allow」が有効にならない。「ufw status numbered」にて順番を確認すること。
順番が意図と異なる場合は一度削除して、設定しなおす必要がある。
ufw を再有効(ufw enable)しないかぎり、すぐに反映されるわけではない。

ufwコマンドのサンプル

例えば SSH の設定は以下のようににすると、IPを特定からのアクセスに制限し、その他を拒否する。

sudo ufw allow from 192.0.2.178 to any port ssh
sudo ufw deny 22/tcp

DNS の port 53 を空けておかないと名前解決できないかも。

sudo ufw allow 53/tcp
sudo ufw allow 53/udp

「/etc/ufw/after.rules 」の「COMMIT」の前に以下を記述しとかないと、DNS解決できない。

-A ufw-after-input -m state --state ESTABLISHED,RELATED -j ACCEPT

設定内容の確認

以下のコマンドで確認できる。

# 概要
sudo ufw status

# iptables 形式
sudo ufw show raw

参考サイト

ufw コマンドの使い方は本家マニュアル参照。before とかの書き方は iptables の書き方なので、別途学習が必要。

2012年10月13日

Ubuntu で ufw を利用して ping を拒否する設定

概要

Ubuntu で ufw を利用して ping を拒否する機会があったのでメモ。
Ubuntu では ファイアウォールの設定は ufw を利用した方が良い。
ping のプロトコルは ICMP になる。

設定(IPv4)

「/etc/ufw/before.rules」に以下の設定をする。

-A ufw-before-input -p icmp --icmp-type destination-unreachable -j DROP
-A ufw-before-input -p icmp --icmp-type source-quench -j DROP
-A ufw-before-input -p icmp --icmp-type time-exceeded -j DROP
-A ufw-before-input -p icmp --icmp-type parameter-problem -j DROP
-A ufw-before-input -p icmp --icmp-type echo-request -j DROP

当然 ufw を有効にしておく必要がある。

sudo ufw enable

ファイルのパーミッションが不正だと警告が出るので、確認。

chown root:root /etc/ufw/before.rules
chmod 640 /etc/ufw/before.rules

設定(IPv6)

IPv6も設定するなら、「/etc/ufw/before6.rules」にも設定しないといけない模様。

ufwの有効化

当然 ufw を有効にしておく必要がある。

sudo ufw enable

ファイルのパーミッションが不正だと警告が出るので、確認。

chown root:root /etc/ufw/before6.rules
chmod 640 /etc/ufw/before6.rules

まとめ

ufw のコマンド経由では設定できないので、設定ファイルを編集する必要がある。

2012/10/13公開後追記:

Ubuntu 12.04 でこの設定をすると再起動時に「ERROR: problem running ufw-init」エラーが発生して、ufw が有効にならない様子。
公式説明にある、「Enable PING」を再度参考にして設定したが、変化しない。
「/lib/ufw/ufw-init restart」すると、rules のエラーが表示される。

以下でも同じような現象が発生している。
UFW ERROR: problem running ufw-init

2012/10/13夜追加

上記のエラーは単にfilterの記述忘れだった。

*filter
:ufw-before-input - [0:0]
:ufw-before-output - [0:0]
:ufw-before-forward - [0:0]

-A ufw-before-input -p icmp --icmp-type destination-unreachable -j DROP
-A ufw-before-input -p icmp --icmp-type source-quench -j DROP
-A ufw-before-input -p icmp --icmp-type time-exceeded -j DROP
-A ufw-before-input -p icmp --icmp-type parameter-problem -j DROP
-A ufw-before-input -p icmp --icmp-type echo-request -j DROP
COMMIT

2012年10月11日

RRDtool の使い方

概要

RRDtool」は時系列データを高速にロギングしたり、グラフ化するためのオープンソースのツール。
Munin」等のツール経由で利用する機会が多い。
ほとんどコマンドラインから利用しないので使い方をちゃんと調べた事がなかったのだけど、Munin で高度なグラフが必要になる機会が増えてきたので、ちゃんと調査してみることにした。

インストール

Mac であれば MacPorts なり homebrew なりでインストールするのが楽。この記事を書いている時点では「1.4.7」がインストールされる。

# MacPorts
port install rrdtool
# homebrew
brew install rrdtool

記録用ファイル作成

最初に記録用のファイルであるRRD(Round Robin Database)を作成する。
「rrdtool」コマンドを利用する。ファイルの作成は「rrdcreate」を参照すると詳細が記述されている。

rrdtool create filename \
        [--start|-b start time] \
        [--step|-s step] \
        [--no-overwrite] \
        [DS:ds-name:DST:dst arguments] \
        [RRA:CF:cf arguments]

コマンドの引数は以下。

  • filename:ファイルの名前。通常拡張子を「rrd」にするが、特に拡張子は関係ない。
  • --start:記録開始とする時刻。指定しないと、RRDファイル作成時間の10秒前に設定される。
  • --step:RRDファイルへの記録間隔。指定しないと300秒(5分)に設定される。
  • --no-overwrite:同じファイル名があったら上書きしない。
  • DS:データソース(data sources)の定義。複数定義でき、一定義がグラフ画像を生成する時の一つの線になる。
    • ds-name:参照用のデータソース名。1文字以上19文字以下で、[a-zA-Z0-9_]で定義する
    • DST:データソースのタイプ(Data Source Type)定義。(DS:ds-name:GAUGE | COUNTER | DERIVE | ABSOLUTE:heartbeat:min:max もしくは DS:ds-name:COMPUTE:rpn-expression)
      • GAUGE:取得した値をそのまま記録
      • COUNTER:前回の記録に加算していく。減算は考慮されていない。そのため、いつかオーバーフローするが、適切に処理される。
      • DERIVE:前回との差を記録。オーバフローは考慮されない。マイナス値もありえる。
      • ABSOLUTE:読み取るごとに0になる、もしくは0にしたい場合で、マイナスにならない物を記録。
      • COMPUTE:計算式を記述して、その結果を記録
    • arguments(heartbeat:min:max もしくは rpn-expression)
      • heartbeat:指定秒数を越えてデータが取得できない場合、UNKNOWNと記録する
      • min or max:必須ではない。最大値、最小値を定義。不明な場合は「U」を記述。最大最小が判明している時は明記すること。
      • rpn-expression:逆ポーランド記法の数式。COMPUTEの時のみ利用可能。
  • RRA:RRDへのRRA(round robin archives)の保存定義。(RRA:AVERAGE | MIN | MAX | LAST:xff:steps:rows)
    • CF:統合関数(consolidation function)
      • AVERAGE:平均
      • MIN:最小
      • MAX:最大
      • LAST:最後
    • xff:統合関数の結果、UNKNOWNがどの程度だったら、UNKNOWNにするかを定義。0から1の間の数を指定。0.5だと半分以上がUNKNOWNだと結果をUNKNOWNにする。
    • steps:統合関数にて統合するステップ数
    • rows:記録するレコード数

コマンドの引数は、実際の例を見た方が速いかもしれない。サンプルとして「load average」を取得してみる。

rrdtool create load.rrd \
    --step 300 \
    DS:load1:GAUGE:600:0:U \
    DS:load5:GAUGE:600:0:U \
    DS:load15:GAUGE:600:0:U \
    RRA:AVERAGE:0.5:1:600 \
    RRA:AVERAGE:0.5:6:700 \
    RRA:AVERAGE:0.5:24:775 \
    RRA:AVERAGE:0.5:288:797 \
    RRA:MAX:0.5:1:600 \
    RRA:MAX:0.5:6:700 \
    RRA:MAX:0.5:24:775 \
    RRA:MAX:0.5:288:797 \
    RRA:MIN:0.5:1:600 \
    RRA:MIN:0.5:6:700 \
    RRA:MIN:0.5:24:775 \
    RRA:MIN:0.5:288:797

この例だと以下のようになる。

  • 「load.rrd」というファイル名
  • 1ステップ5分
  • 「load average」は1分、5分、15分の3つの値があるので、DSをその数定義。
  • Daily用に、1ステップを600個、つまり5分×600個なので、50時間(2日2時間)の平均、最小、最大を保存
  • Weekly用に、6ステップを700個、つまり5分×6×700個なので、350時間(2日2時間×7)の平均、最小、最大を保存
  • Monthly用に、24ステップを775個、つまり5分×24×775個なので、1550時間(2日2時間×31)の平均、最小、最大を保存
  • Yearly用に、288ステップを797個、つまり5分×288×797個なので、18600時間(2日2時間×372=31×12)の平均、最小、最大を保存

Dailyは前々日ぐらいまでと比較したいので、50時間にしてある。48時間ぴったりだと同時刻が上手く比較できないため2時間を加算。
この50時間を単位として、週、月、年を定義してある。
週は7倍、月は31倍、年は31×12倍になるように定義。この定義で2年間はデータが記録可能ということになる。

データの記録

実際にデータを記録する。データ記録は「rrdupdate」を参照すると詳細が記述されている。

今回は「load average」を取得してみる。Mac で load average を取得する場合は以下のコマンドで可能。

uptime | awk -F\  '{print $(NF - 2)":"$(NF - 1)":"$NF}'

rrdtoolで記録する場合は時刻と同時に記録するように作成。

rrdtool update load.rrd \
    --template load1:load5:load15 \
    `date +%s`:`uptime | awk -F\  '{print $(NF - 2)":"$(NF - 1)":"$NF}'`

cron 等でしばらく動作させておく。step が 300 に指定してあるが、それより短い時間で記録してもそれなりに処理する。

記録内容の確認

内容確認は「fetch」を利用する。「rrdfetch」を参照すると詳細が記述されている。

rrdtool fetch load.rrd AVERAGE

グラフ画像の生成

グラフ生成は「graph」を利用する。「rrdgraph」を参照すると詳細が記述されている。
グラフの色は自動ではないので、自分で考える必要がある。

rrdtool graph load.png \
    --title "Load Average" \
    --vertical-label "Load Average" \
    --width 500 \
    --upper-limit 10.0 \
    --lower-limit 0 \
    --rigid \
    --imgformat PNG \
    DEF:load1=load.rrd:load1:AVERAGE \
    DEF:load5=load.rrd:load5:AVERAGE \
    DEF:load15=load.rrd:load15:AVERAGE \
    LINE1:load1#00FF00:"CPU Usage 1" \
    GPRINT:load1:LAST:"cur\: %2.2lf /" \
    GPRINT:load1:AVERAGE:"ave\: %2.2lf /" \
    GPRINT:load1:MAX:"max\: %2.2lf /" \
    GPRINT:load1:MIN:"min\: %2.2lf\n" \
    LINE2:load5#0000FF:"CPU Usage 5" \
    GPRINT:load5:LAST:"cur\: %2.2lf /" \
    GPRINT:load5:AVERAGE:"ave\: %2.2lf /" \
    GPRINT:load5:MAX:"max\: %2.2lf /" \
    GPRINT:load5:MIN:"min\: %2.2lf\n" \
    LINE3:load15#FF0000:"CPU Usage 15" \
    GPRINT:load15:LAST:"cur\: %2.2lf /" \
    GPRINT:load15:AVERAGE:"ave\: %2.2lf /" \
    GPRINT:load15:MAX:"max\: %2.2lf /" \
    GPRINT:load15:MIN:"min\: %2.2lf\n"

まとめ

とりあえず、グラフまで生成できるようになったが、オプションが一部の動作が良くわかっていないので、さらに細かい事項は使いながら調べることにする。

参考資料

いくつかの資料を参照した。本家のチュートリアルはそれなりに説明されているが、わかりずらい気がする。

2012年9月3日

ps の出力を grep する時「grep -v grep」しないで grep 自身のプロセスを取り除くには "[プ]ロセス名"

概要

psの出力をgrepする場合、grep 自身が含まれる。取り除く場合「grep -v grep」を利用するが他の方法もある。

"[プ]ロセス名"

zsh のプロセスを grep する場合は以下のようにする。

ps aux | grep "[z]sh"

簡単な解説

[ ] は囲まれた文字のリスト中の一文字にマッチする。
「grep "[z]sh"」とダブルクォートで囲み[ ]を使うことで grep の プロセスは「grep "[z]sh"」になる。
実際のプロセスの検索は「z」一文字と「sh」という意味で検索されるため、grep のプロセスは一致しなくなる。

課題

これは手で grep する時用な気がしている。スクリプトの中で grep 対象が変数に格納されている場合は「grep -v grep」の方が書くのは楽。

元ネタ

結構昔から利用しているので元ネタはすっかり忘れたが、おそらく元ネタはこのあたり。ps -ef | grep hoge | grep -v grep ではなく、ps -ef | grep [h]oge - hogehoge @teramako

2012年6月23日

Linuxサーバの反応が遅い(重い)場合の原因の調査手順

概要

Linuxサーバの反応が遅い場合の調査手順のメモ。
実行する場合は自己責任でお願いします。

原因として考慮すべき事項

サーバが遅い場合には様々な原因がありますが、以下を考慮します。

  • CPU負荷
  • メモリ不足
  • ディスクI/O負荷
  • ネットワークI/O負荷
まず、どれが原因か調査する必要があります。

top コマンド

最初は「top」コマンドを利用します。

top
以下のような出力になります。
top - xx:xx:xx up 0 min,  1 user,  load average: 1.44, 0.51, 0.18
Tasks:  87 total,   1 running,  86 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.7%us,  0.3%sy,  0.0%ni, 99.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   2057692k total,   291352k used,  1766340k free,    27824k buffers
Swap:  4292600k total,        0k used,  4292600k free,   133052k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND           
    6 root      20   0     0    0    0 S  3.3  0.0   0:02.29 events/0
    1 root      20   0 23672 1884 1288 S  0.0  0.1   0:00.98 init
    2 root      20   0     0    0    0 S  0.0  0.0   0:00.01 kthre

確認する項目は「load average」、「Tasks」、「Cpu(s)」、「Mem」、「Swap」になります。

「load average」

Load average は単純に説明すると、処理を待っているプロセスの平均数です。 この数が多いほど、処理が滞留しているので、反応が遅くなります。
左から「直近1分」、「直近5分」、「直近15分」の平均になります。
CPUの数やサーバの状態よって異なりますが、CPU コア数で割って「1」以下が良いと考えてください。
「直近5分」、「直近15分」の値が大きい場合は、かなり処理がつまっています。
あまりに大きい値の場合 SSH でログインする処理も処理待ちの列に入りますので、ログインに異状に時間がかかったりするようになります。

「Tasks」

プロセスの数が表示されます。zombie プロセス等が異状に多かったりしないか確認します。
普段からプロセスの数を確認していないと訳に立たないかもしれません。

「Cpu(s)」

CPUの利用率になります。各項目は以下の割合を示します。

  • %us:ユーザプロセス
  • %sys:システムプロセス
  • %ni:niceしてあるプロセス
  • %id:空き
  • %wa:I/O待ち
  • %hi:ハードウェア割り込み要求
  • %si:ソフトウェア割り込み要求
  • %st:仮想プロセス
id が大きい場合は CPU が余ている状態なので問題ありませんが、他の値が大きい場合は問題になります。
wa が大きいとファイルの I/O 待ちをしている可能性が高いです。
st の値は共用のサーバ(VPS、レンタルサーバ等)で 値が大きくなると、自分意外のユーザによる負荷が影響していることになります。
最近のサーバはかなり CPU の効率が良い物が多いので、よほど変なプログラムを走らせないかぎり、wa と st 以外は大きな値にならないかと思います。
wa と st 以外が大きくなるようならば、最近入れたプログラムが異状になっている可能性が高いです。
topコマンド表示中に「P」(shift+p)を押すとCPU利用率順にソートされますので、CPUを大量に利用しているプロセスを確認します。
自分の作成したプログラムならばなんらかの改善が必要ですし、インストールしたソフトの場合は、設定のミスがないかを疑ってください。
そもそもCPUが不足している場合は、CPUの増強を考慮する必要があります。

「Mem」

メモリの利用率です。

  • total:メモリの合計
  • used:利用中メモリ
  • free:空きメモリ
  • buffers:確保メモリ
free が少ないのならば、メモリ不足になっている場合があります。
topコマンド表示中に「M」(shift+m)を押すとメモリ利用順にソートされますので、メモリを大量に利用しているプロセスを確認します。
自分の作成したプログラムならばなんらかの改善が必要ですし、インストールしたソフトの場合は、設定のミスがないかを疑ってください。
そもそもメモリが不足している場合は、メモリの増強を考慮する必要があります。

「Swap」

Swap の率です。メモリが大量に free なのに used が高い等の場合は「vm.swappiness」の値を確認すると良いです。

cat /proc/sys/vm/swappiness

データベースサーバ等はメモリを大量に積んで swappiness の値を 0 に設定してしまって良いと思います。

vmstat コマンド

I/O 関連は top コマンドだけだと原因が不明です。top の CPU(s)でどの値も高くなく、メモリもswapもたいしたことがないが、「load average」が異状に高い、という場合はほとんどの場合 I/O に問題があります。
I/O に問題があると CPU(s) の wa が高くなりそうな物ですが、CPU のコア数が多かったり、高機能だと、wa に限界がくるので、 wa が 20%以下 なのに、I/O 限界のような状況になる場合があります。
vmstat を確認してみるのが良いでしょう。

vmstat 1

以下のような出力になります。

procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
 0  0      0 1770564  23700 132956    0    0 13298   215  252  907 17 43 38  2
 0  0      0 1770556  23700 132980    0    0     0     0   19   38  0  0 100  0
 0  0      0 1770556  23700 132980    0    0     0     0   18   24  0  1 99  0
 0  0      0 1770556  23700 132980    0    0     0     0   15   17  0  0 100  0
 0  0      0 1770564  23700 132980    0    0     0     0   18   20  0  1 99  0
 0  0      0 1770564  23700 132980    0    0     0    36   19   24  0  1 99  0
 0  0      0 1770564  23700 132980    0    0     0     0   21   40  0  1 99  0
 0  0      0 1770564  23700 132980    0    0     0     0   15   15  0  0 100  0
 0  0      0 1770564  23700 132980    0    0     0     0   19   17  0  1 99  0

プロセス、メモリ、swap、I/O、system、CPUの変化が1秒毎に見れます。
注目するのは「procs」で「r」が「実行中プロセス」、「b」が「ブロック中プロセス」です。
「r」の数が1以上の場合はプロセス数に対してCPUの機能が不足しています。
「b」の数が1以上の場合はほとんどの場合は「I/O待ち」です。

dstat コマンド

top と vmstat で原因が特定できる場合もありますが、それは簡単な問題の場合が多く、複雑な問題は経験に頼ることになる場合も多くなってしまいます。
dstat コマンドは、より正確にサーバ負荷関連を調査する場合は強力なツールになります。

以下のようにインストールします。

# CentOS
sudo yum install dstat
# Debian/Ubuntu
sudo apt-get install dstat

dstat の使い方は「DAG: Dstat: Versatile resource statistics tool」に説明がありますが、以下のように使います。

dstat -Tclmdrn

dstat にはプラグイン機構があるので「dstat --list」などするとプラグイン一覧が表示されます。
「--」でプラグインが複数指定できます。

dstat -tlp --disk-util --top-io --top-bio

dstat が利用できれば、サーバに関する知識があればだいたいの問題の原因は特定できると思われます。

その他のツール

その他にも以下のようなツール、コマンドがありますが、dstat があれば機能的には足りると思います。

  • free -m
  • ps aux
  • sar(sysstat)
  • iostat
  • iotop

負荷対処方法

負荷の原因がわかったとして、対処をどうすれば良いかが問題になります。

  • CPU負荷
  • メモリ不足
  • ディスクI/O負荷
  • ネットワークI/O負荷
CPU負荷への対処方

CPU負荷への対処は以下になります。

  • 負荷を発生させているプロセスの改善
  • CPUを増強
top コマンドや dstat コマンドを利用すると CPU 負荷を発生させているプロセスを特定することは可能ですので、地道に対処するのが良いかと思います。

メモリ不足への対処方

メモリ不足への対処は以下になります。

  • メモリを消費しているプロセスの改善
  • メモリを増強
top コマンドや dstat コマンドを利用すると メモリを消費しているプロセスを特定することは可能ですので、地道に対処するのが良いかと思います。

ディスクI/O負荷への対処方

ディスクI/O負荷への対処は以下になります。

  • 無駄なディスクI/Oを発生しているプロセスの改善
  • データを書き出すディスクを物理的に分離
  • RAID構成の場合はアレイコントローラのキャッシュ設定等を確認
ディスクI/Oは SSD にしてしまうなどで、速度を改善することも可能ですが、プログラムに問題がある場合も多いです。

ネットワークI/O負荷への対処方

ネットワークI/O負荷への対処は以下になります。

  • 無駄なネットワークI/Oを発生しているプロセスの改善
  • ネットワークカードの改善
  • ネットワークカードを増設し、物理的に分離
ネットワークI/O負荷は、ほとんどの場合プログラムに問題があります。ノンブロッキングI/O等ブロックしないようなプログラムをしないと問題が発生する場合が多いです。
また Web サーバなどはサーバデーモンの設定に問題があることも多いので、設定は気をつけましょう。

まとめ

原因が判明しても、対処や検証に時間が必要な場合が多いです。基本的には地道にやるのが良いでしょう。