diff --git a/o2server/restart_linux.sh b/o2server/restart_linux.sh new file mode 100755 index 0000000000000000000000000000000000000000..c0a61c4bff5ad1317f07d2896f808c01974dd5ab --- /dev/null +++ b/o2server/restart_linux.sh @@ -0,0 +1,16 @@ +echo ready to stop server $(cd "$(dirname "$0")"; pwd) +$(cd "$(dirname "$0")"; pwd)/jvm/linux/bin/java -javaagent:$(cd "$(dirname "$0")"; pwd)/console.jar -cp $(cd "$(dirname "$0")"; pwd)/console.jar com.x.server.console.swapcommand.Exit +echo 'check server stoped wait 2s-10s' +sleep 2 +PID=`ps -ef | grep "$(cd "$(dirname "$0")"; pwd)" | grep -v grep | awk '{print $2}'` +if [ "X$PID" != "X" ] +then + sleep 8 + if [ "X$PID" != "X" ] + then + echo ready to kill server $PID + kill -9 $PID + fi +fi +echo 'server stoped ready to start' +$(cd "$(dirname "$0")"; pwd)/start_linux.sh diff --git a/o2server/x_console/src/main/java/com/x/server/console/CommandFactory.java b/o2server/x_console/src/main/java/com/x/server/console/CommandFactory.java index 6288469b1342fe0bfb465454782b5fbdd40a47b8..a94b9c3395642be022700f2091c37f3f902901f1 100644 --- a/o2server/x_console/src/main/java/com/x/server/console/CommandFactory.java +++ b/o2server/x_console/src/main/java/com/x/server/console/CommandFactory.java @@ -18,10 +18,10 @@ public class CommandFactory { public static final Pattern test_pattern = Pattern.compile("^ {0,}test {0,}$", Pattern.CASE_INSENSITIVE); //public static final Pattern create_encrypt_key_pattern = Pattern.compile("^ {0,}create encrypt key{0,}$",Pattern.CASE_INSENSITIVE); - + public static final Pattern create_encrypt_key_pattern = Pattern.compile("^ {0,}create encrypt key {0,}$", Pattern.CASE_INSENSITIVE); - + public static final Pattern start_pattern = Pattern .compile("^ {0,}start {0,}(data|storage|center|application|web|all|) {0,}$", Pattern.CASE_INSENSITIVE); @@ -50,6 +50,8 @@ public class CommandFactory { public static final Pattern exit_pattern = Pattern.compile("^ {0,}exit {0,}$", Pattern.CASE_INSENSITIVE); + public static final Pattern restart_pattern = Pattern.compile("^ {0,}restart {0,}$", Pattern.CASE_INSENSITIVE); + // public static final Pattern updateFile_pattern = Pattern.compile("^ {0,}update file (.+) (true|false) {0,}$", // Pattern.CASE_INSENSITIVE); diff --git a/o2server/x_console/src/main/java/com/x/server/console/Main.java b/o2server/x_console/src/main/java/com/x/server/console/Main.java index 2735241c5644958775aeded9627ada595e819819..ea623c2da401c2b6cf6e20aeb859b856788b7a8d 100644 --- a/o2server/x_console/src/main/java/com/x/server/console/Main.java +++ b/o2server/x_console/src/main/java/com/x/server/console/Main.java @@ -1,14 +1,10 @@ package com.x.server.console; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.RandomAccessFile; +import java.io.*; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.lang.reflect.Method; +import java.net.Socket; import java.net.URL; import java.net.URLClassLoader; import java.nio.MappedByteBuffer; @@ -19,12 +15,12 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; import java.util.concurrent.LinkedBlockingQueue; import java.util.regex.Matcher; +import com.x.base.core.project.gson.XGsonBuilder; +import com.x.base.core.project.tools.Crypto; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.BooleanUtils; @@ -52,6 +48,7 @@ public class Main { private static final String MANIFEST_FILENAME = "manifest.cfg"; private static final String GITIGNORE_FILENAME = ".gitignore"; private static final LinkedBlockingQueue commandQueue = new LinkedBlockingQueue<>(); + private static NodeAgent nodeAgent; private static final Thread swapCommandThread = new Thread(() -> { // 文件中的命令输出到解析器 @@ -122,7 +119,7 @@ public class Main { swapCommandThread.start(); consoleCommandThread.start(); if (BooleanUtils.isTrue(Config.currentNode().nodeAgentEnable())) { - NodeAgent nodeAgent = new NodeAgent(); + nodeAgent = new NodeAgent(); nodeAgent.setCommandQueue(commandQueue); nodeAgent.setDaemon(true); nodeAgent.start(); @@ -234,6 +231,12 @@ public class Main { if (matcher.find()) { exit(); } + + matcher = CommandFactory.restart_pattern.matcher(cmd); + if (matcher.find()) { + restart(); + continue; + } System.out.println("unknown command:" + cmd); } // 关闭定时器 @@ -421,6 +424,90 @@ public class Main { System.exit(0); } + private static void restart() { + try { + System.out.println("ready to restart..."); + stopAll(); + stopAllThreads(); + String osName = System.getProperty("os.name"); + //System.out.println("当前操作系统是:"+osName); + File file = new File(Config.base(), "start_linux.sh"); + if (osName.toLowerCase().startsWith("mac")){ + file = new File(Config.base(), "start_macos.sh"); + }else if (osName.toLowerCase().startsWith("windows")) { + file = new File(Config.base(), "start_windows.bat"); + }else if(!file.exists()) { + file = new File("start_aix.sh"); + if(!file.exists()) { + file = new File("start_arm.sh"); + if(!file.exists()) { + file = new File("start_mips.sh"); + if(!file.exists()) { + file = new File("start_raspi.sh"); + } + } + } + } + if(file.exists()) { + System.out.println("server will start in new process!"); + Process ps = Runtime.getRuntime().exec(file.getAbsolutePath()); + Thread.sleep(1000); + if(!Config.currentNode().autoStart()) { + for (int i = 0; i < 5; i++) { + try (Socket socket = new Socket(Config.node(), Config.currentNode().nodeAgentPort())) { + socket.setKeepAlive(true); + socket.setSoTimeout(2000); + try (DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); + DataInputStream dis = new DataInputStream(socket.getInputStream())) { + Map commandObject = new HashMap<>(); + commandObject.put("command", "command:start"); + commandObject.put("credential", Crypto.rsaEncrypt("o2@", Config.publicKey())); + dos.writeUTF(XGsonBuilder.toJson(commandObject)); + dos.flush(); + break; + } + } catch (Exception ex) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } + } + } + }else{ + System.out.println("not support restart in current operating system!start server failure!"); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + System.exit(0); + } + } + + private static void stopAllThreads(){ + if(nodeAgent!=null){ + try { + nodeAgent.stopAgent(); + nodeAgent.interrupt(); + nodeAgent = null; + } catch (Exception e) { + } + } + if(swapCommandThread!=null){ + try { + swapCommandThread.interrupt(); + } catch (Exception e) { + } + } + if(consoleCommandThread!=null){ + try { + consoleCommandThread.interrupt(); + } catch (Exception e) { + } + } + + } + private static void stopAll() { try { WebServer webServer = Config.currentNode().getWeb(); @@ -466,7 +553,7 @@ public class Main { /** * 检查store目录下的war文件是否全部在manifest.cfg中 - * + * * @param base o2server的根目录 */ private static void scanWar(String base) throws Exception { @@ -621,4 +708,4 @@ public class Main { Files.write(path, Long.toString(pid).getBytes(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); } -} \ No newline at end of file +} diff --git a/o2server/x_console/src/main/java/com/x/server/console/NodeAgent.java b/o2server/x_console/src/main/java/com/x/server/console/NodeAgent.java index af78b274c441ea3ecb7bddd1d7c1a3a5c2c6d57c..95cd13183103e44e24d97a0a9a0fbd8e252f49ef 100644 --- a/o2server/x_console/src/main/java/com/x/server/console/NodeAgent.java +++ b/o2server/x_console/src/main/java/com/x/server/console/NodeAgent.java @@ -92,11 +92,16 @@ public class NodeAgent extends Thread { this.commandQueue = commandQueue; } + private volatile boolean runFlag = true; + + private ServerSocket serverSocket = null; + @Override public void run() { - try (ServerSocket serverSocket = new ServerSocket(Config.currentNode().nodeAgentPort())) { + try{ + serverSocket = new ServerSocket(Config.currentNode().nodeAgentPort()); Matcher matcher; - while (true) { + while (runFlag) { try (Socket socket = serverSocket.accept()) { try (DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); DataInputStream dis = new DataInputStream(socket.getInputStream())) { @@ -261,6 +266,24 @@ public class NodeAgent extends Thread { } } catch (Exception e) { e.printStackTrace(); + } finally { + if(serverSocket!=null){ + try { + serverSocket.close(); + } catch (IOException e) { + } + } + } + } + + public void stopAgent(){ + try { + this.runFlag = false; + if(serverSocket!=null) { + this.serverSocket.close(); + this.serverSocket = null; + } + } catch (Exception e) { } } diff --git a/o2server/x_organization_core_entity/src/main/java/com/x/organization/core/entity/Custom.java b/o2server/x_organization_core_entity/src/main/java/com/x/organization/core/entity/Custom.java index 672cb723dbe4cf2a3598bbe57048843504309e4f..608caeb393766a8467917646c957c8f7a8a61c59 100644 --- a/o2server/x_organization_core_entity/src/main/java/com/x/organization/core/entity/Custom.java +++ b/o2server/x_organization_core_entity/src/main/java/com/x/organization/core/entity/Custom.java @@ -61,7 +61,7 @@ public class Custom extends SliceJpaObject { public static final String person_FIELDNAME = "person"; @FieldDescribe("属性所属个人,不可为空.") - @Column(length = JpaObject.length_id, name = ColumnNamePrefix + person_FIELDNAME) + @Column(length = length_255B, name = ColumnNamePrefix + person_FIELDNAME) @Index(name = TABLE + IndexNameMiddle + person_FIELDNAME) @CheckPersist(allowEmpty = false) private String person; @@ -103,4 +103,4 @@ public class Custom extends SliceJpaObject { this.name = name; } -} \ No newline at end of file +} diff --git a/o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/command/ActionCommand.java b/o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/command/ActionCommand.java index eb6c14ab2f6faac1627f38fcdd6e50b37f7f1a00..048f173452099528d87e7e633950614ca358ade4 100644 --- a/o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/command/ActionCommand.java +++ b/o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/command/ActionCommand.java @@ -1,6 +1,5 @@ package com.x.program.center.jaxrs.command; -import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; @@ -11,8 +10,6 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; @@ -30,32 +27,24 @@ import com.x.base.core.project.tools.Crypto; /*执行服务器命令*/ public class ActionCommand extends BaseAction { - - + private static Logger logger = LoggerFactory.getLogger(ActionCommand.class); + ActionResult execute(HttpServletRequest request, EffectivePerson effectivePerson, JsonElement jsonElement) throws Exception { ActionResult result = new ActionResult<>(); Wi wi = this.convertToWrapIn(jsonElement, Wi.class); String ctl = wi.getCtl(); String nodeName = wi.getNodeName() ; - String curServer = request.getLocalAddr(); Wo wo = null; if(nodeName.equalsIgnoreCase("*")) { Nodes nodes = Config.nodes(); if (ctl.indexOf("create encrypt")>-1) { //生成key文件 - for (String node : nodes.keySet()){ - //当前服务器 - if(node.equalsIgnoreCase(curServer)) { - if(nodes.get(curServer).getApplication().getEnable() || nodes.get(curServer).getCenter().getEnable()){ - wo = executeCommand(ctl, node, nodes.get(node).nodeAgentPort()); - } - } - } + wo = executeCommand(ctl, Config.node(), nodes.get(Config.node()).nodeAgentPort()); //同步key文件 for (String node : nodes.keySet()){ //其他服务器 - if(!node.equalsIgnoreCase(curServer)) { + if(!node.equalsIgnoreCase(Config.node())) { if(nodes.get(node).getApplication().getEnable() || nodes.get(node).getCenter().getEnable()){ boolean Syncflag = executeSyncFile("config/public.key" , node ,nodes.get(node).nodeAgentPort()); Syncflag = executeSyncFile("config/private.key" , node ,nodes.get(node).nodeAgentPort()); @@ -63,35 +52,26 @@ public class ActionCommand extends BaseAction { } } } - }else { - - for (String node : nodes.keySet()){ - //先其他服务器 - if(!node.equalsIgnoreCase(curServer)) { - if(nodes.get(node).getApplication().getEnable() || nodes.get(node).getCenter().getEnable()){ - wo = executeCommand(ctl, node, nodes.get(node).nodeAgentPort()); - } - } - } - + //先其他服务器再当前服务器 for (String node : nodes.keySet()){ - //后当前服务器 - if(node.equalsIgnoreCase(curServer)) { - if(nodes.get(curServer).getApplication().getEnable() || nodes.get(curServer).getCenter().getEnable()){ - wo = executeCommand(ctl, node, nodes.get(node).nodeAgentPort()); - } + if(!node.equalsIgnoreCase(Config.node())) { + logger.print("{} executeCommand {} on node {}",effectivePerson.getDistinguishedName(), ctl, node); + wo = executeCommand(ctl, node, nodes.get(node).nodeAgentPort()); } } + logger.print("{} executeCommand {} on node {}",effectivePerson.getDistinguishedName(), ctl, Config.node()); + wo = executeCommand(ctl, Config.node(), nodes.get(Config.node()).nodeAgentPort()); } }else { - wo = executeCommand(ctl, nodeName, Integer.parseInt(wi.getNodePort())); + logger.print("{} executeCommand {} on node {}",effectivePerson.getDistinguishedName(), ctl, nodeName); + wo = executeCommand(ctl, nodeName, Integer.parseInt(wi.getNodePort())); } - + result.setData(wo); return result; } - + synchronized private Wo executeCommand(String ctl , String nodeName ,int nodePort) throws Exception{ Wo wo = new Wo(); wo.setNode(nodeName); @@ -106,7 +86,7 @@ public class ActionCommand extends BaseAction { commandObject.put("credential", Crypto.rsaEncrypt("o2@", Config.publicKey())); dos.writeUTF(XGsonBuilder.toJson(commandObject)); dos.flush(); - + if (ctl.indexOf("create encrypt")>-1) { String createEncrypt = dis.readUTF(); logger.info(createEncrypt); @@ -120,18 +100,18 @@ public class ActionCommand extends BaseAction { wo.setTime(df.format(new Date())); return wo; } - - + + private boolean executeSyncFile(String syncFilePath , String nodeName ,int nodePort){ boolean syncFileFlag = false; File syncFile; InputStream fileInputStream = null; - + try (Socket socket = new Socket(nodeName, nodePort)) { - + syncFile = new File(Config.base(), syncFilePath); fileInputStream= new FileInputStream(syncFile); - + socket.setKeepAlive(true); socket.setSoTimeout(5000); DataOutputStream dos = null; @@ -139,17 +119,17 @@ public class ActionCommand extends BaseAction { try { dos = new DataOutputStream(socket.getOutputStream()); dis = new DataInputStream(socket.getInputStream()); - + Map commandObject = new HashMap<>(); commandObject.put("command", "syncFile:"+ syncFilePath); commandObject.put("credential", Crypto.rsaEncrypt("o2@", Config.publicKey())); dos.writeUTF(XGsonBuilder.toJson(commandObject)); dos.flush(); - + dos.writeUTF(syncFilePath); dos.flush(); - - + + logger.info("同步文件starting......."); byte[] bytes = new byte[1024]; int length =0; @@ -158,14 +138,14 @@ public class ActionCommand extends BaseAction { dos.flush(); } logger.info("同步文件end......."); - + }finally { dos.close(); dis.close(); socket.close(); fileInputStream.close(); } - + syncFileFlag = true; } catch (Exception ex) { logger.error(ex); @@ -173,7 +153,7 @@ public class ActionCommand extends BaseAction { } return syncFileFlag; } - + public static class Wi extends GsonPropertyObject{ @FieldDescribe("命令名称") private String ctl; @@ -181,7 +161,7 @@ public class ActionCommand extends BaseAction { private String nodeName; @FieldDescribe("服务端口") private String nodePort; - + public String getCtl() { return ctl; } @@ -201,9 +181,9 @@ public class ActionCommand extends BaseAction { this.nodePort = nodePort; } } - + public static class Wo extends GsonPropertyObject { - + @FieldDescribe("执行时间") private String time; @FieldDescribe("执行结束") @@ -214,11 +194,11 @@ public class ActionCommand extends BaseAction { public String getTime() { return time; } - + public void setTime(String time) { this.time = time; } - + public String getNode() { return node; } @@ -235,7 +215,7 @@ public class ActionCommand extends BaseAction { this.status = status; } } - - + + }