ssh 列表安装节点按钮判断 java 环境

This commit is contained in:
bwcx_jzy 2022-01-12 22:38:52 +08:00
parent 53e310d357
commit 0a5e06f789
No known key found for this signature in database
GPG Key ID: 5E48E9372088B9E5
11 changed files with 154 additions and 51 deletions

View File

@ -16,6 +16,7 @@
5. 脚本模版新增描述字段(感谢@ʟᴊx💎💎
6. 在线升级取消重复 jar 包判断,改为自动重命名(感谢@大土豆)
7. 项目文件管理调整为支持清空当前目录(感谢@ʟᴊx💎💎
8. 【server】ssh 列表安装节点按钮判断 java 环境
------

View File

@ -8,6 +8,7 @@
3. ~~ssh 批量执行命令~~
4. 自定义检查项目状态
5. 自定义启动项目脚本
6. 快速安装导入插件端
----

View File

@ -120,4 +120,4 @@ rm -f install.sh
# 添加权限
chmod 755 ${TYPE}.sh
# 启动
sh ${TYPE}.sh start
sh ${TYPE}.sh start $@

View File

@ -7,6 +7,7 @@
<formats>
<format>dir</format>
<format>zip</format>
<format>tar.gz</format>
</formats>
<fileSets>

View File

@ -55,8 +55,11 @@ import java.net.URL;
@PreLoadClass
public class AutoRegSeverNode {
/**
* 向服务端注册插件端
*/
@PreLoadMethod
private static void reg() throws FileNotFoundException {
private static void reg() {
AgentExtConfigBean instance = AgentExtConfigBean.getInstance();
String agentId = instance.getAgentId();
String serverUrl = instance.getServerUrl();
@ -68,7 +71,11 @@ public class AutoRegSeverNode {
File file = FileUtil.file(ConfigBean.getInstance().getDataPath(), AgentConfigBean.SERVER_ID);
JSONObject serverJson = null;
if (file.exists()) {
serverJson = (JSONObject) JsonFileUtil.readJson(file.getAbsolutePath());
try {
serverJson = (JSONObject) JsonFileUtil.readJson(file.getAbsolutePath());
} catch (FileNotFoundException e) {
serverJson = new JSONObject();
}
oldInstallId = serverJson.getString("installId");
}
HttpRequest installRequest = instance.createServerRequest(ServerOpenApi.INSTALL_ID);

View File

@ -0,0 +1,25 @@
package cn;
import cn.hutool.core.io.resource.ResourceUtil;
import org.junit.Test;
import org.yaml.snakeyaml.Yaml;
import java.net.URL;
/**
* @author bwcx_jzy
* @since 2022/1/12
*/
public class TestYml {
@Test
public void test() {
URL resource = ResourceUtil.getResource("test.yml");
final Yaml yaml = new Yaml();
Object load = yaml.load(ResourceUtil.getStream("test.yml"));
System.out.println(load);
// Dict dict = YamlUtil.loadByPath(resource.getPath());
// System.out.println(dict);
}
}

View File

@ -0,0 +1,3 @@
# test
a:
b: t

View File

@ -200,19 +200,22 @@ public class SshController extends BaseServerController {
List<NodeModel> nodeBySshId = nodeService.getNodeBySshId(sshModel.getId());
JSONObject data = new JSONObject();
NodeModel nodeModel = CollUtil.getFirst(nodeBySshId);
if (nodeModel == null) {
try {
SshModel model = sshService.getByKey(sshModel.getId(), false);
SshModel model = sshService.getByKey(sshModel.getId(), false);
try {
if (nodeModel == null) {
Integer pid = sshService.checkSshRunPid(model, Type.Agent.getTag());
data.put("pid", ObjectUtil.defaultIfNull(pid, 0));
data.put("ok", true);
} catch (Exception e) {
DefaultSystemLog.getLog().error("检查运行状态异常:{}", e.getMessage());
data.put("error", e.getMessage());
} else {
data.put("nodeId", nodeModel.getId());
data.put("nodeName", nodeModel.getName());
}
} else {
data.put("nodeId", nodeModel.getId());
data.put("nodeName", nodeModel.getName());
//
String javaVersion = sshService.getSshJavaVersion(model);
data.put("javaVersion", javaVersion);
} catch (Exception e) {
DefaultSystemLog.getLog().error("检查运行状态异常:{}", e.getMessage());
data.put("error", e.getMessage());
}
result.put(sshModel.getId(), data);
}

View File

@ -119,6 +119,22 @@ public class SshService extends BaseWorkspaceService<SshModel> {
return this.checkSshRunPid(sshModel, tag) != null;
}
/**
* 获取 ssh 中的 Java 版本
*
* @param sshModel ssh
* @return true 存在运行中的
* @throws IOException IO
* @throws JSchException jsch
*/
public String getSshJavaVersion(SshModel sshModel) throws IOException, JSchException {
// 检查 java 环境
String javaVersion = "java -version";
List<String> command = this.execCommand(sshModel, javaVersion);
String join = CollUtil.join(command, StrUtil.COMMA);
return ReUtil.getGroup0("\"(.*?)\"", join);
}
/**
* 检查是否存在正在运行的进程
*
@ -130,28 +146,12 @@ public class SshService extends BaseWorkspaceService<SshModel> {
*/
public Integer checkSshRunPid(SshModel sshModel, String tag) throws IOException, JSchException {
String ps = StrUtil.format("ps -ef | grep -v 'grep' | egrep {}", tag);
Session session = null;
ChannelExec channel = null;
try {
session = getSessionByModel(sshModel);
channel = (ChannelExec) JschUtil.createChannel(session, ChannelType.EXEC);
channel.setCommand(ps);
InputStream inputStream = channel.getInputStream();
InputStream errStream = channel.getErrStream();
channel.connect();
Charset charset = sshModel.getCharsetT();
// 运行中
List<String> result = new ArrayList<>();
IoUtil.readLines(inputStream, charset, (LineHandler) result::add);
IoUtil.readLines(errStream, charset, (LineHandler) result::add);
return result.stream().map(s -> {
List<String> split = StrUtil.splitTrim(s, StrUtil.SPACE);
return Convert.toInt(CollUtil.get(split, 1));
}).filter(Objects::nonNull).findAny().orElse(null);
} finally {
JschUtil.close(channel);
JschUtil.close(session);
}
// 运行中
List<String> result = this.execCommand(sshModel, ps);
return result.stream().map(s -> {
List<String> split = StrUtil.splitTrim(s, StrUtil.SPACE);
return Convert.toInt(CollUtil.get(split, 1));
}).filter(Objects::nonNull).findAny().orElse(null);
}
/**
@ -273,6 +273,29 @@ public class SshService extends BaseWorkspaceService<SshModel> {
}
}
private List<String> execCommand(SshModel sshModel, String command) throws IOException, JSchException {
Session session = null;
ChannelExec channel = null;
try {
session = getSessionByModel(sshModel);
channel = (ChannelExec) JschUtil.createChannel(session, ChannelType.EXEC);
// 添加环境变量
channel.setCommand(ServerExtConfigBean.getInstance().getSshInitEnv() + " && " + command);
InputStream inputStream = channel.getInputStream();
InputStream errStream = channel.getErrStream();
channel.connect();
Charset charset = sshModel.getCharsetT();
// 运行中
List<String> result = new ArrayList<>();
IoUtil.readLines(inputStream, charset, (LineHandler) result::add);
IoUtil.readLines(errStream, charset, (LineHandler) result::add);
return result;
} finally {
JschUtil.close(channel);
JschUtil.close(session);
}
}
/**
* 上传文件
*

View File

@ -20,9 +20,14 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import cn.hutool.core.net.NetUtil;
import org.junit.Test;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.LinkedHashSet;
/**
* @author bwcx_jzy
* @since Created Time 2021/8/4
@ -32,7 +37,19 @@ public class TestIp {
@Test
public void test() {
System.out.println(NetUtil.getLocalhostStr());
System.out.println(NetUtil.getLocalhost().getHostAddress());
// System.out.println(NetUtil.getLocalhost().getHostAddress());
System.out.println("------");
final LinkedHashSet<InetAddress> localAddressList = NetUtil.localAddressList(address -> {
// 非loopback地址指127.*.*.*的地址
return !address.isLoopbackAddress()
// 需为IPV4地址
&& address instanceof Inet4Address;
});
for (InetAddress inetAddress : localAddressList) {
System.out.println(inetAddress.getHostAddress());
//System.out.println(((Inet4Address) inetAddress).toString());
//System.out.println("-");
}
}
@Test

View File

@ -8,28 +8,50 @@
<a-button type="primary" @click="loadData">搜索</a-button>
</a-tooltip>
<a-button type="primary" @click="handleAdd">新增</a-button>
<a-tooltip>
<template slot="title">
<div>
<ul>
<li>关联节点数据是异步获取有一定时间延迟</li>
<li>关联节点会自动识别服务器中是否存在 java 环境,如果没有 Java 环境不能快速安装节点</li>
<li>关联节点如果服务器存在 java 环境,但是插件端未运行则会显示快速安装按钮</li>
</ul>
</div>
</template>
<a-icon type="question-circle" theme="filled" />
</a-tooltip>
</a-space>
关联节点数据是异步获取有一定时间延迟
</div>
<!-- 数据表格 -->
<a-table :data-source="list" :loading="loading" :columns="columns" :pagination="this.pagination" @change="changePage" bordered :rowKey="(record, index) => index">
<template slot="nodeId" slot-scope="text, record">
<!-- <a-button v-if="!record.nodeModel" type="primary" @click="install(record)" :disabled="record.installed">安装节点</a-button> -->
<a-tooltip v-if="sshAgentInfo[record.id] && sshAgentInfo[record.id].nodeId" placement="topLeft" :title="`${sshAgentInfo[record.id].nodeName}`">
<a-button style="width: 90px; padding: 0 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis" type="" @click="toNode(sshAgentInfo[record.id].nodeId)">
{{ sshAgentInfo[record.id].nodeName }}
</a-button>
</a-tooltip>
<a-tooltip v-if="sshAgentInfo[record.id] && sshAgentInfo[record.id].error" placement="topLeft" :title="`${sshAgentInfo[record.id].error}`">
{{ sshAgentInfo[record.id].error }}
</a-tooltip>
<a-tooltip
v-if="sshAgentInfo[record.id] && sshAgentInfo[record.id].ok"
placement="topLeft"
:title="`${sshAgentInfo[record.id].pid > 0 ? 'ssh 中已经运行了插件端进程ID' + sshAgentInfo[record.id].pid : '点击快速安装插件端'}`"
>
<a-button type="primary" @click="install(record)" :disabled="sshAgentInfo[record.id].pid > 0">安装节点</a-button>
</a-tooltip>
<div v-if="sshAgentInfo[record.id]">
<div v-if="sshAgentInfo[record.id].javaVersion">
<a-tooltip v-if="sshAgentInfo[record.id].nodeId" placement="topLeft" :title="`节点名称:${sshAgentInfo[record.id].nodeName} java version:${sshAgentInfo[record.id].javaVersion}`">
<a-button style="width: 90px; padding: 0 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis" type="" @click="toNode(sshAgentInfo[record.id].nodeId)">
{{ sshAgentInfo[record.id].nodeName }}
</a-button>
</a-tooltip>
<a-tooltip v-if="sshAgentInfo[record.id].error" placement="topLeft" :title="`${sshAgentInfo[record.id].error}`">
{{ sshAgentInfo[record.id].error }}
</a-tooltip>
<a-tooltip
v-if="sshAgentInfo[record.id].ok"
placement="topLeft"
:title="`${
sshAgentInfo[record.id].pid > 0
? 'ssh 中已经运行了插件端进程ID' + sshAgentInfo[record.id].pid + ',java version:' + sshAgentInfo[record.id].javaVersion
: '点击快速安装插件端,java version:' + sshAgentInfo[record.id].javaVersion
}`"
>
<a-button type="primary" @click="install(record)" :disabled="sshAgentInfo[record.id].pid > 0">安装节点</a-button>
</a-tooltip>
</div>
<div v-else><a-tag>没有Java环境</a-tag></div>
</div>
<div v-else>-</div>
</template>
<template slot="operation" slot-scope="text, record">
<a-space>