Windows2003 监控文件系统并自动上传到 linux 主机

一直用 FTP 直接登录 UFAX2 网络传真机来获取最新传真,但自从换了新版本的设备后,发现 FTP 被限制了,似乎加了连接授权,再随机分配 FTP 端口。如此一来,只好使用它的客户端。


因为一直以来,都是用 Ajaxplorer(已经改名为 pydio)来管理传真文件,运行在 Ubuntu 主机上,用脚本来自动下载传真。现在只能开一台 Windows 主机,要实现传真自动上传。


实现的步骤:

1. 启用 Windows2003 文件夹安全选项中的审核,监控下载的传真文件,对文件创建成功进行监控。

2. 本地策略中,开启 Object Access 审核选项,不然前一项不生效。

3. 创建自动上传到 Ubuntu 主机的 javascript 脚本程序。

4. 创建 eventtriggers 条目,指定要自动执行的脚本。


开启审核,网上有较多参考文档,如:

http://blogs.splunk.com/2013/07/08/audit-file-access-and-change-in-windows/

开启后,传真文件一旦产生新文件,在管理工具的事件查看器中,我们就可以看到对应的消息,事件ID是 560 (event codes 560 (open object))


创建 eventtriggers 可以查考:

http://www.petri.co.il/how-to-use-eventtriggersexe-to-send-e-mail-based-on-event-ids.htm

http://www.computerperformance.co.uk/Logon/VBScript/eventtriggers.htm

在这个例子中,有段 vbs 代码,下面的 js 是参照它来写的,对于我个人来说,用 js 写代码要清晰简洁很多,如 String.format, Date.format 这两个函数一加,生成字符串又轻松,可读性又好。


代码中用到的类,对应的参考资料:

Win32_NTLogEvent class

     http://msdn.microsoft.com/en-us/library/aa394226(v=vs.85).aspx

Converting a Standard Date to a WMI Date-Time Format

    http://technet.microsoft.com/en-us/library/ee156558.aspx

其中日期,使用的是 UTC + 时区偏移分钟 的方式来表示,系统当前的时区值,是用 Select * From Win32_TimeZone 来获取的,这样相信各位就能明白函数 getOffsetTime() 具体是什么作用了。


下面是脚本代码,只有几行,很简单。

1. 从系统日志中提取对应的记录

2. 检查事件描述中,是否包含指定文件下的传真 tif 文件

3. 提取 tif 文件名

4. 将 tif 文件上传到服务器

5. 调用服务器上的 shell 脚本对文件作进一步处理(此处未列出,在服务器上,使用 tiff2pdf 工具将 tif 文件转换成 pdf )

6. 删除本地的 tif 文件


注:远程 ssh 操作,使用的是 putty 系统工具,主要是 pscp 上传文件, plink 命令行执行远程 shell 命令。


// use create event trigger command to call this script
// eventtriggers /create /eid 560 /tr EventFaxProc /ru administrator /rp password /tk "c:\uploadFax.js"

var INTERVAL = -1;
var SSH_EXE_PATH = "C:\\Program Files\\PuTTY";
var LOCAL_FAX_PATH = "C:\\Documents and Settings\\Administrator\\My Documents\\我的传真\\收到的传真";
var REMOTE_HOST = "[email protected]";
var REMOTE_PSWD = "mypassword";
var REMOTE_UPLOAD_PATH = "/pydio/faxtemp/tiff";
var REMOTE_CMD = "/pydio/faxtemp/faxconvert.sh";
var WMI_HOST = ".";
var DEBUG = false;

String.prototype.format = function()
{
	var args = arguments;
	return this.replace(/\{(\d+)\}/g,
		function(m, i){
			return args[i];
		}
	);
};


Date.prototype.format = function(format) {
       var date = {
              "M+": this.getMonth() + 1,
              "d+": this.getDate(),
              "h+": this.getHours(),
              "m+": this.getMinutes(),
              "s+": this.getSeconds(),
              "q+": Math.floor((this.getMonth() + 3) / 3),
              "S+": this.getMilliseconds()
       };
       if (/(y+)/i.test(format)) {
              format = format.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length));
       }
       for (var k in date) {
              if (new RegExp("(" + k + ")").test(format)) {
                     format = format.replace(RegExp.$1, RegExp.$1.length == 1
                            ? date[k] : ("00" + date[k]).substr(("" + date[k]).length));
              }
       }
       return format;
};

