2013年4月29日月曜日

[CentOS] Building Bewulf type PC cluster

Bewulf型PCクラスタを構築してみる。
目標は、
 「MPIライブラリを使ったサンプルプログラムを複数ノードで実行する」

今回構築するクラスタの概要は、
*ヘッドノード、スレーブノード2ノードの計3ノード
*すべてのノードは、CentOS release 6.4 minimal
*ヘッドノードは、/home のみをNFSにて共有する(ディスクレスに挑戦したかったけどまた今度

ネットワークは、下図の様になる。
192.168.200.0/24がクラスタ専用のネットワークです。

各ノードのスペックは、

node name      CPU                       RAM         HDD
bwhead       amd64 (1 core)*1     2 Gbyte       50Gbyte x 2*2
bwslv01      amd64  (1 core)     1 Gbyte       50 GByte
bqslv02      amd64  (1 core)     1Gbyte        50 GByte

*1 型名になっていないのは、今回構築したノードすべてが仮想マシンだからです。
*2 /home 用に1台、/用に1台



-目次-

[0] HeadノードへのOSのインストール
一番上の項目を選択
イメージをマウントしてますが、メディアテスト

Testを選択

OK



Continueを選択

OK

Next

Engilish

キーボードレイアウトの選択英字配列キーボードを使ってます。

Basic strage device


Yesを選択

ホスト名 ここでは、間違っていたので後でbwheadに修正しました。

タイムゾーン Tokyo/Asia


root のパスワード

パーティション構成を決めます

今回は、このように切ることにしました

Formatを押下

Write changes to diskを押下

Nextを押下


インストール中です

インストール完了 再起動します

再起動後 ログイン状況


[1] Head ノードの設定

A) ネットワークインターフェースの設定
前述のネットワーク構成図に沿って設定します。
/etc/sysconfig/network-scripts/ifcfg-eth0
ONBOOT=yes
BOOTPROTO=dhcp

/etc/sysconfig/network-scripts/ifcfg-eth1
ONBOOT=yes
BOOTPROTO=static
IPPADDR=192.168.200.1
NETMASK=255.255.255.0


B) /etc/hosts の編集
以下を追加
192.168.200.1 bwhead
192.168.200.2 bwslv01
192.168.200.3 beslv02
上記の編集を反映させるためにネットワークサービスを再始動
/etc/init.d/networking restart

C) DHCPサーバーのインストール
slaveノードへのOSのインストールは、物理マシンでの構築の演習としてPXEによるネットワークブートとします。ネットワークブートでは、ブートローダーの場所等の情報を配布するのにDHCPを用います。そこでDHCPサーバーを構築します。

yum list dhcp
でパッケージを検索

yum install dhcp
そして、設定ファイルを作成
---- /etc/dhcp/dhcpd.conf ------

#
# DHCP Server Configuration file.
#   see /usr/share/doc/dhcp*/dhcpd.conf.sample
#   see 'man 5 dhcpd.conf'
#

DHCPDARGS=eth1;

# network boot setttings
allow booting;
allow bootp;
option option-128 code 128 = string;
option option-129 code 129 = text;
next-server 192.168.200.1;
filename "pxelinux.0";


subnet 192.168.200.0 netmask 255.255.255.0{

  # default gateway
  option routers                192.168.200.1;
  option subnet-mask            255.255.255.0;

  option domain-name-servers    192.168.100.1;

  range 192.168.200.100 192.168.200.254;
  default-lease-time 21600;
  max-lease-time 43200;

  host bwslv01{
    hardware ethernet 08:00:27:9C:25:55;
    option host-name "bwslv01";
    fixed-address 192.168.200.2;
  }
 
  host bwslv02{
    hardware ethernet 08:00:27:29:4E:37;
    option host-name "bwslv02";
    fixed-address 192.168.200.3;
  }

   
}

------------------------------------



設定ファイルの構文チェック
service dhcpd configtest
service dhcpd start
chkconfig dhcpd on

dhcpの使うポートを開けておく
iptables  -I INPUT -i eth1 -p udp --dport 67:68 --sport 67:68 -j ACCEPT
再起動時に設定が無効にならないように
/etc/init.d/iptables save
ファイヤーウォールの再起動
/etc/init.d/iptables restart


D) tftpサーバーのインストール
ネットワークブートにおいてブートローダ等を配布するのに必要

yum install tftp tftp-server
/etc/xinetd.d/tfptd
chkconfig xinetd on
service xnetd start

chkconfig tftp on

E) slave ネットワークブートのための準備
syslinuxをインストールします。
yum install syslinux

