我們的產品中間件的啟動是由批處理文件開始,這就導致,始終有個DOS窗口,來顯示服務器的運行情況??煽蛻舨粯芬獍。核麄兙拖肴f一誰不小心把那窗口給關了,損害了數據,那問題可就大了!這個問題確實是挺有價值的。
首先,我們考慮WINDOWS環境吧,我不認為WINDOWS環境下和*NIX環境下的實現有很大差別。想到以前看到的,聽到的,再加上自己的經驗,大概有這么集中方式:
包裝bat文件為exe文件,然后以后臺服務的形式注冊
利用windows自帶的Wscript.Shell
寫個Swing界面小程序,利用多線程,啟動應用服務,把DOS窗口替換成應用窗口。
但我們需要考慮另外一點:我們的應用在運行的時候,會向dos窗口輸出一些出來的一些信息,這些信息在很多情況下都是很有用的?,F在如果把DOS窗口隱藏了,那么那些信息我把他們存放到哪兒呢?我想最好還是以文件的形式保存起來,將來如有問題還可以追查!
現在考慮各種實現方式。包裝為exe的形式,也只能在windows環境下運行,并且需要額外的工具;Swing界面小程序這個其實是最可行的,但我這個人比較懶,比較討厭寫界面;利用windows自帶的Wscript.Shell,自然也只能依賴于windows環境,后來我想了下,其實這個方案可以和swing界面那個方案有不少東西是可以公用的。最后決定,為了簡單期間,偶就先用Wscript.Shell,來做測試了。
實際的情況大致是:
應用服務的啟動腳本是/startup.bat 實際中我們可以使用vbs腳本:
dim ws
Set ws = CreateObject("Wscript.Shell")
ws.run "cmd /c /startup.bat >> myServer.log" ,vbhide
通過這樣簡單的設置,我們可以做到隱藏DOS窗口,但是,如果我們的應用一下子運行好幾個月,那我們的日志文件myServer.log的日積月累地,就太大了。我們在查找問題的時候,也很不容易!所以我們應該想法子把日志文件myServer.log,按時間或者按大小分開存儲。這也是我們應用服務器日志的做法。所以,我們需要再做一步中間處理,想想看"appRoot/startup.bat"這一步,我們在程序當中還是可以獲得它的輸出結果的??聪旅鎗ava程序:
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()));
// 服務器日志目錄
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
{
// 如果已經存在日志文件,則先把原來的文件歸檔,然后新創建一個日志文件
StringBuffer oldFileName = new StringBuffer();
oldFileName.append(serverLogDirName);
oldFileName.append("/");
oldFileName.append(logFileNamePrefix).append("[").append(maxFileIndex).append("].log");
logFile.renameTo(new File(oldFileName.toString()));
maxFileIndex++;
//創建新的日志文件
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();
// 超過日志文件規定的大小了,則把日志文件歸檔,然后新創建一個日志文件
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++;
// 創建新的日志文件
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;
// 一個簡單的文件名過濾類
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;
}
}
之后,為了運行方便,我們把這兩個類編譯后打成可執行的jar包,例如ncstartuputil.jar。并修改vbs腳本為:
dim ws
Set ws = CreateObject("Wscript.Shell")
ws.run "cmd /c java -jar ncstartuputil.jar E:/nchome_zhengshi" ,vbhide
如果換做swing界面,其實僅僅需要寫另外一個Thread,thread的主體也正式上面static main方法主體,然后通過多線程,可以獲得原始start.bat批處理文件的輸出,并且把輸出的信息放到一個textarea里面顯示出來。:-)....