powershell&start-processでバッググランド実行&ファイル更新監視
ある案件で問題が発生し、powershellスクリプト作成しましたが、度々思うようにいかない処理があったので、ご紹介します。
ある自動化ソフトより、powershellスクリプトを呼び、設定処理を行う仕様にしていましたが、順番を誤り、仮想マシンが起動前に実行していたため、設定がされていないという不具合が発覚しました。自動化ソフト側の修正は影響が大きく、すぐには修正できないため、powershellスクリプトを修正し、対応を検討しました。
対策実施1 sleep処理追加
powershellスクリプト側に一定時間のsleep処理を入れて、仮想マシンが起動するのを待って、設定スクリプトを実行するように変更しました。しかし、上手くいかず、切り分けると、自動化ソフト側で、設定スクリプトの処理完了を待って、次の処理に移るため、仮想マシンが先に起動することはない。非同期処理だと聞いていましたが、間違った情報でした。。
対策実施2 start-process追加
処理完了を待つという仕様のため、子プロセスを作り、start-processによりバックグラウンド実行を追加してみました。powershellの単体では思ったとおり動作し、解決かと思いきや、自動化ソフト組み合わせテストを実施すると上手くいかない。32bit/64bitアプリ問題やstart-processのオプションを変更してみたが、上手くいかず、子プロセスが実行されない。。その後、切り分けを行うと、親プロセスにsleep処理を入れると、子プロセスが実行された!要は呼び出せてなかったわけではなく、実行開始するも、すぐに親プロセスが完了するため、子プロセスが呼び出せていないように見えただけでした。単体では問題ないものの、自動化ソフト側も組み合わせると、今のアプローチではどうにもできないことを悟りました。この時点でぐったりです。
対策実施3 ファイル更新スクリプト追加
再設定用のスクリプトであり、何度も実行することは問題ないため、実行化ソフトから呼ばれて実行されたpowershellスクリプトのログファイルを監視し、ログが更新されたら、スクリプトを実行する仕様に変更しました。同じスクリプトを実行すると、ループ実行してしまうため、同じ処理内容の別スクリプトを用意し、再度実行する仕様に変更しました。
Register-ObjectEventを利用することで、ファイルの作成(created)、更新(changed)、削除(deleted)、ファイル名変更(rename)を監視できます。-Actionにて、ファイルが更新された場合に実施する処理を、記載できます。一部注意点は-Actionの外で定義していた変数などは一部使えませんので、ご注意ください。
自動化ソフトとも連携テストも上手くいって解決!と思いきや、一点指摘がきました。常駐プロセス化すると、メモリリークが起きて、サーバ側に負荷がかかる可能性があるとのこと。たしかにそうかもしれない。
対策実施4 定期的なログ監視スクリプト実装
常駐プロセスはNGということで、タスクスケジューラで5分おきに、powershellスクリプトを実行する仕様に変更しました。ファイルの更新日付を取得し、現在時刻との比較を行い、5分以内に更新されていれば、再度実行する仕様としました。powershellの日時比較はとても簡単です。
$current_date= Gate-date
$lasttime =$(Get-ItemProperty ファイル名).LastWriteTime
($current_date – $lasttime).totalminute
5分おきに実行するのですが、デフォルト設定では、前回のpowershellスクリプトが完了していないと、次のタスクが実行されないため、新しいインスタンスを並列で実行という処理を加えます。対策実施4を実装して、ようやく対応完了です。
疲れましたが、powershellスクリプトに関する理解は深まったと思います。