PXEブートにブートローダ関係の必要なファイルをtftpの公開ディレクトリにコピーします。
cp /usr/lib/syslinux/pxelinux.0 /var/lib/tftpboot
cp /usr/lib/syslinux/menu.c32 /var/lib/tftpboot
cp /usr/lib/syslinux/memdisk /var/lib/tftpboot
cp /usr/lib/syslinux/mboot.c32 /var/lib/tftpboot
cp /usr/lib/syslinux/chain.c32 /var/lib/tftpboot

OS関係の必要なファイルをtftpサーバーの公開ディレクトリに取ってきます。
yum install wget
mkdir -p /tftpboot/images/centos/x86_64/6.4
cd /var/lib/tftpboot/images/centos/
wget http://linux.mirrors.es.net/centos/6.4/os/x86_64/images/pxeboot/initrd.img
wget http://linux.mirrors.es.net/centos/6.4/os/x86_64/images/pxeboot/vmlinuz

ブートローダメニューの設定ファイルを作成
---/var/lib/tftpboot/pxelinux.cfg/default---

default menu.c32
prompt 0
timeout 300
INTIMEOUT local

MENU TITLE PXE Menu

LABEL local
MENU LABEL Boot from local hard disk drive
LOCALBOOT 0

LABEL CentOS 6.4 x86_64
MENU LABEL CentOS 6.4 x86_64
KERNEL images/centos/6.4/x86_64/vmlinuz
APPEND load initrd=images/centos/6.4/x86_64/initrd.img devfs=nomount


--------------------------------------



tftp(udp 69番ポート)を開ける
iptables -A INPUT -m state --state NEW -i eth0 -p udp --dport 69 -j ACCEPT
再起動時に設定が無効にならないように
/etc/init.d/iptables save
ファイヤーウォールの再起動
/etc/init.d/iptables restart

フォワーディングを有効にする
-- /etc/sysctl.conf--
# Controls IP packet forwarding
net.ipv4.ip_forward = 1   # 0 から 1に変更
----------------------


[2] slavve ノードのOSインストール
仮想マシンを起動したら即座にF12キーを押下する

PXEブートするために「l」キーを押下する

予め行った設定が適切に行われていれば
tftpサーバーからブートロードがDLされてメニューが表示される
CentOSを選択して、Enterを押下
インストール中に用いる言語の選択

キーボードレイアウトの選択

OSインストーラーのメディア種別を選択。セキュリティ的には、
あまり宜しくないけどHTTPで取ってきます。

ネットワーク設定
IPv4は、DHCPにします。

NIC設定中

インストーラーイメージ取得中

これ以降は、Headノードと同じGUIなインストーラーが起動しての同じインストールとなる。



[3] ssh でのhead から slave へのパスワード無しログイン
MPIライブラリのデータの移動、設定ファイルの配布のための仕組みを構築します。
よくr系コマンドが用いられますが、自分の環境では、rootでのパスワード無しログインが
できるようにすることを断念したため、sshを用います。

A) slave ノードへssh-server のインストール
yum install openssh-server
scpを使うため
yum install openssh-client


/etc/ssh/sshd_configの以下のコメントをはずす
#PermitRootLogin yes -> PermitRootLogin yes

chkconfig ssh on
service sshd start

試しにrootで全てのslaveノードにログインしてみる

ssh root@192.168.200.n # n は、整数
ログインしたまま後の作業の準備
cd $HOME
mkdir .ssh


B) head ノードでの作業

公開鍵生成

ssh-keygen -b 1024 -t rsa
鍵のパスフレーズは空にしておく

公開鍵を全てのslaveノードに配布しておく。
scp ~/.ssh/id_rsa.pub root@192.168.200.n:.ssh/authorized_keys

クラスタは、外からの開始される接続を許可しないネットワーク内で運用するのでとりあえずSElinuxは無効化しておく。
setenforce 0
そして、起動後も無効になるように/etc/selinux/configのSELINUXTYPEを下記のようにdisabledに変更しておく。
SELINUXTYPE=diabled


C)シェルスクリプトの作成

各ノードに同様の実行するためのシェルスクリプトを用意( rshでも実現可能だが自分の環境では、rootでの実行がPermission Denied ど言われで実現できなかった


----${HOME}/utils/rssh.sh-----

#!/bin/bash
BEGIN_ADDR=2
END_ADDR=3
ADDR_PREFIX="192.168.200."

for i in `seq $BEGIN_ADDR $END_ADDR`
do
  DST_ADDR="$ADDR_PREFIX$i"
  echo "Processing for $DST_ADDR"

ssh $DST_ADDR<<EOF
$*
EOF

done

---------------------------
chmod 744 ${HOME}/utils/rssh.sh

各ノードにファイルコピーするためのコマンド
---${HOME}/utils/rsscp.sh---

#!/bin/bash
SRC_FILE=$1
DST_PATH=$2

BEGIN_ADDR=2
END_ADDR=3

ADDR_PREFIX="192.168.200."

for i in `seq $BEGIN_ADDR $END_ADDR`
do
  DST_ADDR="$ADDR_PREFIX$i"
  echo "Copying $SRC_FILE -> $DST_ADDR:$DST_PATH"

scp $SRC_FILE $DST_ADDR:$DST_PATH

done

--------------------------

D) /etc/hosts の配布

