system()やexec()はあまり使うなとは言われるけど

Windowsであっても,Linuxであっても文字を操作するプログラムには,文字コード変換が絡んでくる場合が多いです。

Windowsの場合は,以前のプログラムの文字コードがShift-JISのままになっており,最近ではUTF-8に変換する必要があります。

Fedoraにおいては,創生初期からUTF8を採用しており,特に問題にはならない場合が多いのですが,昔の資産であるbashコード等のプログラムを利用するため,system()やexec()を利用したときに変な現象に遭遇しました。

その現象とは,例えば以下のようなソースを,コマンドラインで直接実行した場合と,Web経由でPerl(CGI)とsystem()を利用してbashとして実行したときに全く別の結果が出ました。

#!/bin/bash
test=’長野県長野市’
echo ${test:0:3}

bashやperl: 長野県
Apache経由CGI: 長

説明すると,通常は前から3文字目まで文字の切り出しをして表示するので,「長野県」と出力されるのが正しいところ,Web経由で「長」と出力するのみで文字化けのような状況になりました。

よく考えるとCGIの場合,漢字1文字で3バイトであるため,3バイト分しか表示していないことがわかります。

試しに以下の実行命令をしのばせておくと

locale

出力にOSからのコマンドラインやPerlからexec()やsystem()で実行した場合には,”ja_JP.UTF-8″と表示するにも関わらず,CGIから実行した場合には,”POSIX”を表示してしまいました。このままでは,コマンドラインとWeb環境では日本語処理が同じようにできない状態です。解決方法としては上記ソースの2行目に

export LANG=ja_JP.UTF-8

を挿入すれば,Apacheでも正常に文字の切り出しができることがわかりました。

本来はどうすればいいか調べると,どのサーバー環境の文字環境でも対応できるよう,POSIXに統一してソースを書いたほうがベストらしいので,

#!/bin/bash
export LANG=POSIX
test=’長野県長野市’
echo ${test:0:9}

とするほうが正しいのかも知れません。しかし,プログラムが長い場合,大量の文字数の書き換え等が必要となってしまいます。古い資産を使うという点では,system()やexec()の用いたときには,ソースを書き換えずには利用したいので,対処方法としては「export LANG=ja_JP.UTF-8」の1行を挿入するほうを選択しました。

UNIXやLinuxはすでに歴史が長くなってきているので,昔の人が作ったプログラムをそのまま実行したいというニーズも多いかと思いますので,参考にしてください。