in hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/ssh/SshCollectImpl.java [77:168]
public void collect(CollectRep.MetricsData.Builder builder, Metrics metrics) {
long startTime = System.currentTimeMillis();
SshProtocol sshProtocol = metrics.getSsh();
boolean reuseConnection = Boolean.parseBoolean(sshProtocol.getReuseConnection());
boolean useProxy = Boolean.parseBoolean(sshProtocol.getUseProxy());
int timeout = CollectUtil.getTimeout(sshProtocol.getTimeout(), DEFAULT_TIMEOUT);
ClientChannel channel = null;
ClientSession clientSession = null;
try {
clientSession = getConnectSession(sshProtocol, timeout, reuseConnection, useProxy);
if (CommonSshBlacklist.isCommandBlacklisted(sshProtocol.getScript())) {
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg("The command is blacklisted: " + sshProtocol.getScript());
log.warn("The command is blacklisted: {}", sshProtocol.getScript());
return;
}
channel = clientSession.createExecChannel(sshProtocol.getScript());
ByteArrayOutputStream response = new ByteArrayOutputStream();
channel.setOut(response);
channel.setErr(new NoCloseOutputStream(System.err));
channel.open().verify(timeout);
List<ClientChannelEvent> list = new ArrayList<>();
list.add(ClientChannelEvent.CLOSED);
Collection<ClientChannelEvent> waitEvents = channel.waitFor(list, timeout);
if (waitEvents.contains(ClientChannelEvent.TIMEOUT)) {
// A cancel signal needs to be sent if the execution times out, otherwise the session cannot be closed promptly
int cancelSignal = 3;
channel.getInvertedIn().write(cancelSignal);
channel.getInvertedIn().flush();
throw new SocketTimeoutException("Failed to retrieve command result in time: " + sshProtocol.getScript());
}
Long responseTime = System.currentTimeMillis() - startTime;
String result = response.toString();
if (!StringUtils.hasText(result)) {
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg("ssh shell response data is null");
return;
}
switch (sshProtocol.getParseType()) {
case PARSE_TYPE_LOG -> parseResponseDataByLog(result, metrics.getAliasFields(), builder, responseTime);
case PARSE_TYPE_NETCAT -> parseResponseDataByNetcat(result, metrics.getAliasFields(), builder, responseTime);
case PARSE_TYPE_ONE_ROW -> parseResponseDataByOne(result, metrics.getAliasFields(), builder, responseTime);
case PARSE_TYPE_MULTI_ROW -> parseResponseDataByMulti(result, metrics.getAliasFields(), builder, responseTime);
default -> {
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg("Ssh collect not support this parse type: " + sshProtocol.getParseType());
}
}
} catch (ConnectException connectException) {
String errorMsg = CommonUtil.getMessageFromThrowable(connectException);
log.info(errorMsg);
builder.setCode(CollectRep.Code.UN_CONNECTABLE);
builder.setMsg("The peer refused to connect: service port does not listening or firewall: " + errorMsg);
} catch (SshException sshException) {
Throwable throwable = sshException.getCause();
if (throwable instanceof SshChannelOpenException) {
log.warn("Remote ssh server no more session channel, please increase sshd_config MaxSessions.");
}
String errorMsg = CommonUtil.getMessageFromThrowable(sshException);
builder.setCode(CollectRep.Code.UN_CONNECTABLE);
builder.setMsg("Peer ssh connection failed: " + errorMsg);
} catch (IOException ioException) {
String errorMsg = CommonUtil.getMessageFromThrowable(ioException);
log.info(errorMsg);
builder.setCode(CollectRep.Code.UN_CONNECTABLE);
builder.setMsg("Peer io connection failed: " + errorMsg);
} catch (Exception exception) {
String errorMsg = CommonUtil.getMessageFromThrowable(exception);
log.warn(errorMsg, exception);
builder.setCode(CollectRep.Code.FAIL);
builder.setMsg(errorMsg);
} finally {
if (channel != null && channel.isOpen()) {
try {
// Close the SSH channel with the 'false' parameter to ensure the session is not kept alive.
long st = System.currentTimeMillis();
channel.close(false).addListener(future ->
log.debug("channel is closed in {} ms", System.currentTimeMillis() - st));
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
if (clientSession != null && !reuseConnection && !useProxy) {
try {
clientSession.close();
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
}