/etc/hosts を作成して
 ${HOME}/utils/rsscp.sh /etc/hosts /etc/hosts


[4] NIS を用いたアカウント一元管理

A) サーバーの構築

アカウントを一括管理するためにNISサーバーを構築する

まずは、サーバーのインストール
yum install ypserv

ドメインの設定 このドメインは、DNSとは関係がない
ypdomainname clnet

/etc/sysconfig/network に 先ほど設定したNISドメインを追加
NISDOMAIN = clnet

/var/yp/Makefile の編集(下記がオリジナルのファイルとの差分)
-----差分-----------------------

*** Makefile.org 2013-04-27 17:41:09.642037547 +0900
--- Makefile 2013-04-27 17:42:41.594036564 +0900
***************
*** 39,49 ****
 
  # Should we merge the passwd file with the shadow file ?
  # MERGE_PASSWD=true|false
! MERGE_PASSWD=true
 
  # Should we merge the group file with the gshadow file ?
  # MERGE_GROUP=true|false
! MERGE_GROUP=true
 
  # These are commands which this Makefile needs to properly rebuild the
  # NIS databases. Don't change these unless you have a good reason.
--- 39,49 ----
 
  # Should we merge the passwd file with the shadow file ?
  # MERGE_PASSWD=true|false
! MERGE_PASSWD=false
 
  # Should we merge the group file with the gshadow file ?
  # MERGE_GROUP=true|false
! MERGE_GROUP=false
 
  # These are commands which this Makefile needs to properly rebuild the
  # NIS databases. Don't change these unless you have a good reason.
***************
*** 114,120 ****
  # If you don't want some of these maps built, feel free to comment
  # them out from this list.
 
! all:  passwd group hosts rpc services netid protocols mail \
  # netgrp shadow publickey networks ethers bootparams printcap \
  # amd.home auto.master auto.home auto.local passwd.adjunct \
  # timezone locale netmasks
--- 114,120 ----
  # If you don't want some of these maps built, feel free to comment
  # them out from this list.
 
! all:  passwd shadow group hosts rpc services netid protocols mail \
  # netgrp shadow publickey networks ethers bootparams printcap \
  # amd.home auto.master auto.home auto.local passwd.adjunct \
  # timezone locale netmasks

--------------------------------


このままだとすべてのホストからNIS情報を引き出すことができるようになっているので
NIS情報を引き出せるホストを限定するために /var/yp/securenets を作成して
以下を書き込みます。
255.255.255.0 192.168.200.0


これで指定したネットワークに属するホストだけがNIS情報を引き出せるようになりました。
ここでサーバーデーモンの起動
/etc/rc.d/init.d/ypserv start
/etc/rc.d/init.d/yppasswdd start

そして、起動時に自動でデーモンが走るように以下を実行
chkconfig ypserv on
chkconfig yppasswdd on

/usr/lib64/yp/ypinit -m を実行
NISサーバーの情報を確認される。今回は、サーバーは1台体制(冗長化無し)なのでNISDOMAINで設定した内容が表示されていればおk

B) ファイヤーウォールの設定
portmapper が使う tcp と udp 111番ポートへの通信を受け入れるようにしておく。


C ) クライアントの準備 (サーバーマシンでも実行する)
./rssh.sh  ' echo "NISDOMAIN = clnet" >> /etc/sysconfig/network '
./rssh.sh "sed -ei 's/\(USENIS=\)no/\1yes/' /etc/sysconfig/authconfig "
./rssh.sh 'echo "domain clnet server bwhead" > /etc/yp.conf'

slaveノード用のNS設定ファイルを作成して配布する。
mkdir tmp
cd tmp
cp /etc/nsswitch.conf tmp.conf
スレーブ用設定ファルの変更。以下がオリジナルのファイルとの差分
------差分----------

*** /etc/nsswitch.conf 2013-04-29 15:43:35.280253996 +0900
--- tmp.conf 2013-05-06 22:59:03.979813909 +0900
***************
*** 30,38 ****
  #shadow:    db files nisplus nis
  #group:     db files nisplus nis
 
! passwd:     files nis
! shadow:     files nis
! group:      files nis
 
  #hosts:     db files nisplus nis dns
  hosts:      files dns nis
--- 30,38 ----
  #shadow:    db files nisplus nis
  #group:     db files nisplus nis
 
! passwd:     nis files
! shadow:     nis files
! group:      nis files
 
  #hosts:     db files nisplus nis dns
  hosts:      files dns nis

--------------------
cd
./rscp.sh ./tmp/tmp.conf /etc/nsswitch.conf

