メインコンテンツまでスキップ

Linuxコマンドで複数ファイルの文字コードを一括変換

· 約2分
Yu Sasaki
Enterprise Security Manager / Advisor

Linux系OSのfedora6のデフォルト文字コードはUTF8なので、先日久々に参照したEUCのC++ソースコード中のコメントや出力が文字化けしていました。

そこで、ファイルの文字コードをEUCからUTF8に変換するコマンドを調べたところ、PHPプロ!TIPS+のページの中程にそれに関するコマンドがあったので参考にしました。

$find -name '*.cc' | xargs nkf --overwrite -w

↑は拡張子がccの全てのテキストファイルの文字コードをutf8に変換します。

$find . -type f -print0 | xargs -0 nkf --overwrite -w -Lu

↑このコマンドの意味を簡単に示しますと、まずファイルを検索するfindコマンドで、カレントディレクトリ「.」から通常ファイル「-type f」を探索し出力します「-print0」(常に真)。

% find [検索開始ディレクトリ] (option) 参考:UNIXコマンド [find]

ここで、findコマンドの結果をパイプ「|」をもって渡し、そこでxargsでコマンドを実行します。ここでxargsは以下の機能を持ちます。

xargs[えっくす・あーぐす] 標準入力から引数を読み込み、指定のコマンドを実行するコマンド 参考:UNIXの部屋 検索:xargs (*BSD/Linux/Solaris)

文字コード変換コマンドである nkf のオプション--overwriteは変換した文字コードのデータを元のファイルに上書きするもので、-wが文字コードをUTF8に指定するものです。ちなみに、EUCに変換したい場合は-e、Windowsで使われているSJISにする場合は-sを代わりに指定します。

最後の-Luオプションは改行コードをLFに指定するものです。

Eclipse+CDTを用いてプロジェクトを作成する際の注意点

· 約2分
Yu Sasaki
Enterprise Security Manager / Advisor

以前、K-na TechNotes | Homeのページを参考にWindowsでEclipse3.3とCDTをインストールしました。分かりやすく書かれており、とても参考になりました(謝々)。 たまたまK-na TechNotes | CDT のトラブル対策ページ下部にある

<実行>を押しても、デバッグしても、必ず「アプリケーション・エラー 起動に失敗(バイナリ・ファイルがありません)」のメッセージが出ます。

という件を見て、この症状の理由はProject typesの設定ミスではないかと推測しました。

プロセスの監視&自動復旧(簡易版)

· 約1分
Yu Sasaki
Enterprise Security Manager / Advisor

プロセス監視シェルスクリプトの実行結果

先日書いたシェルスクリプトでプロセスを監視し自動実行&自動killのシェルスクリプトは、その後結局使わず、さらに簡易的なコードで済ませました。

クエリーサーバのチェックスクリプト

scheckp.sh

#!/usr/bin/sh
while true
do
isAliveSev=`ps -ef | grep "/server" | grep -v grep | wc -l`
if [ $isAliveSev = 1 ]; then
echo "o:server process"
else
echo "x:server process"
/ret/sev/server &
fi
sleep 300 # モニター間隔(秒単位)
done

エンジンサーバのチェックスクリプト

echeckp.sh

#!/usr/bin/sh
while true
do
isAliveEng=`ps -ef | grep "/engine" | grep -v grep | wc -l`
if [ $isAliveEng = 1 ]; then
echo "o:engine process"
else
echo "x:engine process"
/ret/eng/engine &
fi
sleep 300 # モニター間隔(秒単位)
done

Ruby: メソッドの引数にブロックを渡す

· 約2分
Yu Sasaki
Enterprise Security Manager / Advisor

ブロックの使い方を練習してみます。

def repeat(n)
n.times { yield } if block_given?
end
repeat(2) { puts "Hello." }
# Hello.
# Hello.

メソッドに渡したブロックはyieldを用いて呼び出します。 似たような例としてもう一つ。

# nからmまでの自然数の合計を求める
def sumup(n, m, sum=0)
(n..m).each { |x|
# yield でブロックを呼び出す
yield if block_given? # 引数にブロックが与えられている
puts x
sum += x
}
puts "Sum : #{sum}"
end
sumup(2, 4) { printf "Add : " }
#Add : 2
#Add : 3
#Add : 4
#Sum : 9

渡されたブロックはProcオブジェクトに変換されるのでcallを用いて呼び出すことも出来ます。下の例で確認してみます。

# nからmまでの自然数の合計を求める
def sumup(n, m, &block)
sum = 0
(n..m).each { |x|
block.call if block # ブロックを呼び出し
puts x
sum += x
}
puts "Sum : #{sum}"
end
sumup(0, 4) { printf "Add : " }
#Add : 0
#Add : 1
#Add : 2
#Add : 3
#Add : 4
#Sum : 10

