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

12.17.2015

How to Color the Output from SSH Commands

SSH の出力をカラフルにする方法

 

SSH に限ったことではないが、ターミナルに表示されるテキストを目的に応じて着色したい場合、
パイプラインと sed を使うのが一番簡単だ。

$ ssh server-1 'python -c "import this"' \
  | sed -e $'s/^\\(.*\\)$/\e[96mserver-1\e[0m|\e[36m\\1\e[0m/'

出力は以下のようになる。
x

\e[96m や \e[36m の部分を変更すれば、色が変わる。

この応用として、複数のサーバに対して SSH をバックグラウンドで実行し(コマンドラインの末尾に「&」を付ける)
最後に wait コマンドで処理を待つようなシェルを書けば、サーバに応じた色のアウトプットをリアルタイムに観察できる。
y

12.16.2015

Manipulating Many Servers by Using parallel-ssh

parallel-ssh を使って複数サーバを同時に操作する

 

tl; dr

  • 2台〜100台程度のサーバに対して、同じオペレーションを同時に実行したい
  • parallel-ssh (pssh) の各種コマンドを使うと便利
  • ただし、リモートサーバで sudo が必要な場合は Ansible 等の他ツールが必要

 

parallel-ssh のセットアップ

 

インストール

parallel-ssh - PSSH: Parallel SSH Tools - Google Project Hosting
  • Mac
    $ brew install pssh
  • RHEL系
    # yum install pssh
ホストリストの準備
  • 任意のパスにテキストファイルを作成
    server-1
    server-2
    server-3 root
  • 1行ずつ、接続先サーバのホスト名またはIPアドレスを記述
  • ログインユーザの指定も可能

 

目的別コマンド実行例

 

SSH 認証のための設定

parallel-ssh を使うには、各サーバに SSH で接続できることが前提となる。
ssh-copy-id コマンドを利用して、~/.ssh/id_rsa の内容を登録する場合は以下。

$ for h in $(cat ~/hosts); do ssh-copy-id $h; done

 

pssh の使い方
  • 基本形
    $ pssh -h ~/hosts -i 'hostname'
    [1] 04:09:13 [SUCCESS] server-1
    server-1
    [2] 04:09:13 [SUCCESS] server-2
    server-2
  • ホスト名を直接指定
    $ pssh -H server-1 -H server-2 -i 'hostname'
    [1] 04:09:13 [SUCCESS] server-1
    server-1
    [2] 04:09:13 [SUCCESS] server-2
    server-2
  • タイムアウトを無制限に
    $ pssh -h ~/hosts -t 0 -i 'hostname'
    [1] 04:09:13 [SUCCESS] server-1
    server-1
    [2] 04:09:13 [SUCCESS] server-2
    server-2
  • アウトプットをすぐに表示
    $ pssh -h ~/hosts -P 'hostname'
    server-1: server-1
    [1] 04:13:28 [SUCCESS] server-1
    server-2: server-2
    [2] 04:13:28 [SUCCESS] server-2
    
  • リモートでバックグラウンド実行
    $ pssh -h ~/hosts -i 'nohup your_command > /path/to/output 2>&1 </dev/null &'
    [1] 04:13:28 [SUCCESS] server-1
    [2] 04:13:28 [SUCCESS] server-2
    
    バッファの影響で、標準出力の出力先ファイルがリアルタイムに更新されない場合がある。
    対応にはハックが必要: linux - redirect nohup stdout and flush - Stack Overflow

 

ファイル転送
  • ローカルからリモートに転送
    $ prsync -h ~/hosts -av /data/input/ /data/input/
    • パスの末尾にスラッシュを付けると、ディレクトリ間の同期となる。(rsync の仕様)
    • -z (圧縮オプション) は付けると CPU がボトルネックになって大幅に性能が劣化する場合がある。ナローバンドでなければ、付けないほうが良さそうだ。
  • リモートからローカルに転送
    $ pssh -h ~/hosts -p 4 -i 'rsync -e "ssh -o StrictHostKeyChecking=no" -av \
    /data/output/ server-1:/data/output/'
    • 全サーバから server-1 に集約する例
    • -p オプションを指定して、並列度を制限している。
      こうしないと、コネクションが多すぎて接続できない場合がある。
    • rsync -e "ssh -o ..." という書式で SSH オプションを指定。
      ここではホストキーのチェックを回避している。

 

リモートサーバで sudo が必要な場合
  • Ansible で代用
    $ ansible -i ~/hosts all --sudo -K \
    -a 'bash -c "cd /path/to/your/app && make install"'
    

 

References

11.08.2015

Universal Use of 'subprocess' Module in Python

Python: バージョン・OS 透過的な subprocess モジュールの利用

 

Python のバージョン (2.6 / 2.7 / 3.2 / 3.3 / 3.4 / 3.5) や、OS環境 (Linux / Mac / Windows /CygWin) に依存せずに外部コマンドを実行するコードを書きたい。

 

ワークアラウンド

なかなか一筋縄ではいかない。

Python3.2 + POSIX環境 では、コマンドラインを bytes で渡してはいけない

以下のようなエラーが出る。

>>> import subprocess
>>> subprocess.call(b'echo')
TypeError: expect bytes or str, not int

subprocess モジュールの中で、args が文字列かどうかを判定するときに bytes である場合の考慮が不足しており、bytes の個々の要素(int)に対して分割が行われてしまうため。

対策は、コマンドラインをリストとして渡せばよい。以下のように対策する。(args が bytes である場合)

import sys

if sys.version_info[:2] == (3, 2):
    args = [args]

 

Python3 + Windows環境では、コマンドラインと環境変数のキー・値を bytes で渡してはいけない

以下のようなエラーが出る。

>>> import subprocess
>>> subprocess.call(b'cmd /C echo x')
    needquote = (" " in arg) or ("\t" in arg) or not arg
TypeError: argument of type 'int' is not iterable

bytes に対する in オペレーションに失敗しているが、これといった対策が見当たらない。bytes で渡すのをやめて、str で渡すことにする。(その場合、コマンドライン文字列のエンコードは指定できない)

import sys
import six
if six.PY2 or sys.platform != 'win32':
    # この場合だけ bytes にエンコード

env の指定についても同様。キーだけではなく、値も bytes が許容されていないので注意。

 

POSIX環境 + shell=True のとき、args をリストとして渡してはいけない

リストの2番目以降の引数が評価されない。

>>> import subprocess
>>> subprocess.call(['echo', '3'], shell=True)

0

ワークアラウンドとしては、subprocess.list2cmdline を使って適切な文字列を生成する。

import sys
import subprocess
if shell and sys.platform != 'win32':
    args = [subprocess.list2cmdline(args)]

 

外部コマンドについて

 

sleep

Windows 7 以降は「timeout」というコマンドが標準装備されているが、Python から実行すると標準入力が奪われてしまい不都合だった。


結局、Python の time モジュールを使うのが一番簡便だという結論に。

import subprocess
subprocess.call('python -c "import time;time.sleep(2)"')

 

プロセステーブルの取得

11.03.2015

How to Clear Terminal Screen in Various Systems

ターミナルの画面を消去する方法

 

特別なインストールなしで実現したい。

  • POSIX互換環境(Linux/Unix/Mac): clear
  • Windows
    • コマンドプロンプト (cmd.exe): cls
    • CygWin (2011以前): cmd /c cls
    • CygWin (mintty): echo -en "\ec"

CygWin の闇は深い。

 

 

References

8.31.2015

SSH Cheat Sheet

SSH チートシート

 

たまに使うけど忘れがちなコマンド & tips についてメモ。

6.28.2015

Ansible: Installing Graphite + Grafana 2

Ansible: Graphite + Grafana 2系をインストールする Playbook

 

以前作った Playbook が最新の Amazon Linux に対応できなくなっていたので更新。

主な対応内容

  • Amazon Linux のデフォルトの Python バージョンが、いつの間にか 2.7 に上がっていた。
    yum でインストールされる Python ライブラリは 2.6 向けにパッケージングされているので使えない。
  • インストールパスを標準準拠に。カスタマイズ箇所を最小限に留めるよう意識した。
  • MySQL の使用もやめた
  • Grafana 2系の導入
    • WebサービスやDBが内包されている。つまり Nginx, ElasticSearch も不要になった

セットアップ手順

README 参照。

色々ハマリどころも多かったが、いったん Playbook に反映。プロビジョニングしてすぐにグラフが作れるようになった。

 

s

S

 

ただし、Graphite はやはり依存関係が複雑で保守性が悪いので、今後は Grafana + InfluxDB の組み合わせを選択するのが主流になりそう。

 

References

Troubleshooting Guide for SSH Connection Error

SSH接続エラーのトラブルシューティング情報まとめ

 

SSH の接続に失敗する場合の対処方法の自分用メモ。随時更新していく。

5.04.2014

Recording the Terminal Session as Video

ターミナル録画系サービスのメモ

 

3種類のサービスを比較。

 

1. Asciinema

 

インストール

pip でインストールする。easy_install から始める場合は以下のとおり。

$ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | sudo python
$ sudo easy_install pip
$ sudo pip install asciinema

 

録画の実行

asciinema rec で録画実行、exit (Ctrl+D) で終了。

Asciinema を実行を Asciinema で録画したのがこちら。

録画した内容が瞬時にパブリックになってしまうというのも少し怖い気がするが……

 

2. showterm

 

インストール

gem でインストール。(実行シェルを直接ダウンロードする手順も記載されているが、うまく動作しなかった)
ruby からインストールする場合は以下のとおり。(RedHat系Linuxの場合)

$ sudo yum install -y rubygems
$ sudo gem install showterm

 

録画の実行

showterm で録画実行、exit (Ctrl+D) で終了。
終了すると即座にアップロード処理が始まる。

showterm を実行を showterm で録画したのがこちら。

表示が若干崩れるのは、script コマンドの問題だろうか。




 

3. Shelr.tv

 

インストール

gem でインストール。
ruby からインストールする場合は以下のとおり。(RedHat系Linuxの場合)
json ライブラリに依存しているので、ruby-devel のインストールが必要。

$ sudo yum install -y rubygems
$ sudo yum install -y ruby-devel
$ sudo gem install shelr

 

録画の実行

shelr record で録画実行、exit (Ctrl+D) で終了。
ターミナルのサイズが大きいと録画が実行されないので注意。

$ shelr record
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
=> Please, resize your terminal!
=> Sizes bigger than 132x43 are slow and will not be available to all users.
=> We care about this.
=> Also, do not resize your terminal while recording. It will break the record.
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

ターミナルサイズを一時的に変更




$ stty rows 43 cols 132
$ stty -a    # 確認

shelr を実行を shelr で録画したのがこちら。

shelr の場合、録画内容が勝手に公開されてしまう心配がないので安心だ。
必要に応じて shelr play で内容をチェックした後、shelr publish で明示的に公開操作を行う。




Shelr.tv のアカウントを作れば、限定メンバーへの公開も可能な様子。

2.04.2014

Docker: Getting Started with boot2docker

Docker: 母艦 boot2docker に乗り換える

 

こちらのブログポストを読み、

Mac のローカルで docker run するためだけに CentOS を立ち上げるのは贅沢すぎると反省。
そして、母艦を boot2docker に鞍替え。

非常に軽快。
そして今まで使っていたコンテナをそのまま新しい母艦へ運搬する。

この感覚がとても新鮮。

2.02.2014

Docker: Creating Development Environment with SSH

Docker: SSH標準装備の開発環境コンテナイメージの作成

 

Docker コンテナ内で完結する開発環境を作って immutable infra を実現したいというのが動機。
コンテナ内の各種ログを確認したり、ちょっとしたファイルを転送したりするために SSH によるログインも可能としたい。 

 

ファイル構成

 

複数プロセスをまとめる Supervisor

Docker は 1つのアプリケーションを 1つのコンテナで動かすのが基本的な考え方。

複数のプロセスをまとめてデーモンとして動作させるためにはプロセス管理ツールが必要。
その現時点のデファクトスタンダードが Python で書かれたツール、Supervisor である。

 

ファイル内容

作業ディレクトリ配下に Dockerfile と supervisord.conf、そして必要であればミドルウェア等の設定ファイルを置く。

CentOS ベースのコンテナであれば、各ファイルの内容は以下のような構成になる。

  • Dockerfile

    ssh-user という OSユーザを作成し(パスワードも ssh-user)、sudo も可能にする。

    FROM centos:6.4
    
    #
    # SSH
    #
    
    RUN yum install -y --nogpgcheck openssh-server sudo
    RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key && ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key && sed -i 's/UsePAM.*/UsePAM no/g' /etc/ssh/sshd_config
    
    # create user
    RUN useradd ssh-user && echo 'ssh-user:ssh-user' | chpasswd && echo 'ssh-user ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
    
    #
    # Supervisor
    #
    
    # enable EPEL repository
    RUN yum install -y --nogpgcheck http://dl.iuscommunity.org/pub/ius/stable/Redhat/6/x86_64/epel-release-6-5.noarch.rpm
    
    # install supervisord
    RUN yum install -y --nogpgcheck supervisor
    
    # settings
    ADD supervisord.conf /etc/supervisord.conf
    RUN mkdir -p /var/log/supervisor
    
    #
    # Other applications here!
    #
    
    EXPOSE 22
    CMD ["/usr/bin/supervisord"]
    
    

    尚、ADD コマンドの後は常に新しいイメージが生成されるようで、キャッシュが使えなくなる。
    Dockerfile を編集して何度もコンテナを作りたい場合は ADD を後回しにした方がいいかもしれない。

  • supervisord.conf
    [supervisord]
    nodaemon=true
    
    [program:sshd]
    command=/usr/sbin/sshd -D
    stdout_logfile=/var/log/supervisor/%(program_name)s.log
    stderr_logfile=/var/log/supervisor/%(program_name)s.log
    autostart=true
    autorestart=true
    

    起動するプロセスを増やしたい場合は、[program:xxx] を増やしてゆけばよい。
    sshd だけは autorestart を有効にした方がいいだろう。

 

Apache + MySQL + PHP 環境のサンプル

例えばお手軽な LAMP環境を使いたい場合は以下のような Dockerfile を作る。

ローカルのみの使用を前提としているので、セキュリティの制限は設けていない。

 

コンテナイメージの作成と起動

 

Docker ホスト SELinux の無効化

まず最初に、Dockerホスト側の SELinux を無効化(/etc/selinux/config -> SELINUX=disabled)する。

これをしないと Dockerコンテナ側で getenforce コマンドがエラーになってしまい、SSH 接続ができなくなる。

(getenforce の中で呼ばれている security_getenforce 関数が負数を返し、結果としてパスワード認証後に通信が切断される。このトラブルシューティングで1日を費やしてしまった)

 

イメージ作成

Docker Registry との連携を考えるなら、イメージの名前にはハイフンではなくアンダースコアを使った方がいい。

$ docker build -t local/apache_mysql_php .

 

コンテナ起動

Dockerホストのポートとの転送設定を -p オプションで指定する。

$ docker run -d -t -p 50000:22 -p 3306:3306 -p 8000:80 local/apache_mysql_php

この例では、SSH(22) を 50000番に、MySQL(3306) はそのまま、Apache(80) は 8000番に割り当てている。

尚、実際の運用では -v /vagrant/app:/app のようにディスクのマウント設定を行い、
アプリケーションの領域を Dockerホストと連携させると良さそうだ。

(さらに Vagrant の synced folder 機能を使って、自分のPCとDockerコンテナのディレクトリを直接リンクさせることもできる)

2014-03-15 追記
環境によっては、docker run に「-t」オプション(pseudo tty 有効化) が必須となるので付けたほうがいい。

 

動作確認

 

Docker

コンテナが起動していることを確認

$ docker ps
CONTAINER ID        IMAGE                           COMMAND                CREATED             STATUS              PORTS                                                                 NAMES
c636e5dbaebf        local/apache_mysql_php:latest   /usr/bin/supervisord   16 seconds ago      Up 14 seconds       0.0.0.0:3306->3306/tcp, 0.0.0.0:50000->22/tcp, 0.0.0.0:8000->80/tcp   angry_pare

 

SSH

ログイン先は Dockerホストの 50000番ポート。

「Dockerホスト」の箇所は環境に合わせて適宜置換(以下同じ)。ログインパスワードは ssh-user。

$ ssh -p 50000 -l ssh-user Dockerホスト
(パスワード入力など)
[ssh-user@70a19c076413 ~]$

 

Apache, PHP

Docker コンテナの中で適当なPHPページを作る。

$ sudo /bin/bash -c "echo '<?php phpinfo(); ?>' > /var/www/html/info.php"

ブラウザで http://Dockerホスト:8000/info.php にアクセスして、phpinfo() の結果が表示されればOK。

 

MySQL

root アカウントで直接操作できるようにしている。

$ mysql -uroot -h Dockerホスト
mysql> select host, user from mysql.user;
mysql> exit

 

これで immutable な開発環境のベースができあがった。

 

 

References

 

2.01.2014

VirtualBox: How to Increase the Virtual Hard Disk Size

VirtualBox: CentOS 仮想ディスクの容量拡張について

 

VirtualBox で立てた Docker ホストの中でコンテナを作り続けていたら、いつしか仮想ディスクの容量が
full になってしまっていた。

VirtualBox のゲストOSで使っているストレージ容量を増やす手順をメモしておく。

 

環境

  • ホストOS: Mac OS X 10.9 (Mavericks)
  • VirtualBox: 4.3.6
  • ゲストOS: CentOS 6.5

こちらの Dockerfile で構築した CentOS (ベースは opscode 提供イメージ) のディスクを
40GB から 80GB へ拡張する。

尚、物理ディスクの空き容量は十分にあるものとする。

 

手順

こちらのブログポストの内容に従って作業。

 

(1) 仮想OS の停止
$ vagrant halt

 

(2) フォーマット変換

ストレージが VMDK 形式の場合、VBoxManage コマンドで直接その容量を変えることはできない。(※1)
いったん VDI 形式のクローンを作ってから、その容量を拡張する。

以下は packer-centos-6.5-x86_64-disk1 というストレージの場合の例。

$ cd ~/VirtualBox\ VMs/ゲストOSの名前
$ VBoxManage clonehd packer-centos-6.5-x86_64-disk1.vmdk packer-centos-6.5-x86_64-disk1.vdi --format VDI
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Clone hard disk created in format 'VDI'. UUID: 32e9d2f1-d30c-4dfc-84dd-24ba96e3be31
$ VBoxManage modifyhd packer-centos-6.5-x86_64-disk1.vdi --resize 81920
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%

clonehd コマンドの所要時間は実ディスクの使用量やI/O性能に依存。数十分かかる場合もある。

変換し終わったらVMDK形式のファイルは削除してよいが、バックアップとして暫く残しておくことをお勧めする。

 

(3) ストレージ差し替え

VirtualBox の GUI 上で作業した。

設定画面を開いて、IDE Controller 配下の Primary Master ディスクを VDI 形式のものに付け替え。

Docker host1 Storage 4

 

(4) 仮想OS の起動
$ Vagrantfileのあるディレクトリ
$ vagrant up
$ vagrant ssh

fdisk コマンドで 80GB (+α) が認識されていることを確認。

$ sudo fdisk -l |head -20

ディスク /dev/sda: 85.9 GB, 85899345920 バイト
ヘッド 255, セクタ 63, シリンダ 10443
Units = シリンダ数 of 16065 * 512 = 8225280 バイト
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O size (minimum/optimal): 512 bytes / 512 bytes
ディスク識別子: 0x0004a286

デバイス ブート      始点        終点     ブロック   Id  システム
/dev/sda1   *           1          64      512000   83  Linux
パーティション 1 は、シリンダ境界で終わっていません。
/dev/sda2              64        5222    41430016   8e  Linux LVM

ディスク /dev/mapper/VolGroup-lv_root: 41.4 GB, 41448112128 バイト
ヘッド 255, セクタ 63, シリンダ 5039
Units = シリンダ数 of 16065 * 512 = 8225280 バイト
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O size (minimum/optimal): 512 bytes / 512 bytes
ディスク識別子: 0x00000000

 

(5) パーティションの拡張

fdisk または parted で実行。以下は parted の例。
最初に unit cyl でシリンダ単位で操作するようにしている。ハイライトした行が parted 内での入力。

$ sudo parted
(parted) unit cyl
(parted) p
モデル: ATA VBOX HARDDISK (scsi)
ディスク /dev/sda: 10443cyl
セクタサイズ (論理/物理): 512B/512B
BIOS シリンダ、ヘッド、セクタ geometry: 10443,255,63.  1シリンダは 8225kB。
パーティションテーブル: msdos

番号  開始   終了     サイズ   タイプ   ファイルシステム  フラグ
 1    0cyl   63cyl    63cyl    primary  ext4              boot
 2    63cyl  5221cyl  5157cyl  primary                    lvm

(parted) rm 2
警告: WARNING: the kernel failed to re-read the partition table on /dev/sda (デバイスもしくはリソースがビジー状態です).  As a result, it may not reflect all of your changes until after reboot.
(parted) p
モデル: ATA VBOX HARDDISK (scsi)
ディスク /dev/sda: 10443cyl
セクタサイズ (論理/物理): 512B/512B
BIOS シリンダ、ヘッド、セクタ geometry: 10443,255,63.  1シリンダは 8225kB。
パーティションテーブル: msdos

番号  開始  終了   サイズ  タイプ   ファイルシステム  フラグ
 1    0cyl  63cyl  63cyl   primary  ext4              boot

(parted) mkpart primary 63 10443
警告: 63cyl から 10443cyl までのパーティションを指定されました。
可能な中で最も近いものは 63cyl から 10443cyl になります。
それでもかまいませんか?
はい(Y)/Yes/いいえ(N)/No? y
警告: WARNING: the kernel failed to re-read the partition table on /dev/sda (デバイスもしくはリソースがビジー状態です).  As a result, it may not reflect all of your changes until after reboot.
(parted) p
モデル: ATA VBOX HARDDISK (scsi)
ディスク /dev/sda: 10443cyl
セクタサイズ (論理/物理): 512B/512B
BIOS シリンダ、ヘッド、セクタ geometry: 10443,255,63.  1シリンダは 8225kB。
パーティションテーブル: msdos

番号  開始   終了      サイズ    タイプ   ファイルシステム  フラグ
 1    0cyl   63cyl     63cyl     primary  ext4              boot
 2    63cyl  10443cyl  10379cyl  primary

(parted) set 2 lvm on
警告: WARNING: the kernel failed to re-read the partition table on /dev/sda (デバイスもしくはリソースがビジー状態です).  As a result, it may not reflect all of your changes until after reboot.
(parted) p
モデル: ATA VBOX HARDDISK (scsi)
ディスク /dev/sda: 10443cyl
セクタサイズ (論理/物理): 512B/512B
BIOS シリンダ、ヘッド、セクタ geometry: 10443,255,63.  1シリンダは 8225kB。
パーティションテーブル: msdos

番号  開始   終了      サイズ    タイプ   ファイルシステム  フラグ
 1    0cyl   63cyl     63cyl     primary  ext4              boot
 2    63cyl  10443cyl  10379cyl  primary                    lvm

(parted) q
通知: 必要であれば /etc/fstab を更新するのを忘れないようにしてください。

設定が終わったら、ssh から抜けてリブート(vagrant halt; vagrant up)する。

 

(6) LVM 物理ボリューム (physical volume) サイズの拡張

pvscan で確認、pvresize で変更。

$ sudo pvscan
  PV /dev/sda2   VG VolGroup   lvm2 [39.51 GiB / 0    free]
  Total: 1 [39.51 GiB] / in use: 1 [39.51 GiB] / in no VG: 0 [0   ]
$ sudo pvresize /dev/sda2
  Physical volume "/dev/sda2" changed
  1 physical volume(s) resized / 0 physical volume(s) not resized
$ sudo pvscan
  PV /dev/sda2   VG VolGroup   lvm2 [79.51 GiB / 40.00 GiB free]
  Total: 1 [79.51 GiB] / in use: 1 [79.51 GiB] / in no VG: 0 [0   ]

vgdisplay コマンドで状態を確認。

$ sudo vgdisplay
  --- Volume group ---
  VG Name               VolGroup
  System ID
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  4
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                2
  Open LV               2
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               79.51 GiB
  PE Size               4.00 MiB
  Total PE              20354
  Alloc PE / Size       10114 / 39.51 GiB
  Free  PE / Size       10240 / 40.00 GiB
  VG UUID               Iv3nnF-GabP-gmv5-sU9W-iGtb-y5yg-9MA68g

Total PE 20354 に対して、Alloc PE が 10114 であることがわかった。

 

(7) LVM 論理ボリューム (logical volume) サイズの拡張

lvdisplay で確認、lvextend で変更。
空き領域を全て使用する場合には -l +100%FREE オプションが便利だ。

$ sudo lvdisplay
  --- Logical volume ---
  LV Path                /dev/VolGroup/lv_root
(略)
  LV Size                38.60 GiB
(略)
$ sudo lvextend -l +100%FREE /dev/VolGroup/lv_root
  Extending logical volume lv_root to 78.60 GiB
  Logical volume lv_root successfully resized
$ sudo lvdisplay
  --- Logical volume ---
  LV Path                /dev/VolGroup/lv_root
(略)
  LV Size                78.60 GiB
(略)

 

(8) ファイルシステムのサイズ拡張

最後に、resize2fs で対象のファイルシステムのサイズを変更。

$ sudo resize2fs /dev/VolGroup/lv_root
resize2fs 1.41.12 (17-May-2010)
Filesystem at /dev/VolGroup/lv_root is mounted on /; on-line resizing required
old desc_blocks = 3, new_desc_blocks = 5
Performing an on-line resize of /dev/VolGroup/lv_root to 20604928 (4k) blocks.
The filesystem on /dev/VolGroup/lv_root is now 20604928 blocks long.

$ df -h
Filesystem                    Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup-lv_root   78G   38G   36G  52% /

無事、ファイルシステム上で使えるディスク容量を 40GB 増やすことに成功した。

 

 

 

※1 現バージョンでは対応していないフォーマットだと表示される。

$ VBoxManage modifyhd packer-centos-6.5-x86_64-disk1.vmdk --resize 81920
0%...
Progress state: VBOX_E_NOT_SUPPORTED
VBoxManage: error: Resize hard disk operation for this format is not implemented yet!

1.06.2014

Vagrant: Creating CentOS 6.5 Docker Host

Vagrant: CentOS 6.5 Docker 母艦の建造

 

Vagrant 1.4 で Docker へのプロビジョニング対応 (Vagrant 1.4 - Vagrant) が行われたことで
ローカルマシン(VirtualBox)上での Docker ホストOS の構築はより一層簡単になった。

尚、Ubuntu ホストであればこちらの手順通り、公式リポジトリをそのまま使えばよい。

 

事前準備

 

環境
  • ローカルマシン: Mac OS X 10.9.1
    • Vagrant: 1.4.2 (確認は「vagrant -v」)
    • VirtualBox: 4.3.6
  • Docker ホスト (母艦): CentOS 6.5
    • Docker: 0.7.2 (確認は「docker -v」)
  • Docker コンテナ: CentOS 6.4

 

母艦の立ち上げ

基本的には適当なディレクトリに Vagrantfile を作成して、「vagrant up」するだけ。

Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "opscode-centos65"
  config.vm.box_url = "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5_chef-provisionerless.box"

  config.vm.provider :virtualbox do |vb|
    vb.name = "docker1"
    vb.customize ["modifyvm", :id, "--memory", 1024]
  end

  config.vm.network :private_network, ip: "192.168.33.10"

  config.vm.provision :docker do |d|
    d.pull_images "centos:6.4"
  end
end
  • 8行目: OpsCode 提供の CentOS 6.5 box をダウンロードして利用
  • 11-12行目: VirtualBox の VM に docker1 という名前を付け、メモリを少し増やす
  • 15行目: Docker コンテナへ直接アクセスしたいので、静的アドレスを割り振った方が便利
    (ネットワークアドレスは VirtualBox の仮想ネットワークアダプタの設定に依存。
    デフォルトでは host-only ネットワークが 192.168.33.0/24 として構築されている)
  • 17-19行目: Docker のプロビジョニング設定。ここでは centos:6.4 のイメージを pull している。
    これを記述することで、Docker 自体のインストール、サービスへの登録が自動的に行われる。

 

仮想マシンの作成

単に「vagrant up」でもよいが、ゴミの消去も含めたシェルスクリプトを書いて実行した。

#!/bin/bash


### Clean.
vagrant destroy --force

### Create VirtualBox image and boot.
vagrant up

### Print status.
vagrant status

実行結果は以下のとおり。プロビジョニングの工程で Docker のインストールが行われている。

[default] VM not created. Moving on...
Bringing machine 'default' up with 'virtualbox' provider...
[default] Importing base box 'opscode-centos65'...
[default] Matching MAC address for NAT networking...
[default] Setting the name of the VM...
[default] Clearing any previously set forwarded ports...
[default] Clearing any previously set network interfaces...
[default] Preparing network interfaces based on configuration...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)
[default] Running 'pre-boot' VM customizations...
[default] Booting VM...
[default] Waiting for machine to boot. This may take a few minutes...
[default] Machine booted and ready!
[default] Configuring and enabling network interfaces...
[default] Mounting shared folders...
[default] -- /vagrant
[default] Running provisioner: docker...
[default] Installing Docker (latest) onto machine...
[default] Pulling Docker images...
[default] -- Image: centos:6.4
Current machine states:

default                   running (virtualbox)

The VM is running. To stop this VM, you can run `vagrant halt` to
shut it down forcefully, or you can run `vagrant suspend` to simply
suspend the virtual machine. In either case, to restart it again,
simply run `vagrant up`.

ちなみに、vagrant-vbguest プラグインがインストールされている場合には以下のようなビルドエラーが発生した。

Building the OpenGL support module[FAILED]
(Look at /var/log/vboxadd-install.log to find out what went wrong)
Doing non-kernel setup of the Guest Additions[  OK  ]
Installing the Window System drivers[FAILED]
(Could not find the X.Org or XFree86 Window System.)
An error occurred during installation of VirtualBox Guest Additions 4.3.6. Some functionality may not work as intended.
In most cases it is OK that the "Window System drivers" installation failed.

X Window はインストールされていないので無視してよさそうだが、OpenGL のほうは少し気になる。

 

母艦への接続

「vagrant ssh」で母艦に接続した後、docker コンテナを立ち上げて
/etc/redhat-release ファイルの中身を参照してみた。

$ vagrant ssh
Last login: Thu Dec  5 05:57:05 2013 from 10.0.2.2
[vagrant@localhost ~]$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos              6.4                 539c0211cd76        9 months ago        300.6 MB
[vagrant@localhost ~]$ sudo docker run centos:6.4 /bin/cat /etc/redhat-release
CentOS release 6.4 (Final)

Cent OS 6.4 のコンテナが起動したことが確認できた。

 

 

 

References

 

Related Posts

12.24.2013

Monitoring JMX in Zabbix

Zabbix: JMX監視について

 

バージョンによって手順に違いがあったり、公式ドキュメントでも日本語化されていない部分があったりしたので
導入のポイントをメモしておく。 

 

環境

監視サーバ
  • zabbix-server 2.2
  • Zabbix Java Gateway (後述) を同居

 

監視対象サーバ
  • RedHat Enterprise Linux または Cent OS (もちろんこれ以外でも動作する)
  • zabbix-agent
  • 適当な JVM アプリケーション
    • 適当な JMX ポートを決定し、監視サーバから接続可能にすること

 

監視対象サーバの設定

 

JMX ポートの起動

JVM の標準機能である JMX を有効にする。
起動スクリプトなどで JAVA_OPTION を指定すればよい。

設定例 (セキュリティ関連の項目は必要に応じて書き換えること)

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=12345
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false

 

疎通確認

監視サーバからの疎通確認には、cmdline-jmxclient を使うと便利だった。

実行例 (適当なディレクトリ配下で)

curl -O http://crawler.archive.org/cmdline-jmxclient/cmdline-jmxclient-0.10.4.jar
java -jar cmdline-jmxclient-0.10.4.jar - xxx.xxx.xxx.xxx:12345
java -jar cmdline-jmxclient-0.10.4.jar - xxx.xxx.xxx.xxx:12345 java.lang:type=Threading

Exception が発生せず、何らかの情報が表示されればひとまずOK。

 

補足

ネットワーク関連の問題が発生した場合、JVM の起動オプションで以下のように自分自身のIPアドレスを明記することで解決する場合がある。

監視対象サーバ自身のIPアドレスを書く

-Djava.rmi.server.hostname=xxx.xxx.xxx.xxx

 

監視サーバの設定

 

Zabbix Java Gateway のインストール

Zabbix 2.2 の場合(であっても)、zabbix-server を入れただけでは JMX の監視はできない。

ソースをダウンロードしてビルドする方法もあるが、パッケージが公開されているのでそのままインストールしたほうが簡単だ。

実行例 (サービス登録および起動も実施)

# rpm -Uv http://repo.zabbix.com/zabbix/2.2/rhel/6/x86_64/zabbix-java-gateway-2.2.0-1.el6.x86_64.rpm
# chkconfig zabbix-java-gateway on
# service zabbix-java-gateway start

設定ファイルの編集
  • /etc/zabbix/zabbix_server.conf の修正 (一部抜粋)
    Timeout=30
    JavaGateway=127.0.0.1
    JavaGatewayPort=10052
    StartJavaPollers=5

    Java Gateway はデフォルトでは10052ポートで起動する。
    Timeout の修正(デフォルト5秒) については、デメリットもあるので問題が起きた場合にのみ書き換えたほうがよいかもしれない。

    参考: zabbix_server.confのTimeoutについて | ZABBIX-JP

設定ファイルを保存したら、zabbix-server から再読み込み (または再起動)。

監視設定

ここから先は Zabbix の管理画面(GUI)での操作となる。

ホスト設定

Configuration -> Hosts -> 監視対象サーバ を選択。
JMX interfaces の部分で Add をクリックし、IPアドレスとJMXポートを指定して Save。

テンプレート・アイテム設定

ひとまずは標準の Template JMX Generic を使ってみるのを勧める。

Configuration -> Templates -> Template JMX Generic を選択。
Group または Host の追加を行った後、Save。

ダッシュボード画面で ホストにひもづく JMX のアイコンが緑色になればOKだ。

References

 

12.13.2013

Installing Docker on CentOS 6.5 (with Vagrant and VirtualBox)

Vagrant+VirtualBox 環境の CentOS 6.5 に Docker をインストールする

 

こちらのブログポストの内容を実践してみた。

なぜ Docker か

Docker とは、Linux のホストOS上で複数の仮想 Linux OS(コンテナ)を実行するためのソフトウェア。

VMWare のようなハイパーバイザー型の仮想OSと異なり、ハードウェア層やカーネルの大部分が共通して使われるため、パフォーマンスのオーバーヘッドが少ない。

LXC (Linux Containers) と aufs (Advanced multi layered unification filesystem) という要素技術が使われており、
Docker自体は Go言語で記述されている。

Docker を使うモチベーションを挙げれば以下のような感じだ。

  • とにかく起動が速い
    aufs の恩恵により、差分ベースでファイルシステムが構築されていく。
    一瞬でOSが立ち上がる様は感動的ですらある。

    Immutable Infrastructure (出典: Trash Your Servers and Burn Your Code: Immutable Infrastructure and Disposable Components - Chad Fowler) の前に立ちはだかっていた壁の一つが音もなく崩れ去った瞬間を目の当たりにしている。

    仮想化技術によって、インフラの「作って捨てて」を非常に短いサイクルでできるようになった結果、
    我々はこれまで混然としていた Immutable (OS, ミドルウェアのバージョン、コンフィギュレーションなど) と Mutable (各種ログ、エラー通知、リソース推移など) の意味的な区別に専念できるようになったのだ。
  • 開発PCのローカル環境 -> CI環境 -> ステージング環境 -> プロダクション環境と、 同一性が保証されたインフラをハードウェア構成に依存せずに作成することができ、 しかもその内容をコードとして管理できる。 (Infrastructure as Code)

    Docker at eBay // Speaker Deck
    (プロダクション環境での利用実績はまだ少ないようだが)
  • 従って、たとえばCI環境で使えば、DB の状態に依存するテストでも並列かつ迅速に実行できる。

 

目的

Mac OS (Mavericks) 上で Vagrant を実行し、VirtualBox 上に CentOS 6.5 インスタンスを作成。
そこに Docker をインストールし、さらにその上に複数のゲストコンテナを実行できるようにする。

事前準備

  • Vagrant インストール
  • VirtualBox インストール

ホストOSのセットアップ

とりあえず今日は Mac 上で Vagrant を実行し、VirtualBox 内のホストOS(いわゆる母艦)に Docker をインストールするまで。

  • VirtualBox Guest Additions を更新するため、Vagrant プラグイン vagrant-vbguest をインストール
  • opscode のテンプレートを利用して vagrant init
  • Vagrantfile を編集し、後処理として epel から docker パッケージを取得しインストール、起動
  • vagrant up
  • Docker 上で Hello World!

 

 

References

12.12.2013

How to Solve Vagrant+CentOS+VirtualBox Mount Error

Vagrant+CentOS+VirtualBox: ゲストOS起動時のマウントエラーの調査

 

事象

Vagrant で CentOS 6 の VirtualBox 用イメージを立ち上げようとしたところ、以下のようなエラーが出てしまった。

$ vagrant up <HOSTNAME>

(略)

[HOSTNAME] Mounting shared folders...
[HOSTNAME] -- /vagrant
Failed to mount folders in Linux guest. This is usually beacuse
the "vboxsf" file system is not available. Please verify that
the guest additions are properly installed in the guest and
can work properly. The command attempted was:

mount -t vboxsf -o uid=`id -u xxxxxxxx`,gid=`getent group xxxxxxxx | cut -d: -f3` /vagrant /vagrant
mount -t vboxsf -o uid=`id -u xxxxxxxx`,gid=`id -g xxxxxxxx` /vagrant /vagrant

このメッセージだけでは、VirtualBox Guest Additions (以下、Guest Additions) の機能である共有フォルダのマウントに失敗していることくらいしか分からない。

ちなみに Guest Additions とは、簡単に言えば VirtualBox ゲストの管理に特化した便利ツールだ。

これを利用しないなら無視しても構わないのだろうが、やっぱり気になるので調べてみる。

 

調査

vagrant status コマンドを実行して、OS自体は起動していることは確認できた。

$ vagrant status

Current machine states:

HOSTNAME                  running (virtualbox)

SSH 接続をしてみよう。

$ vagrant ssh <HOSTNAME>

以下はゲストOS上のプロンプト。
Guest Additions の状態を確認すると、停止状態であることが分かる。

$ service vboxadd status
The VirtualBox Additions are not currently running.

Guest Additions のインストール自体が失敗している可能性があると考え、ログを確認する。

$ cat /var/log/vboxadd-install.log
/tmp/vbox.0/Makefile.include.header:97: *** Error: unable to find the sources of your current Linux kernel. Specify KERN_DIR=<directory> and run Make again.  中止.
Creating user for the Guest Additions.
Creating udev rule for the Guest Additions kernel module.

やはりここに答えがあった。
カーネルのソース (kernel-devel) が不足していたために、Guest Additions のビルドが失敗していたのだった。

対応

 

誤った対応

パッケージが足りないなら、yum でインストールすればよいと安直に

$ sudo yum install kernel-devel -y

と実行するのはよくない。

上記のコマンドでは (基本的に) 最新の kernel-devel がダウンロードされるため、
実際のカーネルバージョンと異なるものがインストールされてしまう可能性があるためだ。

カーネルバージョンと kernel-devel が食い違った状態で Guest Additions のセットアップをすると、やはりビルドは失敗となる。

$ sudo /etc/init.d/vboxadd setup
Removing existing VirtualBox non-DKMS kernel modules       [  OK  ]
Building the VirtualBox Guest Additions kernel modules
The headers for the current running kernel were not found. If the following
module compilation fails then this could be the reason.
The missing package can be probably installed with
yum install kernel-devel-2.6.32-358.el6.x86_64

Building the main Guest Additions module                   [失敗]
(Look at /var/log/vboxadd-install.log to find out what went wrong)
Doing non-kernel setup of the Guest Additions              [  OK  ]

それぞれのバージョンは以下のようなコマンドで確認できる。

$ uname -r
2.6.32-358.el6.x86_64
$ rpm -qa |grep kernel-devel
kernel-devel-2.6.32-431.el6.x86_64

アンインストール。

$ sudo yum remove kernel-devel

 

 

正しい対応

では、適切なバージョンの kernel-devel をインストールするにはどうしたらよいか。

残念ながら、このまま yum でバージョンを指定してもうまくいかない。

$ sudo yum install kernel-devel-$(uname -r) -y
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.riken.jp
 * extras: ftp.riken.jp
 * updates: ftp.riken.jp
Setting up Install Process
No package kernel-devel-2.6.32-358.el6.x86_64 available.
Error: Nothing to do

古いバージョンのパッケージは CentOS-Vault リポジトリに置かれている。
以下いずれかの方法で対応が可能だ。

  • /etc/yum.repos.d/CentOS-Vault.repo ファイルを編集
    適切なOSバージョンの記載を追加し、「enabled=0」 を「enabled=1」へ書き換える
  • URLを指定して直接ダウンロード
    $ sudo yum install http://vault.centos.org/6.4/os/x86_64/Packages/kernel-devel-$(uname -r).rpm

インストールを終えたらゲストOS上で、Guest Additions のセットアップを再度実行。

$ sudo /etc/init.d/vboxadd setup
Removing existing VirtualBox non-DKMS kernel modules       [  OK  ]
Building the VirtualBox Guest Additions kernel modules
Building the main Guest Additions module                   [  OK  ]
Building the shared folder support module                  [  OK  ]
Building the OpenGL support module                         [  OK  ]
Doing non-kernel setup of the Guest Additions              [  OK  ]
Starting the VirtualBox Guest Additions                    [  OK  ]

うまくいった。

$ service vboxadd status
The VirtualBox Additions are currently running.

目的は達成できたので、一度ゲストOSから抜け、Vagrant から再起動する。

$ vagrant reload <HOSTNAME>

マウントエラーは晴れて解消された。

 

 

References

7.16.2013

Installing tmux with Fabric

Fabric で tmux をインストール

yum でインストールするだけだけど。

# -*- coding: utf-8 -*-
"""
Installing tmux.
"""

from fabric.api import *
from fabric.decorators import runs_once, roles, task

env.user = 'ec2-user'
env.use_ssh_config = True

@task
def install():
    """Install tmux."""
    sudo('yum -y install tmux')

これで、寝ている間も安心して AWS に仕事を任せられる。

 

References

tmux 公式

7.15.2013

How to Copy Text in Vim with iTerm

iTerm の Vim 上でテキストをコピーする

デフォルトの状態では、iTerm で Vim 等を開いた時
マウスで範囲を選択してもコピー・ペーストを行うことができない。 

プロファイルのターミナル設定で、「Enable xterm mouse reporting」のチェックを外したら
コピペできるようになった。

Preferences 2

 

追記: 2013-07-16

@todashuta 様より追加情報を頂きました。ありがとうございます。

7.07.2013

How to Set Up IRC Server on CentOS

CentOS で IRC サーバの構築

以下、簡単なメモのみ。

  • 今回選んだサーバは ngIRCd
    ngIRCd: Next Generation IRC Daemon
  • EPEL リポジトリへ接続可能な状態にして yum コマンドでインストール
    EPEL/ja - FedoraProject 
    # yum install ngircd
  • /etc/ngircd.conf を編集
    最新のサンプル(http://ngircd.barton.de/doc/sample-ngircd.conf)を参考にカスタマイズ。
    バージョンアップに伴い、[Limits] や [SSL] が使えるようになっている。 
  • /etc/ngircd.motd を作成
    Message Of The Day。空ファイルでもよい。 
  • 構文チェック
    # ngircd --configtest
     
  • サービス追加、起動
    # chkconfig ngircd --add
    # service ngircd start
     
  • 必要に応じて iptables 等の設定を変更

 

Setup Shogi-server on AWS with Fabric

AWS: shogi-server を Fabric で構築する

目的

コンピュータ将棋のネット対局用サーバ shogi-server を AWS の EC2 インスタンス上に構築する。

このとき、全ての設定作業を Fabric で完結させたい。

 

前提

 

準備するもの

 

iptables

shogi-server (CSAプロトコル) で使う 4081 ポートを許可、ロギング設定など。

# Firewall configuration written by system-config-firewall
# Manual customization of this file is not recommended.
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 4081 -j ACCEPT
-N LOGGING
-A INPUT -j LOGGING
-A LOGGING -j LOG --log-level warning --log-prefix "DROP:" -m limit
-A LOGGING -j DROP
COMMIT

 

sudoers

sudo の際に環境変数 PATH を引き継ぐようにしないと、なぜか Ruby のインストールに失敗してしまう。
env_keep に PATH を追記した sudoers ファイルをあらかじめ用意しておく。

# diff -u ./sudoers.20130707 ./sudoers
--- ./sudoers.20130707	2013-05-10 03:53:29.636195742 +0900
+++ ./sudoers	2013-07-07 11:47:48.647961526 +0900
@@ -76,6 +76,7 @@
 Defaults    env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
 Defaults    env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
 Defaults    env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
+Defaults    env_keep += "PATH"
 
 #
 # Adding HOME to env_keep may enable a user to run unrestricted

 

起動スクリプト

shogi-server をサービスとして登録し、起動/停止を行うためのスクリプト。
/etc/init.d/shogi-server として配備。

PIDファイルを /var/run、ログを /var/log/shogi-server 配下に作成している。

サービスは専用ユーザ shogi で実行される。

#!/bin/bash
#
# Start/Stop shogi-server daemon
#
# chkconfig: 2345 85 15
# description: shogi-server daemon mode

PROC_NAME=shogi-server
PROC_USER=shogi
PROC_GROUP=shogi
PROC_BIN=/opt/shogi-server/shogi-server
PID_FILE=/var/run/shogi-server.pid
DAEMON_LOG_DIR=/var/log/shogi-server
PLAYER_LOG_DIR=$DAEMON_LOG_DIR/player-logs
CONSOLE_LOG=$DAEMON_LOG_DIR/console.log

EVENT_NAME=event1
PORT_NUMBER=4081

# Sanity checks
[ -x $PROC_BIN ] || exit 1

# Source function library & LSB routines
. /etc/rc.d/init.d/functions

RETVAL=0

start()
{
    echo -n $"Starting $PROC_NAME: "

    mkdir -p $DAEMON_LOG_DIR $PLAYER_LOG_DIR
    touch $PID_FILE
    chown $PROC_USER:$PROC_GROUP $DAEMON_LOG_DIR $PLAYER_LOG_DIR $PID_FILE

    su - $PROC_USER -c \
        "ruby $PROC_BIN --daemon $DAEMON_LOG_DIR --pid-file $PID_FILE \
        --player-log-dir $PLAYER_LOG_DIR $EVENT_NAME $PORT_NUMBER \
        > $CONSOLE_LOG 2>&1"
    RETVAL=$?
    if [ $RETVAL -eq 0 ]; then
        success
    else
        rm -f $PID_FILE
        failure
    fi
    echo
}

stop()
{
    echo -n $"Stopping $PROC_NAME:"
    if [ -f $PID_FILE ]; then
        killproc -p $PID_FILE $PROC_NAME -TERM
        rm -f $PID_FILE
    fi
    RETVAL=$?
    [ $RETVAL -eq 0 ] && success || failure
    echo
}

case "$1" in
    start)
        start
        RETVAL=$?
        ;;
    stop)
        stop
        RETVAL=$?
        ;;
    status)
        status -p $PID_FILE $PROC_BIN
        RETVAL=$?
        ;;
    restart)
        stop
        start
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart}"
        RETVAL=2
        ;;