ypbind をインストールする
./rssh.sh 'yum -y install rpcbind'
./rssh.sh '/etc/rc.d/init.d/rpcbind start'
./rssh.sh 'chkconfig rpcbind on'

./rssh.sh 'yum -y install ypbind'
./rssh.sh '/etc/rc.d/init.d/ypbind start'
./rssh.sh 'chkconfig ypbind on'


D) ユーザーの追加 (適宜)
NISサーバーにて
useradd newuser_name
passwd newuser_name

以上で通常通りユーザーを追加した後

cd /var/yp
make

でNIS DBに追加したユーザーの情報を追加する。
これでもログイン出来ない場合は、まずクライアントマシンで
ypcat passwd して追加したユーザーの情報が反映されれているかチェック。

追加されているにもかかわらずログイン出来ない場合は、
/etc/ypserv.conf中の
files: 30

files: 0
に変更してキャッシュを無効にする。


[5] NFS の構築

すべてのノードでホームディレクトリを共有できるようにする。

A) サーバーの構築

yum -y install nfs-utils

共有するディレクトリに関する設定を行う /etc/exports に以下を追加

/home 192.168.200.0/24(rw,sync,no_root_squash,no_all_squash)

/home … 共有するディレクトリの指定
192.168.200.00/24 … 共有を許すネットワーク
sync … 遅延書き込みをしない
no_root_squash … root の特権を行こうにする
no_all_squash … そのままの権限でアクセスさせる

/etc/idampd.conf にドメインの設定をする。デフォルトでは、「Domain = 」を含む行がコメントアウトされているので有効にしてドメインを記述する。

Domain = clnet


起動していないデーモンを起動しておく
/etc/rc.d/init.d/rpcbind start
/etc/rc.d/init.d/nfslock start
/etc/rc.d/init.d/nfs start

起動時にデーモンが自動で起動するようにしておく

chkconfig rpcbind on
chkconfig nfslock on
chkconfig nfs on


B) クライアントの準備

サーバーマシンからシェルスクリプトを用いて実行する

./rssh.sh 'yum -y install nfs-utils'

先ほど編集したNFSサーバーの /etc/idamp


./rssh.sh '/etc/rc.d/init.d/rpcbind start'
./rssh.sh '/etc/rc,d/init.d/nfslock start'
./rssh.sh '/etc/rc.d/init.d/netfs start'

./rssh..sh 'chkconfig rpcbind on'
./rssh.sh 'chkconfig nfslock on'
../rssh.sh 'chkconfig netfs on'


ここからは、各ノードに直接ログインして操作する
まずは、サーバーのパーティションをマウントできるかをテスト


mount -t nfs bwhead:/home /home

df -h

でマウントされたかどうかを確認する。

次に起動時に自動でマウントされるように/etc/fstab を変更
以下の行を追記
bwhead:/home /home nfs bg,intr 0 0

bg… NFSでのマウントが失敗した時にバックグランドで試行を繰り返す。
intr … 停止しているプロセスをkillするために、割り込みを可能にする。
0 … dump頻度
0 … fchkパスのフィールド

さらにインストール時に切った/home のパーティションをマウントしないようにコメントアウトしておく。
これ以上ができたNFSクライアントマシンを再起動して無事にマウントされるかを確認しておく。


[6] OpenMPI のインストール(headノード含めすべてのノードで)
その前にgcc とg++ ,makeのインストール

yum -y install gcc
yum -y install gcc-c++
yum -y install make

今回は、OpenMPI Ver.1.6.4 を用いる。
wget http://www.open-mpi.org/software/ompi/v1.6/downloads/openmpi-1.6.4.tar.gz
cd openmpi-1.6.4
./configure --prefix=/usr/local
make all # 複数コアある場合は make -j num_proc all で並列コンパイルできるらしい

[7] サンプルプログラムの実行

実行用専用ユーザーをNISサーバーにて作る
useradd cltest
passwd cltest
NIS DBへの反映
cd /var/yp ; make

ヘッドノードにてログアウトしてcltestでログインする
以下のソースを作成
-----main.c------------

#include <stdio.h>
#include <mpi.h>

int main(int argc, char **argv){
int rank, size, namelen;
char name[256];

MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Get_processor_name(name, &namelen);
sleep(5);
printf("This is %d of %d on %s\n", rank, size, name);
MPI_Finalize();
return 0;
}

----------------------

mpicc main.c
でコンパイル。


実行前にライブラリサーチPATHをbashrcに追加
export LD_LIBRARY_PATH=/usr/local
source .bashrc


そして、root権限を得て/usr/local/etc/openmpi-default-hostfile (headノード)
にどのユーザーのジョブでも常に実行させたシステム共通の計算ノードを追記する。
以下例
bwhead
bwslv01
bwslv02

