using System; using System.Collections.Generic; using System.IO; using System.Linq; using FileTransDataObject; using Sog; namespace SMCenter { public static class CmdUtils { public static bool IsValidServerIDSub(string one) { int result = -1; try { result = Convert.ToInt32(one); if (result >= 0 && result < 256) { return true; } else { return false; } } catch { return false; } } // server id是否合法, 如果不合法但可以fix就修改成正确格式 public static bool CheckValidServerId(string serverid, out string fixSvrId) { fixSvrId = null; string[] split = serverid.Split('.'); if(split == null || split.Length != 3) { return false; } bool error = false; bool fix = false; for (var i = 0; i < split.Length; i++) { var one = split[i]; // *.*.* 或者 255.255.255 if (one != "*" && ! IsValidServerIDSub(one)) { // 支持 *.game.* 写法, 避免记不住AppType if (i == 1) { var appCfg = SMProcAppMgr.Instance.GetAppTypeByName(one, out bool isWorldLayer); if (appCfg != null) { split[1] = appCfg.apptype.ToString(); fix = true; } } else { error = true; break; } } } if (! error && fix) { fixSvrId = string.Join('.', split); TraceLog.Debug("CmdUtils.CheckValidServerId {0} chg to {1}", serverid, fixSvrId); } return error == false; } public static int GetPushCfgFile(CmdInfo cmdInfo, List fileList, bool loadFile) { try { // key = file path & send host, value = 1 Dictionary dict = new Dictionary(); foreach (var proc in cmdInfo.m_procs.Values) { string dir = SMCenterUtils.Config.centerPush + "/publish/cfg/" + proc.SMApp.CfgPath + "/" + proc.SMApp.Name + "/"; foreach (string path in Directory.GetFiles(dir)) { // center上cfg文件路径:cfg/AppCfgPath/AppName/xxxxxx.json // agent上cfg保存路径:WorkPath/cfg/HostCfg/AppName/xxxxx.json string key = Path.GetFullPath(path) + "@" + proc.SMApp.HostName; // 文件重复, 比如起了2个进程, 配置文件相同 if (dict.ContainsKey(key)) { continue; } var file = FileUtils.CreateFileData(path, loadFile); if (file != null) { file.writeFilePath = Path.GetFullPath(Path.Combine(proc.SMApp.WorkPath, proc.SMApp.CfgPath, proc.SMApp.Name)); TraceLog.Debug("CmdUtils.GetPushCfgFile {0} md5 {1}, center path {2}, agent path {3}" , file.fileName, file.fileMd5, file.readFilePath, file.writeFilePath); fileList.Add(file); dict.Add(key, 1); } } } } catch (Exception e) { TraceLog.Exception(e); return -1; } return 0; } public static int GetPushBinFile(CmdInfo cmdInfo, List fileList, bool loadFile) { try { var workPath = cmdInfo.m_procs.Values.First().SMApp.WorkPath; // workpath是同一个 Dictionary dict = new Dictionary(); string dir = SMCenterUtils.Config.centerPush + "/publish/bin/"; foreach (string path in Directory.GetFiles(dir)) { // center上bin文件路径:../centerPush/publish/bin/*.dll *.pdb // agent上cfg保存路径:WorkPath/*.dll *.pdb string name_ex = Path.GetFileName(path); string name = name_ex.Split('.')[0]; CmdProcInfo proc = cmdInfo.m_procs.Values.FirstOrDefault(p => p.SMApp.ScriptName == name); if (proc == null) { continue; } string key = name_ex + "@" + proc.SMApp.HostName; // 文件重复, 比如起了2个进程, bin文件是同一个 if (dict.ContainsKey(key)) { continue; } var file = FileUtils.CreateFileData(path, loadFile); if (file != null) { file.writeFilePath = workPath; TraceLog.Debug("CmdUtils.GetPushBinFile {0} md5 {1}, center path {2}, agent path {3}" , file.fileName, file.fileMd5, file.readFilePath, file.writeFilePath); fileList.Add(file); dict.Add(key, 1); } } } catch (Exception e) { TraceLog.Exception(e); return -1; } return 0; } public static int GetPushShellFile(CmdInfo cmdInfo, List fileList, bool loadFile) { try { var workPath = cmdInfo.m_procs.Values.First().SMApp.WorkPath; string dir = SMCenterUtils.Config.centerPush + "/publish/ctrl_sh/"; foreach (string path in Directory.GetFiles(dir)) { // center上bin文件路径:../centerPush/publish/ctrl_sh/*.sh // agent上cfg保存路径:WorkPath/../ctrl_sh/*.sh var file = FileUtils.CreateFileData(path, loadFile); if (file != null) { file.writeFilePath = Path.GetFullPath(Path.Combine(workPath, "../ctrl_sh")); TraceLog.Debug("CmdUtils.GetPushShellFile {0} md5 {1}, center path {2}, agent path {3}" , file.fileName, file.fileMd5, file.readFilePath, file.writeFilePath); fileList.Add(file); } } } catch (Exception e) { TraceLog.Exception(e); return -1; } return 0; } public static int GetPushAgentFile(CmdInfo cmdInfo, List fileList, bool loadFile) { // agent的运行目录可以选择硬编码完整路径,或根据center计算(center和agent的部署层次应该是一样) // var centerBin = Assembly.GetExecutingAssembly().Location; // 生成agent相对center的路径 // var relativePath = Path.Combine(Path.GetDirectoryName(centerBin), SMCenterUtils.Config.agentRunPath); // 转换成agent的完整路径 // var workPath = Path.GetFullPath((new Uri(relativePath)).LocalPath); try { // 把当前center同级目录下的agent发出去, build脚本把center和agent一起打包 //var dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); var dir = Path.GetFullPath(SMCenterUtils.Config.centerPush); var dll = dir + "/SMAgent.dll"; var pdb = dir + "/SMAgent.pdb"; if (!File.Exists(dll) || !File.Exists(pdb)) { return -1; } var file = FileUtils.CreateFileData(dll, loadFile); if (file != null) { // windows下进程被占用, 不能直接拷贝到bin目录 file.writeFilePath = SMCenterUtils.Config.agentRecv; TraceLog.Debug("CmdUtils.GetPushAgentFile {0} md5 {1}, center path {2}, agent path {3}" , file.fileName, file.fileMd5, file.readFilePath, file.writeFilePath); fileList.Add(file); } file = FileUtils.CreateFileData(pdb, loadFile); if (file != null) { file.writeFilePath = SMCenterUtils.Config.agentRecv; TraceLog.Debug("CmdUtils.GetPushAgentFile {0} md5 {1}, center path {2}, agent path {3}" , file.fileName, file.fileMd5, file.readFilePath, file.writeFilePath); fileList.Add(file); } } catch (Exception e) { TraceLog.Exception(e); return -1; } return 0; } public static int GetPushFile(CmdInfo cmdInfo, List fileList, bool loadFile) { try { /* push 命令支持绝对路径,如果是相对路径,那么是center和agent所在的bin目录为当前目录 * 所以最好用绝对路径,不容易出错 * -r 表示递归 * push 1.200.1 -r /data/mmogrun/publish/cfg/* /data/mmogrun/publish/cfg/ */ //先处理一下参数 bool recursive = false; List pushfileParams = new List(); for (int i = 1; i < cmdInfo.CmdParams.Count; i++) { var param = cmdInfo.CmdParams[i]; if (param == "-r") { recursive = true; } else { pushfileParams.Add(param); } } if (pushfileParams.Count != 2) { TraceLog.Error("CmdUtils.GetPushFile invalid param, need svrId, srcPath, dstPath"); return -1; } string srcFile, srcfullPath; string srcfilePath = pushfileParams[0]; string dstPath = pushfileParams[1]; //补一下'/',否则Path.GetFullPath结果不会带有'/' if (dstPath[dstPath.Length - 1] != '/' && dstPath[dstPath.Length - 1] != '\\') { dstPath += '/'; } string dstfullPath = Path.GetFullPath(dstPath); int lastindex = srcfilePath.LastIndexOf('/'); if (lastindex == -1) { lastindex = srcfilePath.LastIndexOf('\\'); if (lastindex == -1) { TraceLog.Error("CmdUtils.GetPushFile invalid src path {0}", srcfilePath); return -1; } } //源是个目录而不是文件名或通配符,那么在最后加个*上去,这样统一了 if (recursive && Directory.Exists(srcfilePath)) { if (srcfilePath[srcfilePath.Length - 1] != '/' && srcfilePath[srcfilePath.Length - 1] != '\\') { srcfilePath += '/'; } srcFile = "*"; srcfullPath = Path.GetFullPath(srcfilePath); srcfullPath = Path.GetDirectoryName(srcfullPath); } else { string srcPath = srcfilePath.Substring(0, lastindex + 1); srcFile = srcfilePath.Substring(lastindex + 1); srcfullPath = Path.GetFullPath(srcPath); srcfullPath = Path.GetDirectoryName(srcfullPath); } //说明只传一个文件 if (srcFile.Contains('*') == false) { string filefullpath = srcfullPath + "/" + srcFile; var file = FileUtils.CreateFileData(filefullpath, loadFile); if (file != null) { TraceLog.Trace("CmdUtils.GetPushFile add file {0}", filefullpath); fileList.Add(file); } return 0; } //根据通配符传送多个文件,先判断是否递归 SearchOption so = SearchOption.TopDirectoryOnly; if (recursive) { so = SearchOption.AllDirectories; } foreach (string filefullpath in Directory.GetFiles(srcfullPath, srcFile, so)) { var file = FileUtils.CreateFileData(filefullpath, loadFile); if (file != null) { // 子目录 if (file.readFilePath != srcfullPath) { string addsubdir = file.readFilePath.Substring(srcfullPath.Length); file.writeFilePath += addsubdir; } else { file.writeFilePath = dstfullPath; } TraceLog.Trace("CmdUtils.GetPushFile add file {0}", filefullpath); fileList.Add(file); } } } catch (Exception e) { TraceLog.Exception(e); return -1; } return 0; } } }