比較的最近の話です。2日だけ緊急で携わったもので、ありがちだけど自分の中ではこんなことあるんだなというようなバグを紹介します。
今回はPowershellでの不具合でしたが、多くのプログラミング言語で起きる可能性があると思います。
プログラムの機能は、SFTPと共有ディレクトリへのファイル送信で、今回不具合がありそうなのは後者の共有ディレクトリへのファイル送信ということでした。ある文字を含んだファイルを送ろうとするとエラーとなってしまうという内容でした。プログラムを作成した担当者が隣にいたのですが時間が取れないということで私がやることになりました。
話を聞いてみると、特定の文字を含んだファイルを送信しようとするとエラーになってしまうとの事でした。具体的に聞くと"$"を含んだファイル名ということで、文字のエスケープ関係ということは明白でした。
ということでエラー確認後、Powershellでエスケープとして使われる文字の洗い出しを行いました。
特殊文字一覧
$ | シェル変数参照 |
---|---|
, | カンマ(配列で使う) |
& | スクリプト実行 |
` | バッククォート |
" | シェル展開を行った後の文字列を表現 |
‘ | シェル展開行わない文字列を表現 |
`0 | ヌル |
`a | 警告 |
`b | バックスペース |
`f | 書式送り |
`n | 改行 |
`r | キャリッジリターン |
`t | タブ |
`v | 垂直タブ |
ということで、これらの文字をファイルやフォルダ名に含めてエラーにならなければ良いという形で進めることに。
こんな感じのソースになっていました。
# コマンドファイル作成処理
"Copy-Item" + """" + $SEND_DIR + """ """ + $RCV_DIR + """ -ErrorAction:Stop" | Out-File $CMD_FILE -encoding Default -append
# 色々処理
# コマンド実行
Get-Content $FILE | % {Invoke-Expression $_}
コマンドファイルを作ってInvokeコマンドで実行する処理自体は変更しないでどうにかしようということで・・。
シェル展開されないシングルクォートに変更しました
# シングルクォートに変更
"Copy-Item" + "’" + $SEND_DIR + "’ ‘" + $RCV_DIR + "’ -ErrorAction:Stop" | Out-File $CMD_FILE -encoding Default -append
# 色々処理
# コマンド実行
Get-Content $FILE | % {Invoke-Expression $_}
これでいけるかなと思いテスト用ファイルを作成
"$STR$ING$"というような名前のディレクトリとファイルを系24ファイル作成し実行
うまく行ってると思いきや’STR’ING’という名前のファイルがエラーになりました。
シングルクォートはしょうがないということで(良い感じの方法他にあるのかな・・)
#シングルクォートをエスケープ
$SEND_DIR = $SEND_DIR.Replace("’", "”")
という感じの処理を泣く泣く特別に作りうまく行きました。
今回はバグの内容自体は当初簡単かなと思っていたのですが(シングルクォート使えばいいんじゃないの・・みたいな感じでした)、思った以上に時間取られた印象がある内容でした。依頼内容としては$を含むファイル名ということだったため担当者がやったほうが早いのではないかと思いましたが、横展開すると結構考えることありますからね・・。特にシェル系のプログラムを組む際はダブルクォートとシングルクォート使い分けて行きたいですね。(余談・・自分はそんなにこだわらないですが)