本来なら、ヘッドノードは、ジョブ実行のみで計算は行わないがホストPCのリソースがそんなに潤沢ではないためヘッドノードも追加した。


mpirun -np 3 a,out

これで下記の様に各ノードでの出力が表示されればクラスタ構築一応完了。
---実行結果-----

This is 0 of 3 on bwhead.clnet
This is 1 of 3 on bwslv01
This is 2 of 3 on bwslv02

----------------



[7]参考
http://kuni255.blogspot.jp/2013/04/iptables.html





2013年4月24日水曜日

[grub] コマンドラインからのLinuxのブート

Ver.0.9.7


上記のようなメニューページにて「c」キーを押下するとgrubのコマンドラインへ移行する。


helpコマンドを実行すると要約されたコマンドリストが表示される。

root コマンドで起動パーティションを指定する。なお、「root (hd0,」でtabキーを押下すると、パーティションのリストが表示される。



なお、(hd0,0) は、/dev/hda1 or /dev/sda1 という具合である。
次にkernelコマンドでカーネールをロードする。
以降は、調査中。



[CentOS] SELinux 無効化後のカーネルパニック

SELinuxを無効化後に再起動したら 




上記のように「  Kernel panic – not syncing: Attempted to kill init!」カーネルパニックをおこした。

グーグル先生に聞くと同じようなミスを犯す人が多いみたいですぐに解決策が分かった。

とりあえずPCを再起動させて「Booting CentOS .以下略」と表示中に間髪入れずに「Enter」keyを押下する。


するとGrub のメニューが表示されるので


「e」キーを押下して、起動リストを表示させる。


2番目のCentOS のカーネルをハイライトして再び「e」キーを押下する。そして、起動オプション「enforcing=0」を追記する。



追記したら「Enter」キーを押下して保存して元のページに戻り、「b」キーを押下して起動オプションを加えたコマンドで起動する。


起動後は、毎回この作業をせずに済むように /etc/grub.conf に先ほどと同様に「encorcing=0」オプションを追記しておく。

2013年4月23日火曜日

[CentOS] パスワード無しでrootとしてsshでログイン

ssh で公開鍵でrootログインする必要があり

サーバーにクライアントの公開鍵を登録して

/etc/ssh/sshd_config の

PermitRootLogin

を「Yes」にした後

クライアントから

ssh server

としてログインしてもパスワードを聞かれてしまう。

これで2・3日悩んでたw

結果 SELinuxが原因だった。

サーバー・クライアント共にセキュアなネットワーク内での仕様だったので



setenforce 0
そして、起動後も無効になるように/etc/selinux/configのSELINUXTYPEを下記のようにdisabledに変更しておく。

SELINUXTYPE=diabled

と無事パスワード無しでログインできる様になった。

SELinux については、こちらのサイトを中心に勉強させていただきたい。

2013年4月17日水曜日

[delphi] PEバイナリ

{$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE} としておくと

IMAGE_FILE_LARGE_ADDRESS_AWARE フラグが立ったPEバイナリをdccが吐いてくれて、


64bit Windowsではプロセスの仮想アドレス空間が4Gbyteになる。


[Windows] About virtualization of Registry

Windows Vista 以降のクライアント Windowsでは、特定のKeyへのアクセスがリダイレクトされる
この件について調べてみた

リダイレクトの挙動の概要は下記である。


                 ---------------  Yes  ---------------- Yes
Start ->---| 64bitカーネルの |-----| 32bitバイナリか? |-----> rule A 適用
                |  Windowsか ?     |        |                         |
                ----------------        ----------------
                         | No 32bit                       | No 64bitバイナリである
                         |     カーネルである          |
                         |------------------------------------> rule B 適用


[rule A]

64bit カーネルのWindowsにおいて32bitバイナリは、32bitプロセスとしてWOW 64(Windows On Windows 64)に32bit systemをエミュレートしてもらってその上を走るのでこのルールが適用されます。


HKEY_LOCAL_MACHINE\Software 配下等特定のレジストリキーへのアクセスは、Wow6432Nodeに含まれるロケーションにリダイレクトされます。

    HKEY_LOCAL_MACHINE\Software -> (リダイレクト先) HKEY_LOCAL_MACHINE\Software\Wow6432Node

[rule B]

  UACによるリダイレクト が行われる

  
HKEY_LOCAL_MACHINE\SOFTWARE ->(リダイレクト先) HKEY_CURRENT_USER\Software\Classes\VirtualStore




[WOW64環境で走っているかどうかの確認]
WOW64.pas


unit WOW64;

// wether OS is windows
{$IFDEF MSWINDOWS}
// wether target platform is Windows 32bit
{$IFDEF WIN32}
{$DEFINE MYTARGET}
{$ENDIF}
{$ENDIF}

interface

{$IFDEF MYTARGET}
uses Windows;
{$ENDIF}

function IsWOW64 : Boolean;

{$IFDEF MYTARGET}
var
  IsWow64Process : function(hProcess : THandle; var Wow64Process : BOOL) : BOOL stdcall;
{$ENDIF}

implementation

function IsWOW64 : Boolean;
{$IFDEF MYTARGET}
var
  Flg : BOOL;
begin
  Result := False;
  @IsWow64Process := GetProcAddress(GetModuleHandle('kernel32.dll'), 'IsWow64Process');
  if @IsWow64Process <> nil then begin
    if IsWow64Process(GetCurrentProcess, Flg) then Result := Flg;
  end;
{$ELSE}
begin
  Result := False;
{$ENDIF}
end;

end.


WOW64test.pas // エラーハンドリング をしていません。レジストリ書き込みを伴います。
unit wow64test;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, WOW64,Registry;

type
  TForm4 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form4: TForm4;

implementation

{$R *.dfm}

procedure TForm4.Button1Click(Sender: TObject);
const
 appKey = 'Software\RegTest';
var
 RegIni : TRegIniFile;
 val : string;
begin

  if IsWOW64 then begin
    showMessage('This process is running on Wow64');
  end else begin
    showMessage('This process is not running on Wow64');
  end;

  RegIni := TRegIniFile.Create(appKey);
  RegIni.RootKey := HKEY_CURRENT_USER;
  RegIni.WriteInteger('settings', 'value', 3);
end;

end.


XP (32bit) での実行結果


7 Pro (64bit) での実行結果

しかし、レジストリは、 HKEY_CURRENT_USER\RegTest\settings に書き込まれる。なぜ?






 なお、UAC制限によるリダイレクトは、Interactive process の場合は行われないらしいが、
Interactive process とは何なのか? 想像するにコマンドラインプログラムは、Interactive processではなさそうだが真相は不明

2013年4月15日月曜日

[ubuntu] evince でフォントを埋め込んでいないPDFの日本語が豆腐に化ける

 evince は,/etc/fonts/conf.avail の 69-language-selector-ja-jp.conf を
見て割り当てるフォントを決定しているがここに非日本語フォントが割り当てら
 れ ているために日本語部分が豆腐になる.
 以下は,修正用パッチ
 
 *** 69-language-selector-ja-jp.conf.org 2013-04-15 10:57:22.039956485 +0900
 --- 69-language-selector-ja-jp.conf 2013-04-15 10:59:19.140041561 +0900
 ***************
 *** 10,16 ****
 <string>serif</string>
 </test>
 <edit name="family" mode="prepend" binding="strong">
 - <string>DejaVu Serif</string>
 <string>Takao P明朝</string>
 <string>IPA P明朝</string>
 <string>IPA モナー P明朝</string>
 --- 10,15 ----
 ***************
 *** 28,34 ****
 <string>sans-serif</string>
 </test>
 <edit name="family" mode="prepend" binding="strong">
 - <string>DejaVu Sans</string>
 <string>Takao Pゴシック</string>
 <string>IPA Pゴシック</string>
 <string>IPA モナー Pゴシック</string>
 --- 27,32 ----
 

2013年4月14日日曜日

[DHCP] アドレスの再取得

こんなことは、めっったにないけどDHCP Serverの設定を変えてクライアントに変更を
反映させたいとき。

sudo dhclient -r
で借りていたアドレスをリリース(Release)

sudo dhclient
でアドレスを再取得

[iptables] NATの構築

Linux においてルーティングを行うには(REF)、

echo 1  > /proc/sys/net/ipv4/ip_forward


本エントリでは、192.168.200.0/24が内側のネットワーク、eth0がインターネットに繋がる外側のネットワークに接続されたインターフェースです。

iptables -t nat -A POSTROUTING -o eth0 -s 192.168.200.0/24 -j MASQUERADE


これに加えて@ITでは、


 iptables -A OUTPUT -o eth0 -d 10.0.0.0/8 -j DROP
 iptables -A OUTPUT -o eth0 -d 176.16.0.0/12 -j DROP
 iptables -A OUTPUT -o eth0 -d 192.168.0.0/16 -j DROP
 iptables -A OUTPUT -o eth0 -d 127.0.0.0/8 -j DROP

なる、設定をして「内部アドレスやプライベートアドレスが外部ネットワークに漏れないようにブロック」しているらしいがこの意味がわからない。とりあえずNAT自体は、構築でき通信が通っているのでひとまずOKとする。



[iptables] 基本

原則 /etc/sysconfig/iptables は直で編集せず iptables コマンドでルールを追加する


iptables commands  chain rule-specification target


[commands]

-A chain  chain にルールを追加する (Append)
-D chain rule-num chain rule-num 番のルールを削除する (Delete)
-L chain [--line-numbers] chain のルールを表示する (List) --line-numbersをつけるとルール番号も表示する

-I chain rule-num chain rule-num にルールを挿入する (Insert)



[chain]
INPUT OUTPUT FORWARDING PREROUTING POSTROUTING


[rule-specification]

-s  expression expressionの部分にホストのIPアドレスやネットワークアドレス(ex. 192.168.0.0/24)を記述して送信元(Source)を指定する。

-d expression -sと同様でこちらは、送信先(Destination)を指定する。

-i interface パケットが入ってくる(Input)インターフェースを指定する。

-o interface パケットが出て行く(Output)インターフェースを指定する。

-p protocol  protocol にはudp tcp icmp all 等が指定できる

-j target target を参照



--dport port(s) 送信先のポートやポート番号を指定する。(Destination Port)
--sport port(s) 送信元のポートやポート番号を指定する。(Source Port)

-TCP拡張-
-p tcpが指定された場合の拡張

--tcp-flags mask comp maskに評価されるフラグ、compに指定されたフラグが立っているパケットにマッチする。 --tcp-flags SYN,ACK,FIN,RST SYN ならばSYNフラグが立っていて、ACK,FIN,RSTフラグが立っていないパケットにマッチする。

--syn SYNフラグのみが立っている(ACK,RST,FINフラグが立っていない)パケットにマッチ。このオプションは、外からのTCP接続要求を拒否したい場合に使える。

-ICMP拡張-
-p icmp が指定された場合に

--icmp-type type

として対象とするICMPパケットを指定できる。typeにはecho-request等を指定する。
詳細は、iptables -p icmp -h として確認。


[target]

ACCEPT パケットを受け入れる
DROP    パケットを破棄する
REJECT パケット受け入れを拒否する(この場合は、DROPと違いICMPエラーを送信元ホストに返す。よって送信元アプリケーションは、タイムアウトにならずエラーとなる。)





[ルールの保存]
コマンドを実行しただけだと再起動後に設定が消えてしまう。保存したい場合は、

/etc/init.d/iptables save

[設定変更の反映]
/etc/init.d/iptables restart

[ブロックしたパケットの情報]
iptables -L --verbose

[ルールの一覧]
iptables -L --line-numbers

[ルールの削除]
iptables -D INPUT,OUTPUT,FORWARD rule-number


[オプション一覧]

-i 着信インターフェースを指定する
-o 送信インターフェースを指定する


参照元: http://www.turbolinux.co.jp/products/server/11s/user_guide/iptablescmd.html

2013年4月10日水曜日

[FreeBSD on VirtualBox] Guest Additions のインストール

Guest Additionsインストールの前にカーネルのソースが必要になるのでDLしておく

wget ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/9.1-RELEASE/srx.txz

tar xvfJ src.txz

mv ./usr/src/* /usr/src/

続いて Guest Additionsのインストール

cd /usr/ports/emulators/virtualbox-ose-additions/
make config-recursive
make
make install
make clean

次にxorg.confを編集するが自分は、まだxorg.confがなかったのでとりあえず、/etc/rc.conf の3行をコメントアウトしてX Serverが起動時に走らないようにしてリブート。

#hald_enable="YES"
#dbus_enable="YES"
#slim_enable="YES"

 リブート、再ログイン後
su
Xorg -configure

これで xorg.confのサンプル(xorg.conf.new)が/root に出力されている。
そして、次のセクションを適宜追加する。



Section "Device"
        ### Available Driver options are:-
        ### Values: <i>: integer, <f>: float, <bool>: "True"/"False",
        ### <string>: "String", <freq>: "<f> Hz/kHz/MHz"
        ### [arg]: arg optional
        Identifier "Card0"
        Driver "vboxvideo"
        VendorName "InnoTek Systemberatung GmbH"
        BoardName "VirtualBox Graphics Adapter"
        BusID "PCI:0:2:0"
EndSection

同様に次のセクションも


Section "InputDevice"
        Identifier "Mouse0"
        Driver "vboxmouse"
EndSection

さらに、下記の内容の/usr/local/etc/hal/fdi/policy/90-vboxguest.fdi を作成。


<?xml version="1.0" encoding="UTF-8"?>
<deviceinfo version="0.2">
  <device>
    <match key="info.subsystem" string="pci">
      <match key="info.product" string="VirtualBox Guest Service">
        <append key="info.capabilities" type="strlist">input</append>
        <append key="info.capabilities" type="strlist">input.mouse</append>
        <merge key="input.x11_driver" type="string">vboxmouse</merge>
        <merge key="input.device" type="string">/dev/vboxguest</merge>
      </match>
    </match>
  </device>
</deviceinfo>

以上ができたら /etc/rc.conf の先ほどコメントアウトした3行をコメントを外して有効にしてリブート
これで Guest Additions のインストールは、完了


hald_enable="YES"
dbus_enable="YES"
slim_enable="YES"





参考サイト https://wiki.freebsd.org/VirtualBox

2013年4月6日土曜日

[Windows] Microsoft提供の便利なツール群

http://technet.microsoft.com/ja-jp/sysinternals/bb545027

[Windows] PAEについて

[仮想アドレス空間全体]
Windows XPでは、PAEによる恩恵を受けることは、できない(物理アドレスの上限が4 GByteのまま)。

Windows Serverは、その限りではなく、C:\boot.ini に/PAEオプションを追加することで4GByte以上のRAMをサポートします。

ref: http://msdn.microsoft.com/ja-jp/library/windows/hardware/gg487503.aspx

[ユーザーモード仮想アドレス空間]
Windows2k/Windows XP(Later SP2)では、
C:\boot.iniの[Operating Systems]セクションにおいて
/3GBオプションを加えブートことでユーザーモードの仮想アドレス空間が3GByteになる。

[C] イベントハンドラのサンプル

#include <stdio.h>

typedef int (*EVHND)(int, int);

int proc(EVHND evhnd){
    printf("Error occured !!\n");
    if(evhnd != NULL) evhnd(4,2);
    return -1;
}

int evha(int a, int b){
    printf("event hundler A %d\n", a-b);
    return 0;
}

int evhb(int a,int b){
    printf("event hundler B %d\n", a+b);
    return 0;
}



int main(){
    proc(evha);
    proc(evhb);
    return 0;
}

2013年4月5日金曜日

[delphi] ユーザーデータ出力ディレクトリ等の取得

ユーザーデータをインストールディレクトリに出力するアプリケーションは、行儀が悪いです。
Windows Vista以降では、virtual storeの仕組みが導入されてましにはなりましたが。。。

というわけで、アプリケーションからWindows固有のディレクトリPATHを取得する関数 SHGetFolderPath を調べました。



procedure TForm2.Button3Click(Sender: TObject);
var
 path : String;
begin

  SetLength(path, MAX_PATH);
  if Succeeded( SHGetFolderPath(0, CSIDL_APPDATA, 0, SHGFP_TYPE_CURRENT, PChar(path) ) ) then begin
    ShowMessage(path);
  end;

end;

第1引数: 0
第2引数:  CSIDL_APPDATA // アプリケーションデータ出力ディレクトリ
参考 CSIDLについて 

第3引数:0 // Windows 2k 以前は、必ず0らしい
第4引数 SHGFP_TYPE_CURRENT // 現在の設定 デフォルトを得たい場合は SHGFP_TYPE_DEFAULT
第5引数: path


参考サイト

Windows Vista UAC Control with delphi

[delphi] 条件付きコンパイル プリプロセッシング

Cで言うところのマクロ

{$IFDEF CPUX64}
 64bit architecture dependency code
{$ELSEIF}
  ordinary code
{$ENDIF}

イマイチ自信がないけどこれで、64bit環境用のバイナリと32bit環境用バイナリを
区別して出力することができると思われる。

参考サイト: http://docwiki.embarcadero.com/RADStudio/XE3/ja/%E6%9D%A1%E4%BB%B6%E4%BB%98%E3%81%8D%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB%EF%BC%88Delphi%EF%BC%89

64bit delphi コンパイラについて http://docwiki.embarcadero.com/RADStudio/XE3/en/DCC64.EXE,_the_Delphi_64-bit_Command_Line_Compiler

[delphi] 例外処理

例外を投げるときに

raise Exception.Create('OOPS') at @MyFunction

と関数のアドレス渡しているのがあるけどあれはなんだろう?

当該サイト: http://docwiki.embarcadero.com/RADStudio/XE3/ja/%E4%BE%8B%E5%A4%96

参考になりそうなサイト: http://stackoverflow.com/questions/8950513/what-does-at-returnaddress-mean-in-delphi

2013年4月4日木曜日

[delphi] Windowsの環境変数の取得

%OS% や %PATH% 等の環境変数を取得するには、そのままの名前の「GetEnvironmentVariable」関数を使います。



procedure TForm2.Button1Click(Sender: TObject);
var
 env : String;
begin
  env := GetEnvironmentVariable('NUMBER_OF_PROCESSORS');
  showMessage(env);
    env := GetEnvironmentVariable('APPDATA');
  showMessage(env);
end;

なお、コマンドプロンプトで環境変数を表示するには、setコマンドを使います。(UNIXで言うところのechoコマンド)

> set APPDATA

現在定義されているすべての環境変数を表示するには、setコマンド単独で実行します(ここがechoコマンドとは違う)。

参考サイト
http://northaraba.blog17.fc2.com/blog-entry-310.html

http://www.geocities.jp/asumaroyuumaro/program/tips/GetEnvironmentVariable.html

http://homepage2.nifty.com/nonnon/Chinamini/20100001/20101116.html