Зажечь обнаружение ОС Linux как Windows при использовании функции автозапуска - PullRequest
0 голосов
/ 13 июня 2018

Я написал программу, которая может автоматически запускать сервер Ignite, когда ему предоставляется подробная информация (адрес машины, имя пользователя, пароль и т. Д.) Различных машин.В моем случае я пытаюсь сделать это на двух машинах, для простоты давайте назовем их X и Y. Я использую Ignite версии 1.9.

Код довольно прост и вызывает следующий API, предоставленный вКласс org.apache.ignite.IgniteCluster для запуска сервера Ignite на удаленных компьютерах:

Collection<ClusterStartNodeResult> org.apache.ignite.IgniteCluster.startNodes(Collection<Map<String, Object>> hosts, @Nullable Map<String, Object> dflts, boolean restart, int timeout, int maxConn) throws IgniteException

После выполнения кода сервер Ignite успешно запускается на компьютере X, тогда как при запуске Ignite Server он выдает следующее исключениена компьютере Y:

Caused by: com.abc.roc.exception.ROCException: One  of the Nodes failed to start properly, java.lang.UnsupportedOperationException: Apache Ignite cannot be auto-started on Windows from IgniteCluster.startNodes(â–’) API.
    at org.apache.ignite.internal.util.nodestart.StartNodeCallableImpl.call(StartNodeCallableImpl.java:138)
    at org.apache.ignite.internal.util.nodestart.StartNodeCallableImpl.call(StartNodeCallableImpl.java:47)
    at org.apache.ignite.internal.util.IgniteUtils.wrapThreadLoader(IgniteUtils.java:6618)
    at org.apache.ignite.internal.processors.closure.GridClosureProcessor$2.body(GridClosureProcessor.java:925)
    at org.apache.ignite.internal.util.worker.GridWorker.run(GridWorker.java:110)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

Я немного углубился в исходный код класса и метод StartNodeCallableImpl.call (), из которого было сгенерировано исключение.Соответствующий моментальный снимок метода вызова, упомянутого выше из исходного кода Apache Ignite, выглядит следующим образом:

    JSch ssh = new JSch();

    Session ses = null;

    try {
        if (spec.key() != null)
            ssh.addIdentity(spec.key().getAbsolutePath());

        ses = ssh.getSession(spec.username(), spec.host(), spec.port());

        if (spec.password() != null)
            ses.setPassword(spec.password());

        ses.setConfig("StrictHostKeyChecking", "no");

        ses.connect(timeout);

        boolean win = isWindows(ses);

        char separator = win ? '\\' : '/';

        spec.fixPaths(separator);

        String igniteHome = spec.igniteHome();

        if (igniteHome == null)
            igniteHome = win ? DFLT_IGNITE_HOME_WIN : DFLT_IGNITE_HOME_LINUX;

        String script = spec.script();

        if (script == null)
            script = DFLT_SCRIPT_LINUX;

        String cfg = spec.configuration();

        if (cfg == null)
            cfg = "";

        String startNodeCmd;
        String scriptOutputFileName = FILE_NAME_DATE_FORMAT.format(new Date()) + '-'
            + UUID.randomUUID().toString().substring(0, 8) + ".log";

        if (win)
            throw new UnsupportedOperationException("Apache Ignite cannot be auto-started on Windows from IgniteCluster.startNodes(…) API.");
        else { // Assume Unix.
            int spaceIdx = script.indexOf(' ');

Метод isWindows () используется для определения, является ли ОС окнами или нет.Соответствующий снимок метода из исходного кода Ignite:

private boolean isWindows(Session ses) throws JSchException {
    try {
        return exec(ses, "cmd.exe") != null;
    }
    catch (IOException ignored) {
        return false;
    }
}

Внутренний метод exec выглядит следующим образом:

private String exec(Session ses, String cmd) throws JSchException, IOException {
    ChannelExec ch = null;

    try {
        ch = (ChannelExec)ses.openChannel("exec");

        ch.setCommand(cmd);

        ch.connect();

        try (BufferedReader reader = new BufferedReader(new InputStreamReader(ch.getInputStream()))) {
            return reader.readLine();
        }
    }
    finally {
        if (ch != null && ch.isConnected())
            ch.disconnect();
    }
}

Я взял тот же код, который использовался Ignite, и создалтестовая программа, которая будет выполнять на компьютере X и Y. Пример написанного кода был следующим:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

public class JSCHSessionUtil {

public static boolean checkIgniteStyleWindow(String username, String password, String host, int port)
        throws JSchException, IOException {

    boolean isWindows = false;

    JSch ssh = new JSch();

    Session sess = ssh.getSession(username, host, port);

    sess.setPassword(password);

    sess.setConfig("StrictHostKeyChecking", "no");

    sess.connect();

    String cmd = "cmd.exe";

    ChannelExec ch = null;

    try {
        ch = (ChannelExec) sess.openChannel("exec");

        ch.setCommand(cmd);
        ch.connect();

        try (BufferedReader reader = new BufferedReader(new InputStreamReader(ch.getInputStream()))) {

            String output = "";

            String currentLine;

            while (true) {
                currentLine = reader.readLine();
                if (currentLine == null) {
                    break;
                }
                output += currentLine;
            }

            if (output.trim().isEmpty()) {
                isWindows = false;
            }

            else {
                System.out.println("Command Output : \n"+output);
                isWindows = true;
            }

        }

    } finally {
        if (ch != null && ch.isConnected())
            ch.disconnect();
        if (sess != null && sess.isConnected())
            sess.disconnect();
    }

    return isWindows;

}

public static void main(String[] args) throws JSchException, IOException {

    boolean isWindows = checkIgniteStyleWindow("username", "password", "127.0.0.1", 22);

    if (isWindows) {
        System.out.println("\nThis is a Windows OS");
    }

    else {
        System.out.println("\nThis is a Linux OS");
    }

}

}

Вывод, наблюдаемый на двух машинах, был следующим:


Вывод для машины X

Это ОС Linux


Вывод для машины Y

Вывод команды: bash: cmd.exe: команда не найдена

Это ОС Windows

Как видно, для машины Y ошибка возвращается в виде строки, а API возвращает ноль (как для машины X).Это приводит к тому, что Ignite определяет ОС Linux как Windows.

Я хочу узнать, как навсегда решить эту проблему.

1 Ответ

0 голосов
/ 13 июня 2018

Я думаю, что проблема заключается в версиях или конфигурации программного обеспечения Machine Y.

Можете ли вы предоставить подробную информацию о том, как сконфигурирована Machine Y, и об отличиях от Machine X?Я попробовал ваш репродуктор, и он правильно определяет Linux.

Какая версия sshd используется на компьютере Y?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...