using Tiobon.Core.OPS.Tool.OPS.Tool.Helper; using Tiobon.Core.OPS.Tool.OPS.Tool.Model; using Tiobon.Core.OPS.Tool.OPS.Tool.View; using ICSharpCode.SharpZipLib.Zip; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Web.Script.Serialization; using System.Windows.Forms; using System.Text.RegularExpressions; namespace Tiobon.Core.OPS.Tool.OPS.Tool.Src { public class Module_method { #region 全局变量 SSHHelper sSH = new SSHHelper(Const.config.ip, Const.config.ssh_port, Const.config.ssh_user, Const.config.ssh_passwd); SFTPHelper sFTP = new SFTPHelper(Const.config.ip, Const.config.ssh_port, Const.config.ssh_user, Const.config.ssh_passwd); bool isLinux = Const.config.system == "Linux"; public Action End_Init; Module module_conf; #endregion #region 获取配置信息 public Module GetConf(string filepath) { Const.ExtractSpecifyZipFile(filepath, "Config/", "", new List { "README.ihdis" }); string fm = File.ReadAllText("Config/README.ihdis"); JavaScriptSerializer js = new JavaScriptSerializer(); module_conf = js.Deserialize(fm); return module_conf; } #endregion #region 检测压缩包是否损坏 public bool Is_BadZip(string path) { try { ZipFile entry = new ZipFile(path); return true; } catch { return false; } } #endregion #region 模块安装 public void Install(string filepath, Action handle) { bool isLinux = Const.config.system == "Linux"; var hospital = Const.config.install_item_dir.Split('/').Last(); if (isLinux) { var installpath = $"/home/{Const.config.ssh_user}/ihdis/tools/{module_conf.Name}"; var webpath = $"/home/{Const.config.ssh_user}/ihdis/produse"; try { sSH.Connect(); var tmpdir = $"/tmp/{module_conf.Name}{new Random().Next(10000, 20000)}"; //1,上传文件 handle?.Invoke("正在上传文件..."); Upload(filepath, handle); //2,解压到临时目录 handle?.Invoke("正在解压到临时目录..."); sSH.Excute_Longcmd($"unzip -qo /home/{Const.config.ssh_user}/ihdis/tools/{filepath.Split('\\')[filepath.Split('\\').Length - 1]} -d {tmpdir}"); if (File.Exists("Config/README.ihdis")) { sFTP.Connect(); sFTP.Put("Config/README.ihdis", $"{tmpdir}", "README.ihdis"); sFTP.Disconnect(); } var tmp = Const.config.install_item_dir.Split('/'); var item = Const.MultiEnvs.Where(o => o.Ip == Const.config.ip && o.FileName == tmp[tmp.Length - 1]).FirstOrDefault(); //3,运行init.sh脚本 sSH.Excute_Longcmd_NoError($"cd {installpath} && sudo docker-compose down "); sSH.Excute_Longcmd_NoError($"rm -rf {installpath}"); handle?.Invoke("运行init.sh脚本..."); sSH.Excute_Longcmd_NoError($"sudo sh {tmpdir}/init.sh {tmpdir} {installpath} {webpath}"); sSH.Excute_Longcmd($"sed -i \"s/JL_NETWORK=.*/JL_NETWORK={item.FileName}_oi_net/\" {installpath}/.env"); //4.启动docker handle?.Invoke("启动插件..."); sSH.Excute_Longcmd_NoError($"cd {installpath} && sudo docker-compose up -d "); // 5, 添加开机启动 handle?.Invoke("添加开机启动..."); PluginAutoRestart(installpath, module_conf.Name); // 6,清理缓存 handle?.Invoke("清理缓存..."); sSH.Excute_Longcmd($"sudo bash -c 'echo 3 > /proc/sys/vm/drop_caches'"); //7.删除临时文件 sSH.Excute_Longcmd($"rm -r {tmpdir}"); var tmp1 = filepath.Split('\\'); string filename = tmp1[tmp1.Length - 1]; if (sFTP.Exists($"/home/{Const.config.ssh_user}/ihdis/tools/" + filename)) sFTP.Delete($"/home/{Const.config.ssh_user}/ihdis/tools/" + filename); handle?.Invoke("安装完成..."); sSH.Disconnect(); } catch (Exception ex) { MessageBox.Show($"安装过程出错,请截图错误信息或复制日志后联系工程师!\r\n\r\n{ex.Message}"); } } else { #region Windows var tmpdir = $"{Path.GetTempPath()}{module_conf.Name}{new Random().Next(10000, 20000)}"; //1.解压目录 Const.write_task_log("正在解压安装包..."); if (!Directory.Exists(tmpdir)) Directory.CreateDirectory(tmpdir); Const.ExtractZipFile(filepath, tmpdir, "", null); //2.创建安装目录 var installpath = $"{Const.config.install_dir}\\tools\\{module_conf.Name}"; if (!Directory.Exists(installpath)) Directory.CreateDirectory(installpath); //3.进行插件初始化 handle?.Invoke("正在初始化插件..."); Init(tmpdir, installpath, hospital, handle); Const.DeleteADirectory(tmpdir + "\\"); handle?.Invoke("安装完成..."); Thread.Sleep(2000); #endregion } End_Init(); } #endregion #region 插件开机启动 public void PluginAutoRestart(string installPath, string model) { try { sSH.Excute_Longcmd($"sudo cd {installPath}"); sSH.Excute_Longcmd($"sudo echo '#!/bin/bash' > autostart_{model}.sh"); sSH.Excute_Longcmd($"sudo echo '#chkconfig:345 95 95' >> autostart_{model}.sh"); sSH.Excute_Longcmd($"sudo echo '#description:开机自启脚本' >> autostart_{model}.sh"); sSH.Excute_Longcmd($"sudo echo 'cd {installPath}' >> autostart_{model}.sh"); sSH.Excute_Longcmd($"sudo echo 'sudo docker-compose restart' >> autostart_{model}.sh"); sSH.Excute_Longcmd($"sudo mv autostart_{model}.sh /etc/rc.d/init.d"); sSH.Excute_Longcmd($"sudo chmod +x /etc/rc.d/init.d/autostart_{model}.sh"); sSH.Excute_Longcmd($"cd /etc/rc.d/init.d"); sSH.Excute_Longcmd($"sudo chkconfig --add autostart_{model}.sh"); //sSH.Excute_Longcmd($"chkconfig --list"); sSH.Excute_Longcmd($"sudo chkconfig autostart_{model}.sh on"); } catch (Exception ex) { MessageBox.Show($"插件开机启动失败,请截图错误信息或复制日志后联系工程师!\r\n\r\n{ex.Message}"); } } #endregion #region 上传文件 public void Upload(string filepath, Action handle) { try { var tmp = filepath.Split('\\'); string filename = tmp[tmp.Length - 1]; sFTP.Connect(); if (sFTP.Exists($"/home/{Const.config.ssh_user}/ihdis/tools/" + filename)) { handle?.Invoke($"删除同名更新包..."); sFTP.Delete($"/home/{Const.config.ssh_user}/ihdis/tools/" + filename); handle?.Invoke($"【{filename}】删除完成..."); } handle?.Invoke($"开始上传更新包..."); sFTP.Put(filepath, $"/home/{Const.config.ssh_user}/ihdis/tools/", filename); handle?.Invoke($"更新包上传完成..."); sFTP.Disconnect(); } catch (Exception ex) { MessageBox.Show($"上传文件失败,请截图错误信息或复制日志后联系工程师!\r\n\r\n{ex.Message}"); } } #endregion /// /// 初始化插件 /// /// /// /// public void Init(string tmpdir, string installPath, string hospital, Action handle) { var allOldLines = new List(); if (File.Exists($"{installPath}\\.env")) allOldLines = File.ReadAllLines($"{installPath}\\.env").ToList(); Const.CopyDir(tmpdir, installPath); var env = File.ReadAllText($"{tmpdir}\\.env").ToLower(); var tmp = Const.config.install_item_dir.Split('/'); var item = Const.MultiEnvs.Where(o => o.Ip == Const.config.ip && o.FileName == tmp[tmp.Length - 1]).FirstOrDefault(); // 判断安装插件类型 if (env.Contains("ts")) { Const.CopyDir($"{installPath}\\conf", $"{installPath}\\code"); CmdHelper.RunCmd($"docker load -i {installPath}\\ts.base.tar.gz\r\ndocker tag hh/ts:base hh/ts:1.33.0", out _); } else if (env.Contains("fsc")) { CmdHelper.RunCmd($"docker import {installPath}\\fsc.tar.gz hh/fsc:1.0.0", out _); } else if (env.Contains("hdis_qc")) // 质控插件 { var allLines = File.ReadAllLines($"{tmpdir}\\.env").ToList(); var projectNameStr = "PROJECT_NAME="; var apiVersionStr = "API_VERSION="; var webVersionStr = "WEB_VERSION="; var projectName = allLines.Where(o => o.Contains(projectNameStr)).FirstOrDefault()?.Split('=')[1]; var apiVersion = allLines.Where(o => o.Contains(apiVersionStr)).FirstOrDefault()?.Split('=')[1]; var webVersion = allLines.Where(o => o.Contains(apiVersionStr)).FirstOrDefault()?.Split('=')[1]; #region 删除旧镜像 if (allOldLines.Any()) { handle?.Invoke("开始删除旧镜像..."); var projectName1 = allOldLines.Where(o => o.Contains(projectNameStr)).FirstOrDefault()?.Split('=')[1]; var apiVersion1 = allOldLines.Where(o => o.Contains(apiVersionStr)).FirstOrDefault()?.Split('=')[1]; var webVersion1 = allOldLines.Where(o => o.Contains(apiVersionStr)).FirstOrDefault()?.Split('=')[1]; CmdHelper.RunCmd($"docker rmi {projectName1}/api:{apiVersion1}", out _); CmdHelper.RunCmd($"docker rmi {projectName1}/web:{webVersion1}", out _); handle?.Invoke("完成删除旧镜像..."); } #endregion handle?.Invoke("挂载镜像..."); #region 替换端口号、子网掩码 var newEnv = File.ReadAllText($"{tmpdir}\\.env").Replace("produce_oi_net", $"{item.FileName}_oi_net"); File.WriteAllText($"{installPath}/.env", newEnv); var yml = File.ReadAllText($"{installPath}/docker-compose.yml"); yml = yml.Replace("produce_oi_net", $"{item.FileName}_oi_net"); File.WriteAllText($"{installPath}/docker-compose.yml", yml); #endregion //生成Docker Desktop挂载目录 Main_method.AddDockerMountPath(yml, installPath); CmdHelper.RunCmd($"docker images --format \"{{{{.Repository}}}}:{{{{.Tag}}}}\"", out string res); if (!res.Contains($"{projectName}/api:{apiVersion}")) CmdHelper.RunCmd($"docker load -i {installPath}\\images\\{projectName}_api_{apiVersion}.tar", out _); if (!res.Contains($"{projectName}/web:{apiVersion}")) CmdHelper.RunCmd($"docker load -i {installPath}\\images\\{projectName}_web_{webVersion}.tar", out _); handle?.Invoke("挂载镜像完成..."); } var resultLog = string.Empty; handle?.Invoke("正在启动容器..."); CmdHelper.RunCmd($"{installPath.Split(':')[0].Trim()}: \r\ncd {$"{installPath}/"}" + $"\r\ndocker-compose up -d \r\nexit", out resultLog); if (env.Contains("ts")) { var webPath = $"{Const.config.install_dir}\\{hospital}"; var webConf = $"{webPath}\\conf\\nginx\\site\\web.conf"; var webConfLines = File.ReadAllLines(webConf).ToList(); if (!webConfLines.Any(o => o.Contains("ts/ts"))) { webConfLines.Insert(6, " location /ts/ {"); webConfLines.Insert(7, " proxy_pass http://ts/ts/;"); webConfLines.Insert(8, " }"); File.WriteAllLines(webConf, webConfLines); handle?.Invoke("正在重启nginx..."); CmdHelper.RunCmd($"{webPath.Split(':')[0].Trim()}: \r\ncd {$"{webPath}/"}" + $"\r\ndocker-compose restart nginx \r\nexit", out _); } } } } }