esac

exit $RETVAL

 

logrotate 定義ファイル

ログファイルの洗い替えは logrotate を利用する。
/etc/logrotate.d/shogi-server として配備。

/var/log/shogi-server/shogi-server.log
/var/log/shogi-server/player-logs/*.log {
    weekly
    rotate 4
    missingok
    notifempty
    copytruncate
    compress
}

 

Fabric 用スクリプト

Fabric で使う Python スクリプト。
env.hosts はハードコーディングして使ってもよい。

標準APIの put 関数にも sudo 機能があるものの、SELinux 対応やバックアップ作成などが物足りなかったので
独自の _put という関数でラップしている。

EC2 のファイアウォール設定もこのスクリプトに含めているが、分離させた方がいいかもしれない。

# -*- coding: utf-8 -*-
"""
Installing shogi-server and its dependencies.
"""

import os
import json
from fabric.api import *
from fabric.decorators import runs_once, roles, task

env.user = 'ec2-user'
# env.hosts = []
env.use_ssh_config = True

WORK_DIR = os.path.dirname(os.path.abspath(__file__))

APL_USER = 'shogi'
APL_GROUP = 'shogi'
APL_HOME = '/home/%s' % APL_USER

GIT_RBENV = 'git://github.com/sstephenson/rbenv.git'
GIT_RUBY_BUILD = 'git://github.com/sstephenson/ruby-build.git'
GIT_SHOGI_SERVER = \
    'git://git.sourceforge.jp/gitroot/shogi-server/shogi-server.git'

RUBY_VERSION = '1.9.3-p448'

EC2_SECURITY_GROUP = 'quick-start-1'


@task
def setup():
    """Setup tasks for shogi-server."""

    setup_os_user()
    setup_firewall()
    install_ruby()
    install_shogi_server()


@task
def setup_os_user():
    """Add 'shogi' user and 'shogi' group."""

    if sudo('id %s' % APL_USER, quiet=True).succeeded:
        return

    # Add user and group.
    sudo('groupadd -g 501 %s' % APL_GROUP)
    sudo('useradd -u 501 -g %s %s' % (APL_GROUP, APL_USER))

    # Copy sudoers.
    _put('%s/sudoers' % WORK_DIR, '/etc/sudoers', '440', 'root', 'root')


@task
def setup_firewall():
    """Configure linux and EC2 firewall.
        AWS CLI and its connection settings are required."""

    # Linux iptables
    _put('%s/iptables' % WORK_DIR, '/etc/sysconfig/iptables',
         '600', 'root', 'root')
    sudo('service iptables restart')

    # EC2 firewall
    port = 4081
    cidr = '0.0.0.0/0'
    old = local('aws ec2 describe-security-groups', capture=True)
    j = json.loads(old)

    found = (EC2_SECURITY_GROUP, port, cidr) in (
        (a['GroupName'], b['FromPort'], c['CidrIp'])
        for a in j['SecurityGroups']
        for b in a['IpPermissions']
        for c in b['IpRanges'])

    if not found:
        opts = '--group-name %s --ip-protocol tcp ' % EC2_SECURITY_GROUP
        opts += '--from-port %d --to-port %d --cidr-ip %s' % (port, port, cidr)
        local('aws ec2 authorize-security-group-ingress %s' % opts)


@task
def install_ruby():
    """Install git, rbenv, ruby-build and ruby."""

    # Install git.
    sudo('yum -y install git')

    # Install rbenv.
    with cd('/usr/local'):
        sudo('git clone %s %s' % (GIT_RBENV, 'rbenv'))
        sudo('mkdir rbenv/shims rbenv/versions')

    # Install ruby-build.
    with cd('/usr/local'):
        sudo('git clone %s %s' % (GIT_RUBY_BUILD, 'ruby-build'))
    with cd('/usr/local/ruby-build'):
        sudo('./install.sh')

    # Create system-level profile.
    profile = '/etc/profile.d/rbenv.sh'
    sudo("""echo 'export RBENV_ROOT="/usr/local/rbenv"' > %s""" % profile)
    sudo("""echo 'export PATH="/usr/local/rbenv/bin:$PATH"' >> %s""" % profile)
    sudo("""echo 'eval "$(rbenv init -)"' >> %s""" % profile)

    # Install requirements.
    sudo('yum -y groupinstall "Development Tools"')
    sudo('yum -y install openssl-devel readline-devel zlib-devel')

    # Install ruby.
    sudo('su - -c "rbenv install 1.9.3-p448"')
    sudo('su - -c "rbenv global 1.9.3-p448"')
    sudo('su - -c "rbenv rehash"')


@task
def install_shogi_server():
    """Install and start shogi-server as a service."""

    shogi_path = '/opt/shogi-server'

    if sudo('test -d %s' % shogi_path, quiet=True).succeeded:
        return

    # Clone from repository.
    sudo('git clone %s %s' % (GIT_SHOGI_SERVER, shogi_path))
    sudo('chown -R %s:%s %s' % (APL_USER, APL_GROUP, shogi_path))

    # Copy init script.
    _put('%s/shogi-server.init' % WORK_DIR, '/etc/init.d/shogi-server',
         '755', 'root', 'root')

    # Add and start service.
    sudo('chkconfig --add shogi-server')
    sudo('service shogi-server start')

    # Copy logrotate setting.
    _put('%s/shogi-server.logrotate' % WORK_DIR,
         '/etc/logrotate.d/shogi-server', '644', 'root', 'root')


def _put(src, dst, mode, owner, group):
    tmp = '/tmp/%s.tmp' % src.split('/')[-1]
    backup_opts = '--backup=simple --suffix=.`date +%Y%m%d`'
    permission_opts = '-m %s -o %s -g %s' % (mode, owner, group)

    put(local_path=src, remote_path=tmp)
    sudo('install %s %s %s %s' % (backup_opts, permission_opts, tmp, dst))
    sudo('rm -f %s' % tmp)

 

実行方法

fab コマンドで実行。Microインスタンスで20分弱で完了。

$ fab -f ./shogi-server.py --list
$ fab -f ./shogi-server.py -H 対象サーバ setup

6.30.2013

AWS: EC2 Settings for System Time

AWS: EC2 RHELインスタンスの時刻周りの設定

NTPの設定

ntpd が起動していなくても

/sys/devices/system/clocksource/clocksource0/current_clocksource

が 「xen」 に設定されていれば、このゲストOSはホストノードの時刻と同期されている。

つまり、初期状態で何もしなくても時刻同期は行われていると考えてよい。

タイムゾーンの設定

システムのタイムゾーンを日本時間に変えるには、/etc/localtime を書き換える必要がある。
fabric のスクリプト(かなり手抜き)で実施。

# -*- coding: utf-8 -*-
"""
Initial setup for AWS EC2.
"""

from fabric.api import local, env, cd, lcd, run, sudo, put
from fabric.decorators import runs_once, roles, task

env.use_ssh_config = True


@task
def setup():
    """Initial setup."""
    _set_timezone()


def _set_timezone():
    sudo('mv -i /etc/localtime /etc/localtime.orig')
    sudo('ln -s /usr/share/zoneinfo/Asia/Tokyo /etc/localtime')

fab コマンド投入

$ fab -f ./setup_aws.py -H ec2-user@<対象サーバ> setup