リモートのWindowsサーバ上のバッチ(.batファイル)を起動する要件があり、方法を検討していたのですが、いろんな方法がありますね。
今回検討した方法に対しては、もうひとつ要件があり、バッチの実行結果(リターンコード)を取得でき、その結果によって呼び出しプログラム側で制御をおこなわなければいけません。
いくつか考えた方法を挙げると、、、
- sshdのサーバを立てて、cmd.exeをシェル実行する。
- SFU後継のSUA(Subsystem for UNIX-Based Application)をインストールして、rshで実行する。
- IISなどのWebサーバを立てておき、Webアプリとして実行する。
- JavaのRMIサーバを立てて、RMIクライアントプログラムから実行する。
といったところです。
この中で今回は、3番目のWebアプリとして実行する方法をメモしておこうと思います。
実際のコードを書く前に、この方法でいくつか考慮しておいた方が良いと思うことを挙げます。
・aspx経由で実行させようとしているので、実行権限はIISのユーザになる。バッチが起動できる権限かを確認しておく
・バッチの実行時間が短い場合はあまり問題にならないかもしれませんが、バッチ実行中はIISの実行スレッドを占有します。そのため、IISでWebページを公開していたり、他のWebアプリが動いていたりすると、 スレッドが枯渇した場合は、そちらのリクエストをさばけなくなることが考えられます。
バッチの同時実行数を呼び出しプログラム側で制御するか、IISの設定で、スレッド数を増やす、もしくは別のスレッドプールを割り当てるなどの対策を行った方が良いでしょう。
では、aspxのプログラムを、、
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Diagnostics" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.IO" %>
<%@ Page Language="C#" AutoEventWireup="true" Inherits="System.Web.UI.Page" %>
<script runat="server">
//正常終了のリターンコード
public static readonly int BATCH_RTN_CODE_NORMAL = 0;
//異常終了のリターンコード
public static readonly int BATCH_RTN_CODE_ERROR = -1;
//AWSバッチの配置ディレクトリ
public static readonly string BATCH_INPUT_DIR = @"C:";
//バッチファイルを取得するクエリパラメータ名
public static readonly string PARAM_BAT_FILENAME = "sbatchnm";
protected void Page_Load(object sender, EventArgs e)
{
int intRtnCode = BATCH_RTN_CODE_ERROR;
string strBatchFile = this.Request.QueryString[PARAM_BAT_FILENAME];
if (string.IsNullOrEmpty(strBatchFile))
{
// 値がなかった場合はエラーとして返す。
this.Response.Write(BATCH_RTN_CODE_ERROR);
}
else
{
string strBatDir = BATCH_INPUT_DIR;
string strFilePath = strBatDir + strBatchFile;
System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo();
psi.FileName = strFilePath;
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.RedirectStandardInput = true;
psi.UseShellExecute = false;
// Start the process
System.Diagnostics.Process proc = Process.Start(psi);
string results = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
intRtnCode = proc.ExitCode;
this.Response.Write(intRtnCode);
}
}
</script>
このaspxファイルを「BatchExec.aspx」の名前でIISに配置した場合は、
http://サーバ名/BatchExec.aspx?sbatchnm=バッチファイル名
のようなURLを実行すると、バッチが実行され、結果が返ってきます。