最後に、渡されたブロックをまた引数として渡す場合の例を示します。 その際、ブロック変数名の前に「&」をつけます。

# 配列内の最小値を求める
def minimum(arr, &block)
block ? arr.select(&block).min : arr.min
end
arr = [20,48,15,67]
p minimum(arr) {|i| i > 30}
#=> 48

Cygwinでcronをインストール

· 約1分
Yu Sasaki
Enterprise Security Manager / Advisor

Linux系OSに入っているタスクを自動実行するためのデーモンプロセス、cronをWindows環境でも使用するため,Cygwin((UNIXのフリーソフトウェア等をWindowsに移植したもの))を用いてcronをインストール。 まず、Cygwin Information and InstallationからCygwinをダウンロードしセットアップを開始。セットアップを進めていくと下の画面でインストールするパッケージを選択できます。ここでAdmin内のcronとcygrunsrvをInstallすればOK。 Cygwinのインストール画面:パッケージ選択 インストール後、サービスの設定には主に以下のサイトを参考にしました。

シェルスクリプトでプロセスを監視し自動実行&自動kill

· 約5分
Yu Sasaki
Enterprise Security Manager / Advisor

追記プロセスの監視&自動復旧(簡易版)

今ある検索エンジンのデバッグを行っていますが、事情により短期間ですがクローズドな環境で運用されることになりました。構成は大きく分けてエンジンモジュールサーバ、クエリーモジュールサーバの二つのサーバからなっています。

デバッグはまだ途中なので、運用中にクエリーサーバorエンジンサーバのどちらか、もしくは両方が落ちる可能性もあります。落ちた場合は、手動で起動しなおすことになっていますが、せっかくなので自動化しよう。と、考えました。最初はcronデーモンを用いようと思いましたが、プロセスの監視(dead or alive)の仕方が分からず(調べきれず)、シェルスクリプトを用いることにしました(とは言うもののシェルスクリプトを使うのも初めてでした)。

クエリーサーバ&エンジンサーバのプロセスを一定の間隔で監視し、一方が何らかの原因で落ちた際は、再び二つのプロセスを再実行するようなスクリプトの作成を試みました。ここで、以下の要因を考慮に入れる必要がありました。

  • エンジンorクエリーのどちらかが落ちたら、両システムも再起動する
  • 起動順序はエンジン→クエリー
  • エンジンの起動中にクエリーが起動するとエラー
  • 同じターミナルではエンジン(サーバ)とサーバがうまく動作しない(もともと別々のマシンで動作させるものでもある)→別の端末でそれぞれ実行する(やっかい)

そこで、即席ではありますが、以下の二つのシェルスクリプトを作成しました。

検索エンジンモジュール用監視スクリプト(Echeckp.sh)

#!/usr/bin/sh
inter=3 # プロセスの監視間隔
wait=5 # serverの起動待ち時間
while true
do
isAliveSev=`ps -ef | grep "/server" |
grep -v grep | wc -l`
if [ $isAliveSev = 1 ]; then # serverが動いているか
echo "o:serverプロセス"
else
echo "x:serverプロセス"
pidEng=(`ps -ef | grep "/engine" |
grep -v grep | awk '{ print $2; }'`)
kill $pidEng
/ret/eng/engine &
flag=true
while $flag
do
echo "serverの起動待ち"
reAliveSev=`ps -ef | grep "/server" |
grep -v grep | wc -l`
if [ $reAliveSev = 1 ]; then
flag=false
fi
sleep $wait
reAliveEng=`ps -ef | grep "/engine" |
grep -v grep | wc -l`
if [ $reAliveEng = 0 ]; then # 両方止まったとき
/ret/eng/engine &
fi
done
fi
isAliveEng=`ps -ef | grep "/engine" |
grep -v grep | wc -l`
if [ $isAliveEng = 1 ]; then # engineが動いているか
echo "o:engineプロセス"
else
echo "x:engineプロセス"
pidSev=(`ps -ef | grep "/server" |
grep -v grep | awk '{ print $2; }'`)
kill $pidSev
/ret/eng/engine &
flag=true
while $flag
do
echo "serverの起動待ち"
reAliveSev=`ps -ef | grep "/server" |
grep -v grep | wc -l`
if [ $reAliveSev = 1 ]; then
flag=false
fi
sleep $wait
reAliveEng=`ps -ef | grep "/engine" |
grep -v grep | wc -l`
if [ $reAliveEng = 0 ]; then # 両方止まったとき
/ret/eng/engine &
fi
done
fi
sleep $inter # モニター間隔(秒単位)
done

続いて、

