CODE-檢查伺服器時間同步
2 |
最近因為伺服器時間不同步,造成資料庫記錄時間基準不一,形成困擾。
理論上同一Domain下的主機都應會自動同步時間,但實務上偶爾就是會有出鎚的狀況。為了能快速掌握時間誤,我寫了以下的工具,可自動比對多台主機時間,將之整理成一張網頁報告,以便能快速找出伺服器時間不同步的問題。最終產出如下:
程式的運作原理是以多執行緒方式透過NetRemoteTOD API同時向多台主機取得時間。誤差判定是以計算"收到結果時間"與"結果內容時間"間差異求得(這不算精準的衡量做法,但基於取得成本低,且具有一定程度參考價值,就姑且用之),最後將結果輸出成HTML。程式碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Configuration;
using System.IO;
using System.Runtime.InteropServices;
namespace TimeSyncReport
{
class Program
{
//時間資訊
class TimeData
{
public DateTime MachineTime;
public string TimeZone;
public TimeSpan Difference = TimeSpan.Zero;
}
static Dictionary<string, TimeData> results
= new Dictionary<string, TimeData>();
static void Main(string[] args)
{
string[] ips =
ConfigurationSettings.AppSettings["ServerList"].Split(';');
//取得伺服器清單,同時開多條執行緒執行,讀取遠端機器時間
Thread[] workers = new Thread[ips.Length];
for (int i = 0; i < ips.Length; i++)
{
string ip = ips[i];
workers[i] = new Thread(() =>
{
GetRemoteTime(ip);
});
workers[i].Start();
}
//等待所有執行緒執行完成
for (int i = 0; i < workers.Length; i++)
workers[i].Join();
//將結果輸出成HTML
StringBuilder sb = new StringBuilder();
sb.Append(@"
<html>
<head>
<link rel='stylesheet' href='style.css' type='text/css' />
</head>
<body>
<table id='tblResult'>
<tr class='hdr'>
<td>IP</td><td>Time</td><td>TimeZone</td><td>Difference</td>
</tr>
");
foreach (string ip in results.Keys.OrderBy(s => s))
{
TimeData td = results[ip];
sb.AppendFormat("<tr><td>{0}</td>", ip);
//Error!
if (td.MachineTime == DateTime.MinValue)
sb.AppendFormat("<td colspan='3' class='err'>{0}</td>",
td.TimeZone.Replace("\r", "").Replace("\n", "<br />"));
else
{
double diff = td.Difference.TotalSeconds;
sb.AppendFormat(
"<td>{0:HH:mm:ss.fff}</td><td>{1}</td><td class='{3}'>{2}</td>",
td.MachineTime, td.TimeZone, diff,
Math.Abs(diff) > 1 ? "red" : "green");
}
sb.Append("</tr>");
}
sb.Append("</table></body></html>");
File.WriteAllText(ConfigurationSettings.AppSettings["HtmlPath"],
sb.ToString());
}
//REF:http://www.pinvoke.net/default.aspx/netapi32/NetRemoteTOD.html
#region API
[DllImport("netapi32.dll", EntryPoint = "NetRemoteTOD",
SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
private static extern int NetRemoteTOD(string UncServerName,
ref IntPtr BufferPtr);
[DllImport("netapi32.dll")]
private static extern void NetApiBufferFree(IntPtr bufptr);
[StructLayout(LayoutKind.Sequential)]
public struct structTIME_OF_DAY_INFO
{
public int itod_elapsedt;
public int itod_msecs;
public int itod_hours;
public int itod_mins;
public int itod_secs;
public int itod_hunds;
public int itod_timezone;
public int itod_tinterval;
public int itod_day;
public int itod_month;
public int itod_year;
public int itod_weekday;
}
#endregion
public static void GetRemoteTime(string ip)
{
try
{
structTIME_OF_DAY_INFO result = new structTIME_OF_DAY_INFO();
IntPtr pintBuffer = IntPtr.Zero;
// Get the time of day.
int pintError = NetRemoteTOD(ip, ref pintBuffer);
if (pintError > 0)
throw new System.ComponentModel.Win32Exception(pintError);
// Get the structure.
result = (structTIME_OF_DAY_INFO)
Marshal.PtrToStructure(pintBuffer,
typeof(structTIME_OF_DAY_INFO));
// Free the buffer.
NetApiBufferFree(pintBuffer);
//REF: TIME_OF_DAY_INFO
//http://msdn.microsoft.com/en-us/library/aa370959%28VS.85%29.aspx
//由結果轉成DateTime物件
DateTime dt = new DateTime(
result.itod_year, result.itod_month, result.itod_day,
result.itod_hours, result.itod_mins, result.itod_secs,
result.itod_hunds * 10 // 0.01秒換成0.001秒(ms)
);
lock (results)
{
//以收到時間值與資料內容的時間差當成誤差
results.Add(ip, new TimeData
{
MachineTime = dt,
Difference = dt - DateTime.Now.ToUniversalTime(),
TimeZone = result.itod_timezone.ToString()
});
}
}
catch (Exception ex)
{
lock (results)
{
//如有錯誤,將錯誤訊息寫入TimeZone
results.Add(ip, new TimeData
{
MachineTime = DateTime.MinValue,
TimeZone = ex.Message
});
}
}
}
}
}
Comments
# by jeff
若伺服器是使用 Windows OS,它本身就有同步時間的功能,參考下面網址。 http://ezpost.blogspot.com/2007/09/blog-post.html 另一種方式是使用 NTPClock 定時做網路校時。 http://www.stdtime.gov.tw/chinese/home.htm
# by 賣黑輪
請問我的主機是在國外它的主機時間會常常換來換去 每次我都要手動檢查然後在去改程式=.=" 我有辦法直接抓台灣的主機時間嗎 或是有這方面提供時間的網站嗎?還是有其他方式可以解決 謝謝~