2012/11/30
IPv4 アドレスがネットワークに属しているか調べる
ネットマスクとはその名の通り IPv4 アドレスのうち、
どこまでのビットがネットワークアドレスなのかを示しているので、
IPv4 アドレスとネットマスクの論理和はネットワークアドレスとなる。
そのため、取得した論理和とネットワークアドレスが等しい場合は
IPv4 アドレスはネットワークに属す事になる。
C で実装する場合はこんな感じかな。
1int checkAddr(const char *network, const char *netmask, const char *ipaddr) 2{ 3 4 struct in_addr net, 5 mask, 6 addr; 7 8 if(inet_aton(network, &net) && 9 inet_aton(netmask, &mask) && 10 inet_aton(ipaddr", &addr)) 11 return((addr.s_addr & mask.s_addr) == (net.s_addr & mask.s_addr)); 12 else 13 return(0); 14 15}
ちなみに仕事で実装した java のコード。
1boolean checkAddr(String network, String netmask, String ipaddr) 2{ 3 4 try { 5 int n = 0, 6 m = 0, 7 a = 0; 8 byte[] net = InetAddress.getByName(network).getAddress(), 9 mask = InetAddress.getByName(netmask).getAddress(), 10 addr = InetAddress.getByName(ipaddr).getAddress(); 11 12 for(int i=0; i<4; i++) 13 n |= ((int)net[i] & 0xff) << (8 * (3 - i)); 14 for(int i=0; i<4; i++) 15 m |= ((int)mask[i] & 0xff) << (8 * (3 - i)); 16 for(int i=0; i<4; i++) 17 a |= ((int)addr[i] & 0xff) << (8 * (3 - i)); 18 19 return((a & m) == (n & m)); 20 21 } catch (Throwable e){ 22 return false; 23 } 24 25}java はそれほど詳しくないのでコーディングが冗長だけど、 取りあえず動作している(気がする)。
2012/11/02
CentOS 6.3 インストール直後にする作業
仕事では Linux サーバ、特に CentOS の導入~初期設定の機会が多いので、 全ての CentOS 6.3 サーバの導入時に必ず行っている作業をメモする。
インストール作業は CentOS 6.3 の DVD から起動して行う。
CentOS 6 からはテキストベースのインストーラの場合、
パーティションの設定やファイルシステムの指定、
初期インストールされるパッケージの追加・削除など指定できないので、
GUI を利用した通常のインストールを実行する。
インストールが終了したら初期環境設定を行う。
以下の作業は CentOS 6.3 を導入したマシンでほぼ必ず実施する作業。
- 自分のユーザを作製する
-
# adduser アカウント # password アカウント
- 自分のアカウントを wheel グループに追加する
-
sudo (1) 可能な様に自分のアカウントを
wheel グループに追加する。
# (rm /etc/group; sed 's/^wheel.*/&,アカウント/g' > /etc/group) < /etc/group
- sudo(1) の設定を変更する
-
sudo(1) しても元の環境変数を保持する様設定
Defaults env_reset を Defaults !env_reset に変更 # Defaults env_keep += "HOME" のコメント記号 `#' を削除
wheel グループのアカウントのみ sudo (1) 可能にする# %wheel ALL=(ALL) ALL のコメント記号 `#' を削除
# visudo
- termcap を使用するアプリケーション対応
-
# ln -s /usr/lib/libtinfo.so /usr/lib/libtermcap.so.2
- selinux を無効にする
-
# (rm /etc/sysconfig/selinux; sed 's/^SELINUX=.*/SELINUX=disabled/' > /etc/sysconfig/selinux) < /etc/sysconfig/selinux# ex -s /etc/syconfig/selinux << EOF > /^SELINUX=/s/.*/SELINUX=disabled > wq > EOF2012/11/09 追記
CentOS の /etc/sysconfig/selinux は /etc/selinux/config へのシンボリックリンクで 実際は /etc/selinux/config を参照しているのだが、 rm (1) と sed (1) を使った方法だと /etc/sysconfig/selinux が通常ファイルになって 書き換わってしまい、元の /etc/selinux/config が 変更されていないために selinux が無効にならない という問題を指摘して頂いたので編集方法を修正しました。
- システム更新
-
# yum update
- 最低限必要なソフトウェアのインストール
-
システムを運用する上でこれだけは必要だとうソフトウェアを導入する。
# yum install openssh-clients libtermcap-devel tcpdump # yum install ntpdate telnet wget tcpdump unzip mlocate rsync bind-utils
- 開発環境のインストール
-
ソフトウェアを開発する場合は導入する。
通常はサーバでは開発しないので導入は不要な筈…
# yum install make gcc bison flex
- ファイアウォールの設定
-
グローバル環境に晒されるサーバであれば
最低限のファイアウォールは設定する必要がある。
基本的には以下のポリシーで必要に応じて追加・削除する。
#!/bin/sh iptables=/sbin/iptables # 全て初期化 ${iptables} -F # デフォルトルール ${iptables} -P INPUT DROP ${iptables} -P OUTPUT ACCEPT ${iptables} -P FORWARD DROP # ループバックを有効にする ${iptables} -A INPUT -i lo -p all -j ACCEPT # 接続済みのパケットを受け付ける ${iptables} -A INPUT -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT # http, httpsはどこからでもアクセス可 ${iptables} -A INPUT -p tcp --dport 80 -j ACCEPT ${iptables} -A INPUT -p tcp --dport 443 -j ACCEPT ${iptables} -A INPUT -p tcp --dport 8080 -j ACCEPT ${iptables} -A INPUT -p tcp --dport 9080 -j ACCEPT # dns パケットを許可 ${iptables} -A INPUT -p tcp --sport 53 -j ACCEPT ${iptables} -A INPUT -p udp --sport 53 -j ACCEPT ${iptables} -A INPUT -p tcp --dport 53 -j ACCEPT ${iptables} -A INPUT -p udp --dport 53 -j ACCEPT # ntp パケットを許可 ${iptables} -A INPUT -p tcp --dport 123 -j ACCEPT ${iptables} -A INPUT -p udp --dport 123 -j ACCEPT # そのほか必要なルールを記載 : :
上記設定を /tmp/firewall.sh に格納した場合、 ファイアウォールを有効にして設定をセーブする。# sh /tmp/firewall.sh # /etc/init.d/iptables save iptables: ファイアウォールのルールを /etc/sysconfig/iptableに保存中: [ OK ]
- 起動サービスの設定
-
起動サービスを設定する。
基本的には atd crond iptables network ntpd rsyslog sshd のみを有効にする
# for i in `chkconfig --list | awk '/:on/{ print $1 }'` > do > case $i in > atd|crond|iptables|network|ntpd|rsyslog|sshd ) > ;; > * ) > chkconfig $i off > chkconfig --del $i > ;; > esac > done
ここまで設定して再起動する。
MTA や httpd など固有のサービスは個々に設定する。
2012/10/31
hbstudy まとめ
先日参加した hbstudy #38 ハンズオンの
課題 の幾つかを
シェルのみ 縛りで回答してみる。
流石にシェルのみで解く場合はワンライナーは無理なので、
普通のシェルスクリプトの型式で記述している。
- 問題1: ユーザの抽出
-
/etc/passwd から、ユーザ名を抽出したリストを作って下さい
1IFS=: 2while read id other 3do 4 echo ${id} 5done </etc/passwd
IFS を : に変更して /etc/passwd を 直接フィールド分割して変数 u に read している。
- 問題2: ユーザの抽出
-
/etc/passwd から、次を調べて下さい。
ログインシェルが bash のユーザと sh のユーザどちらが多い?
1IFS=: 2while read id p u g e d shell 3do 4 case ${shell} in 5 */sh ) 6 sh=$((${sh} + 1));; 7 */bash ) 8 bash=$((${bash} + 1));; 9 esac 10done < /etc/passwd 11echo "bash: " ${bash} 12echo "sh: " ${sh}
問題:1 同様に IFS を : に変更して /etc/passwd を直接フィールド分割して 変数 u、shell に read し、 変数 sh と bash に出現回数をカウントしている。
- 問題5: FizzBuzz
-
1,2,3,4,5…と数えていって…
- 3 の倍数だったら数字の代わりに「Fizz」
- 5 の倍数だったら数字の代わりに「Buzz」
- 15 の倍数だったら数字の代わりに「FizzBuzz」
1i=1 2while [ ${i} -lt ${1:-100} ] 3do 4 if [ $((${i} % 15)) -eq 0 ] 5 then 6 echo -n "FizzBuzz," 7 elif [ $((${i} % 5)) -eq 0 ] 8 then 9 echo -n "Buzz," 10 elif [ $((${i} % 3)) -eq 0 ] 11 then 12 echo -n "Fizz," 13 else 14 echo -n "${i}," 15 fi 16 i=$((${i} + 1)) 17done 18echo
素直に 1 から $1 (指定されていない場合は 100) までを $((…)) にて % 演算子で剰余計算して出力している
- 問題8: CPU 使用率
-
top の出力からどのユーザが
何% CPU を使用しているか集計して下さい。
1exec 3<&0 0<< EOF 2`ps aux` 3EOF 4 5while read u p c other 6do 7 if [ "${u}" != "USER" ] 8 then 9 case ${users} in 10 *${u}* ) 11 ;; 12 * ) 13 users="${users} ${u}" 14 ;; 15 esac 16 eval "$u=\$((\$$u + ${c%%.*}))" 17 fi 18done 19 20for i in ${users} 21do 22 echo "${i} : `eval echo '$'$i`" 23done
CPU 使用率は小数点以下切り捨てで計算している。
出現したユーザID を users 変数に格納しておく。
eval と $((…)) を利用して、 ユーザID を変数名とした変数に CPU 利用率を集計している。
最後に for ループで users に格納された ユーザID とユーザIDを変数名とした変数に格納されている 集計値を表示している。
FreeBSD では top -b -n 1 が利用不可なので ps aux の出力を集計する
全てのスクリプトは FreeBSD 上の /bin/sh で動作確認済み。
手元に Linux 環境が存在しないので Linux での動作は未確認だけど、
posix 機能だけしか使用していない(筈)なので Linux でも動作すると思う。
2012/10/30
2012/08/27
2012/08/12
行き当たりばったり
折角の新車なのでドライブでも…と早朝 5 時に起床して出発。
新東名の駿河湾沼津 SA のリサとガスパールのカフェに行ってみたいので、
とりあえず本栖湖を目的地に設定し朝 6 時に出発する。
が、しかし既に東名高速は渋滞している様で、
VICS 信号を受信したナビは鶴川方面を通過して
高尾山の辺りから中央高速経由のルートを指示してくる。
ナビに従って走り続けると殆ど渋滞もしていない中央高速から
朝 9 時には河口湖に到着してしまう。
折角河口湖に早い時間に到着したので当初の目的をすっかり変更し
白鳥のボートなどに乗りつつ河口湖を満喫してると空腹になってきたので、
以前何度か行った山中湖のレストランに向かう事にする。
山中湖に向かうと丁度ランチタイムに無事到着。
別荘地の森の中にある隠れ家の様な燻製レストランの
とっても気持ち良いテラスで美味しいランチを楽しんでいると
気持ちはすっかり泊まりたいモードに…
お盆休みの始まる週末に空き室なんかある宿がある訳ないだろうと思いつつ
レストランのご主人に聞いてみた所、
偶然空いているペンションを紹介していただけたので計らずも宿が決定。
宿が決まったので安心して 3 人乗り自転車で山中湖を堪能したり、
温泉にのんびりつかったりと山中湖も満喫。
夕食はアメリカン風のコース料理だったのだが、
スターターからセンス良い味付けで最後まで大満足。
翌日は当初の目的通り本栖湖を経由して新東名高速へ。
念願のリサとガスパールカフェに立ち寄って軽く食事をして自宅へ。
行き当たりばったりで日帰りドライブの予定で出かけた筈なのに、 殆ど渋滞らしい渋滞にも遭遇せずに とっても充実した一泊の家族旅行が楽しめました。
家族一緒だと とっても楽しいね☆
2012/08/04
2012/08/03
2012/08/01
キーボードショートカットのカスタマイズ
Mac では システム環境設定 → キーボード →
キーボードショートカット から
アプリケーション毎、もしくはシステム全体で有効な
キーボードショートカットが独自に作成できる。
この機能を利用するとメニューに項目があるが
ショートカットキーが定義されていない機能に
独自のショートカットキーが簡単に定義できるので非常に便利だ。
但し登録できるショートカットキーに制限があり
スペースやバックスペースなどは登録できないので、
KeyRemap4MacBook
を組み合わせて利用する事で任意のショートカットが利用できる様に設定する。
例えば プレビュー では ツール メニューから
水平方向に反転 や 垂直方向に反転 などの機能が利用できるが、
これらの機能には標準ではショートカットが定義されていない。
そこで前述の キーボードショートカット 機能を利用して
プレビュー に 水平方向に反転のショートカットや、
垂直方向に反転のショートカットを
コントロールやシフトなどとの組み合わせで指定する。
ここでは 水平方向に反転 は コマンド+シフト+H、
垂直方向に反転 は コマンド+シフト+V を登録したとする。
ショートカットが登録できたら プレビュー を起動して
指定したショートカットが正しく動作するか確認しておく。
次に KeyRemap4MacBook でスペースを コマンド+シフト+H に、
バックスペースを コマンド+シフト+V に置き換える設定を行えば、
スペースやバックスペースなどでショートカットが実行可能になる。
この時、キーの置き換えは特定のアプリケーション
(今回は プレビュー)だけに限定すると良いだろう。
そのためには KeyRemap4MacBook の Misc & Uninstall から
Open private.xml をクリックして以下の設定を追加する。
1<?xml version="1.0"?> 2 <root> 3 <!-- アプリケーション "プレビュー" の定義 --> 4 <appdef> 5 <appname>PREVIEW</appname> 6 <equal>com.apple.Preview</equal> 7 </appdef> 8 9 <!-- "プレビュー" に対するキーマッピングの定義 --> 10 <item> 11 <name>Preview Key</name> 12 <identifier>private.PreviewKeys</identifier> 13 <only>PREVIEW</only> 14 <!-- スペースはコマンド+シフト+H に置換 --> 15 <autogen>--KeyToKey-- KeyCode::SPACE, KeyCode::H, ModifierFlag::COMMAND_L | VK_SHIFT</autogen> 16 <!-- バックスペースはコマンド+シフト+V に置換 --> 17 <autogen>--KeyToKey-- KeyCode::DELETE, KeyCode::V, ModifierFlag::COMMAND_L | VK_SHIFT</autogen> 18 </item> 19 </root>これらの設定を追加する事で プレビュー 上では スペースは コマンド+シフト+H に置換されてアプリケーションに 通知されるので、 登録したショートカット(水平方向に反転)が実行される事になる。
2012/07/27
シェルスクリプトで便利な小技
シェルスクリプトを作成するときに知っておくと便利な小技集。
- exec > ファイル
-
以降の標準出力を全て ファイル に出力するので
この設定をしておくと簡単な実行ログが取得出来る。
同様に exec 2> ファイル とすると 標準エラー出力が全て ファイル に出力されるので エラーログが取得できる。
当然 exec > ファイル 2>&1 とすれば 標準出力も標準エラー出力も取得できる。
ファイル に /dev/null を指定すれば スクリプト実行中の出力は全て抑止されるので、 cron (8) から実行される場合などでは便利な場合もある。
1#!/bin/sh 2 3exec 2> ${TMP:-/tmp}/myname.log 4 :
- set -e
-
スクリプト実行時に制御文以外でエラーが発生した場合に
スクリプトを終了させる。
スクリプト中で実行すべきコマンドを typo した場合などで、 以降の処理が実行されると困る場合などに特に役立つ。
1#!/bin/sh 2 : 3echo "call myfunc ..." 4mtfunc # 関数名を typo している 5echo "end myfunc ..." 6 :
この様なコードの場合 set -e されていると、 mtfunc がエラーになった時点でスクリプトが エラー終了するので以降の処理が実行されない。
当然 if、while 、&&、 || などでコマンドの結果が評価される場合は エラーにはならない。 - set -u
-
スクリプト中で値が設定されていない変数を参照した場合に
エラーメッセージを表示してスクリプトを終了させる。
シェル変数や環境変数を typo した場合など、 変数に値が設定されていない事で発生する問題が回避できる。
1#!/bin/sh 2tempdir=/var/tmp/ 3mynam=myname 4 : 5rm -rf ${tmpdir}/${myname} # 変数名を typo している 6 :
この様なコードの場合、 変数名 ${tempdir} と ${mynam} を それぞれ typo しているので、 結果として rm -rf / に展開されてしまうが、 set -u されていると実行が防げる。 - set -n
- こちらはどちらかと言うとスクリプトの開発時に有効な設定で、 コマンドは実行されないのでスクリプトの文法チェックに最適。
- set -x
-
こちらも開発時に有効な設定で、
コマンドが実行される前にコマンドを stderr に出力する。
上の exec と組み合わせると 詳細な実行ログが取得できるのでデバッグに便利1#!/bin/sh 2 3exec 2> ${TMP:-/tmp}/debug.log 4set -x 5 :