我們的產(chǎn)品中間件的啟動(dòng)是由批處理文件開始,這就導(dǎo)致,始終有個(gè)DOS窗口,來顯示服務(wù)器的運(yùn)行情況。可客戶不樂意啊:他們就想萬一誰不小心把那窗口給關(guān)了,損害了數(shù)據(jù),那問題可就大了!這個(gè)問題確實(shí)是挺有價(jià)值的。
首先,我們考慮WINDOWS環(huán)境吧,我不認(rèn)為WINDOWS環(huán)境下和*NIX環(huán)境下的實(shí)現(xiàn)有很大差別。想到以前看到的,聽到的,再加上自己的經(jīng)驗(yàn),大概有這么集中方式:
包裝bat文件為exe文件,然后以后臺(tái)服務(wù)的形式注冊
利用windows自帶的Wscript.Shell
寫個(gè)Swing界面小程序,利用多線程,啟動(dòng)應(yīng)用服務(wù),把DOS窗口替換成應(yīng)用窗口。
但我們需要考慮另外一點(diǎn):我們的應(yīng)用在運(yùn)行的時(shí)候,會(huì)向dos窗口輸出一些出來的一些信息,這些信息在很多情況下都是很有用的。現(xiàn)在如果把DOS窗口隱藏了,那么那些信息我把他們存放到哪兒呢?我想最好還是以文件的形式保存起來,將來如有問題還可以追查!
現(xiàn)在考慮各種實(shí)現(xiàn)方式。包裝為exe的形式,也只能在windows環(huán)境下運(yùn)行,并且需要額外的工具;Swing界面小程序這個(gè)其實(shí)是最可行的,但我這個(gè)人比較懶,比較討厭寫界面;利用windows自帶的Wscript.Shell,自然也只能依賴于windows環(huán)境,后來我想了下,其實(shí)這個(gè)方案可以和swing界面那個(gè)方案有不少東西是可以公用的。最后決定,為了簡單期間,偶就先用Wscript.Shell,來做測試了。
實(shí)際的情況大致是:
應(yīng)用服務(wù)的啟動(dòng)腳本是/startup.bat 實(shí)際中我們可以使用vbs腳本:
dim ws
Set ws = CreateObject("Wscript.Shell")
ws.run "cmd /c /startup.bat >> myServer.log" ,vbhide
Set ws = CreateObject("Wscript.Shell")
ws.run "cmd /c /startup.bat >> myServer.log" ,vbhide
通過這樣簡單的設(shè)置,我們可以做到隱藏DOS窗口,但是,如果我們的應(yīng)用一下子運(yùn)行好幾個(gè)月,那我們的日志文件myServer.log的日積月累地,就太大了。我們在查找問題的時(shí)候,也很不容易!所以我們應(yīng)該想法子把日志文件myServer.log,按時(shí)間或者按大小分開存儲(chǔ)。這也是我們應(yīng)用服務(wù)器日志的做法。所以,我們需要再做一步中間處理,想想看"appRoot/startup.bat"這一步,我們在程序當(dāng)中還是可以獲得它的輸出結(jié)果的。看下面java程序:
package nc.client.StartupUtil;
import java.lang.ProcessBuilder;
import java.util.Vector ;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.util.Collections ;
public class NC50StartUtil
{
public static final String logFileNamePrefix = "ncconsolelogs";
public static void main(String[] args)
{
ProcessBuilder processBuilder = new ProcessBuilder("cmd", "/C", args[0]+"/startup.bat");
processBuilder.directory(new File(args[0]));
Process process = null;
try
{
process = processBuilder.start();
BufferedReader datais =
new BufferedReader(
new InputStreamReader( process.getInputStream()));
// 服務(wù)器日志目錄
String serverLogDirName = args[0] + "/nclogs/server";
File serverLogDir = new File (serverLogDirName);
if (!serverLogDir.exists())
{
serverLogDir.mkdirs();
}
int maxFileIndex = getMaxFileIndex(serverLogDirName).intValue();
File logFile = new File(serverLogDirName+"/ncconsolelogs.log");
if (!logFile.exists())
{
logFile.createNewFile();
}
else
{
// 如果已經(jīng)存在日志文件,則先把原來的文件歸檔,然后新創(chuàng)建一個(gè)日志文件
StringBuffer oldFileName = new StringBuffer();
oldFileName.append(serverLogDirName);
oldFileName.append("/");
oldFileName.append(logFileNamePrefix).append("[").append(maxFileIndex).append("].log");
logFile.renameTo(new File(oldFileName.toString()));
maxFileIndex++;
//創(chuàng)建新的日志文件
if (!logFile.exists())
{
logFile.createNewFile();
}
}
BufferedWriter writer = new BufferedWriter(new FileWriter(logFile));
// 文件的最大大小是2M
int maxlength = 1024*1024*2;
String c;
while ((c = datais.readLine()) != null)
{
writer.write(c);
writer.newLine();
writer.flush();
// 超過日志文件規(guī)定的大小了,則把日志文件歸檔,然后新創(chuàng)建一個(gè)日志文件
if (logFile.length() > maxlength)
{
writer.close();
StringBuffer oldFileName = new StringBuffer();
oldFileName.append(serverLogDirName);
oldFileName.append("/");
oldFileName.append(logFileNamePrefix).append("[").append(maxFileIndex).append("].log");
logFile.renameTo(new File(oldFileName.toString()));
maxFileIndex++;
// 創(chuàng)建新的日志文件
if (!logFile.exists())
{
logFile.createNewFile();
}
writer = new BufferedWriter(new FileWriter(logFile));
}
}
}
catch(IOException e)
{
e.printStackTrace ();
}
}
public static Integer getMaxFileIndex(String ncconsolelogdirname)
{
File ncconsolelogdir = new File(ncconsolelogdirname);
File[] ncconsolelogs = ncconsolelogdir.listFiles(new NcLogFileNameFilter(logFileNamePrefix));
if (ncconsolelogs != null && ncconsolelogs.length > 0)
{
Vector v = new Vector();
for (int i=0, len=ncconsolelogs.length; i startIndex)
{
String index = logFileName.substring (startIndex+1, endIndex);
int ind = -1;
try
{
ind = Integer.parseInt(index);
}
catch(Exception e)
{
}
if (ind > 0)
{
v.add(ind);
}
}
}
if (v.size() > 0)
{
return Collections.max(v) + 1;
}
else
{
return 1;
}
}
return 1;
}
}
package nc.client.StartupUtil;
import java.io.File;
import java.io.FilenameFilter;
// 一個(gè)簡單的文件名過濾類
public class NcLogFileNameFilter implements FilenameFilter {
private String fileNamePrefix = null;
public NcLogFileNameFilter(String fileNamePrefix)
{
this.fileNamePrefix = fileNamePrefix;
}
public boolean accept(File dir, String name)
{
if (name.toLowerCase().startsWith(fileNamePrefix))
{
return true;
}
return false;
}
}
之后,為了運(yùn)行方便,我們把這兩個(gè)類編譯后打成可執(zhí)行的jar包,例如ncstartuputil.jar。并修改vbs腳本為:
dim ws
Set ws = CreateObject("Wscript.Shell")
ws.run "cmd /c java -jar ncstartuputil.jar E:/nchome_zhengshi" ,vbhide
Set ws = CreateObject("Wscript.Shell")
ws.run "cmd /c java -jar ncstartuputil.jar E:/nchome_zhengshi" ,vbhide
如果換做swing界面,其實(shí)僅僅需要寫另外一個(gè)Thread,thread的主體也正式上面static main方法主體,然后通過多線程,可以獲得原始start.bat批處理文件的輸出,并且把輸出的信息放到一個(gè)textarea里面顯示出來。:-)....