var objWMIService;
var cmdPara = DEBUG ? "/K" : "/C";
var cmdWin = DEBUG ? 4 : 0;
main();


function main()
{
	var pathName = "winmgmts:{impersonationLevel=impersonate}!\\\\{0}\\root\\cimv2".format(WMI_HOST);
	echo(pathName);
	objWMIService = GetObject(pathName);
	var queryString = "Select * from Win32_NTLogEvent"
		+ " Where TimeGenerated>='{0}' and LogFile='Security' and EventIdentifier=560".format(getOffsetTime());
		
	var loggedEvents = objWMIService.ExecQuery(queryString);
	if (loggedEvents.Count == 0)
	{
		echo("events not found.");
		WScript.Quit();
	}
	
	var e = new Enumerator(loggedEvents);
	var pos = 0;
	for(; !e.atEnd(); e.moveNext()) procFax(e.item(), pos++);
	
	echo("Fax upload and convert to pdf completed.");
}

function echo(msg)
{
	if (DEBUG) WScript.echo(msg);
}

function getOffsetTime()
{
	var bias = 0;
	var timeZone = objWMIService.ExecQuery("Select * From Win32_TimeZone");
	var e = new Enumerator(timeZone);
	for(; !e.atEnd(); e.moveNext())
	{
		bias = e.item().Bias;
	}
	
	var currentDate = new Date();
	currentDate.setSeconds(currentDate.getSeconds() + INTERVAL);
	
	return "{0}.000000{1}".format(currentDate.format("yyyyMMddhhmmss"), bias >= 0 ? ("+" + bias) : bias);
}

function procFax(event, pos)
{
	var parttern = "Object Name:\\s+{0}\\\\(.*)".format(LOCAL_FAX_PATH.replace(/\\/g, "\\\\"));
	if (pos == 0) echo(parttern + "\r\n" + event.Message);
	var regExp = new RegExp(parttern, "i");
	var matches = regExp.exec(event.Message);
	if (matches == null) return;
	
	var fileName = matches[1];
	echo("{0}\r\n{1}\r\n{2}".format(matches[0], fileName, event.TimeGenerated));
	
	sshUpload(fileName);
}

function sshUpload(fileName)
{
	var objShell = WScript.CreateObject("WScript.Shell");
	var cmd = "cmd.exe {6} \"\"{0}\\pscp.exe\" -pw {1} \"{2}\\{3}\" {4}:{5}\"".format(
		SSH_EXE_PATH, REMOTE_PSWD, LOCAL_FAX_PATH, fileName, REMOTE_HOST, REMOTE_UPLOAD_PATH, cmdPara);
	
	var returnValue = objShell.Run(cmd, cmdWin, true);
	if (returnValue == 0)
	{
	
	}
	else
	{
		echo("SSH upload failured.\r\n\r\nCommand Line:\r\n{0}\r\n\r\nreturn value:{1}".format(cmd, returnValue));
		if (!DEBUG) return;
	}
	
	fileName = fileName.replace(/\.tif/, "");
	cmd = "cmd.exe {5} \"\"{0}\\plink.exe\" {1} -pw {2} \"echo -e \"{2}\" | sudo -S {3} {4} \"\"".format(
		SSH_EXE_PATH, REMOTE_HOST, REMOTE_PSWD, REMOTE_CMD, fileName, cmdPara);
	var returnValue = objShell.Run(cmd, cmdWin, true);
	if (returnValue == 0)
	{
		objShell.Run("cmd.exe {2} \"Del /Q \"{0}\\{1}.tif\"\"".format(LOCAL_FAX_PATH, fileName, cmdPara), cmdWin, true);
	}
	else
	{
		echo("SSH command failured.\r\n\r\nCommand Line:\r\n{0}\r\n\r\nreturn value:{1}".format(cmd, returnValue));
		return;
	}
}

其它参考资料:

    plink 如何执行 sudo

        http://www.zimbra.com/forums/installation/10553-solved-sudo-sorry-you-must-have-tty-run-sudo.html

你可能感兴趣的:(ssh,文件系统)