検索クエリーサーバモジュール用監視スクリプト(Scheckp.sh)

#!/usr/bin/sh
inter=3 # プロセスの監視間隔
wait=3 # engineの起動待ち時間
while true
do
isAliveEng=`ps -ef | grep "/engine" |
grep -v grep | wc -l`
if [ $isAliveEng = 1 ]; then
echo "o:engineプロセス"
else
echo "x:engineプロセス"
pidSev=(`ps -ef | grep "/server" |
grep -v grep | awk '{ print $2; }'`)
kill $pidSev
flag=true
while $flag
do
echo "engineの起動待ち"
reAliveEng=`ps -ef | grep "/engine" |
grep -v grep | wc -l`
if [ $reAliveEng = 1 ]; then
flag=false
fi
sleep $wait
done
/ret/sev/server &
fi
isAliveSev=`ps -ef | grep "/server" |
grep -v grep | wc -l`
if [ $isAliveSev = 1 ]; then
echo "o:serverプロセス"
else
echo "x:serverプロセス"
pidEng=(`ps -ef | grep "/engine" |
grep -v grep | awk '{ print $2; }'`)
kill $pidEng
flag=true
while $flag
do
echo "engineの起動待ち"
reAliveEng=`ps -ef | grep "/engine" |
grep -v grep | wc -l`
if [ $reAliveEng = 1 ]; then
flag=false
fi
sleep $wait
done
/ret/sev/server &
fi
sleep $inter # モニター間隔(秒単位)
done

と記述し、それぞれ別の端末でshコマンドで実行します。その際chmodで実行権限を与えておくことを忘れないようにします。また、待ち時間は状況に合わせて変更します(初期設定は3秒おきにチェック)。
一応、これで期待した自動復旧の動作はしましたが、冗長なコードの気がしますし、今回の問題解決にはもっと上手い手段があると思いました。

まぁ、それはそれ。
本分のデバッグ作業に戻りますか。
にしても、シェルスクリプトも興味深いです。

Ruby: lambdaメソッドを使いブロックをオブジェクト化

· 約3分
Yu Sasaki
Enterprise Security Manager / Advisor

に関して、練習します。 他の言語と比較してRubyのコードブロックの扱いは特徴的で扱い難そうに見えますが、使いこなせればコード量を減らせるし、その結果として可読性も増すので、慣れていきたいです。

def times_n(n)
lambda { |x| x * n} # Kernel#lambdaの引数はブロック
# lambda do |x| x * n end でもよい(複数行に渉るときなど)。
end
times_ten = times_n(10) # nに10を代入
# 生成されたtimes_tenはProcインスタンス
p times_ten.class #=> Proc
# times_ten = { |x| x * n} はエラー。
# {}でのブロックはメソッドの引数としてのみ渡せる。
# また、ブロック引数はメソッドの最後の引数として定義する。
# ブロックの実行にはcallメソッドを用いる
p times_ten.call(5) # ブロック変数xに10が代入される
#=> 50

ここで、クラスProcとは

JavaのソースコードからUMLのクラス図を作成

· 約2分
Yu Sasaki
Enterprise Security Manager / Advisor

オセロプログラムの実行画面 統合開発環境のEclipseでJavaのオセロプログラム(講義の課題)を制作中に一度クラス図を作成しようと試みました。使用プラグインはAmaterasUMLでこちらのサイト(軽量なUMLプラグインAmaterasUML (1/4) - @IT)を参考にしながらインストールを進めました。 さて、数あるUMLデザイナの中でこのプラグインのアドバンテージの一つはJavaクラスの継承関係などを包含したクラス図をソースコードから生成できる点にあると私は考えます。 その作り方は、まず「ファイル」→「新規」→「その他」から「AmaterasUML」→「クラス図」と選択してクラス図ファイルを作成し、そのファイルをダブルクリックしクラス図エディタを起動します。その上にクラスファイルをドラックアンドドロップすれば、そのクラスのクラス図が作成されます。また継承関係などを表したい場合は、その関係のクラスを選択した上でドラッグ&ドロップすればOK。下図にその使用状況を示します。 AmaterasUMLの使用画面 ちなみに、これによって作成された図は画像形式でエクスポートできます。 人にプログラムの構造の説明する際に役立つので重宝しています。

X Window System 上での描画色の変更

· 約3分
Yu Sasaki
Enterprise Security Manager / Advisor

先日X11/Xlib.h、X11/Xutil.hを用いてフラクタルを描画するプログラムを作成していた折、描画する図形を構成する線分の色を変えようと試みた。X Window Systemではあらかじめ定義されている色名があるが、今回は多くの色を扱うためRGB指定での描画色の変更を行う。まず、以下のような整数型のピクセル値を返す関数MyColorを作成する。