Programatically отвечают на подсказку y/n с “y” в человечности 16.04 от Java .jar файл

Я не уверен, отправить ли это на StackOverflow или AskUbuntu, на основе моего текущего понимания, что проблема заключается в моем отсутствии понимания прав и полномочий/обработки выполнения в рамках Ubuntu вместо подхода программирования Java, следовательно я думал, что это было местом для выяснения.

В то время как успешное выполнение терминальных команд генерировало в проекте Java, который компилируется в a commandUbuntu.jar, Я нашел команду, которая не выполняется, поскольку я думал, что она будет. Я установил taskwarrior 2.5, и я пытаюсь создать пользовательский определяемый пользователем атрибут (UDA) с помощью Java. Команда (команды), is/are:

printf 'y\n' | sudo task config uda.newTestSort.type numeric
printf 'y\n' | sudo task config uda.newTestSort.label nTSort

воспроизведение Taskwarrior может быть установлено с:

sudo apt update && sudo apt upgrade
sudo apt install task

Можно добавить 2 задачи с:

task add this is the test task one description
task add test task two

Присоединенный MWE, созданный, чтобы просто выполнить 2 команды, он может быть скомпилирован в .jar в затмении путем нажатия: file>export>select node Java>Select Runnable JAR file>Click next>Launch Configuration:CommandLinux - LearnToSayYesToLinux>Chose an export location and name, e.g.c:/commandLinux.jar'> Пакет потребовал, чтобы библиотеки в сгенерированный JAR> Нажали Finish.

Затем это может быть выполнено в Ubuntu с:

cd /mnt/c/commandLinux.jar
java -jar commandLinux.jar

MWE:

package learnToSayYesToLinux;

import java.io.*;
import java.util.ArrayList;


public class CommandLinux {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //Test create a custom UDA
        createUDA("abstractSort","aSort","numeric");

        System.exit(0);
    }

    /**
     * Method creates a taskwarrior user defined Attribute if the data type is correct
     * Thows error datatype is not correct.
     * TODO: write proper exception
     * @param udaName
     * @param label
     * @param type
     */
    private static void createUDA(String udaName, String label,String type) {
        char vd = (char)124; //vertical dash: |
        char bs = (char)92; //backslash: \      
        String[] commands = new String[2];

        //Check if the datatype is correct for taskwarrior:
        if (type.equals("numeric") || type.equals("string") || type.equals("date") || type.equals("duration")){
            commands[0]="printf 'y"+bs+"n' "+vd+" sudo task config uda."+udaName+".type "+type;
            commands[1]="printf 'y"+bs+"n' "+vd+" sudo task config uda."+udaName+".label "+ label;          

            runCommands(commands[0], false);
            runCommands(commands[1], false);

            System.out.println("Ran:"+commands[0]);
            System.out.println("Ran:"+commands[1]);
            //Trow exception if the datatype is not correct.
        }else {
            try {
                throw new Exception();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }


    public static ArrayList<ArrayList<String>> runCommands(String command,boolean ignoreOutput) {

        String s = null;
        String outputLines=null;
        ArrayList<String> goodExecutionOutput=new ArrayList<String>();
        ArrayList<String> errorExecutionOutput=new ArrayList<String>();
        ArrayList<ArrayList<String>> returnLists = new ArrayList<ArrayList<String>>();

        try {
            // run the Unix "task nice0" command
            Process p = Runtime.getRuntime().exec(command);
            BufferedReader brGood = new BufferedReader(new InputStreamReader(p.getInputStream()));
            BufferedReader brError = new BufferedReader(new InputStreamReader(p.getErrorStream()));

            // get output
            if (!ignoreOutput) {
                while ((s = brGood.readLine()) != null) {
                    System.out.println("Adding:"+s);
                    goodExecutionOutput.add(s);
                }

                // get the error message
                while ((s = brError.readLine()) != null) {
                    errorExecutionOutput.add(s);
                }   
            }

        }
        catch (IOException e) {
            System.out.println("Error: ");
            e.printStackTrace();
            System.exit(-1);
        }

        //Merge outputLists and return
        returnLists.add(goodExecutionOutput);
        returnLists.add(errorExecutionOutput);
        return returnLists;
    }   
}

Результат, Если команда выполняется .jar файл это возвращается:

$ ationAndSystems/Taskwarrior/customSortServerV4 Java - банка testCommand.jar

Adding:'y
Adding:'
Adding:'y
Adding:'
Ran:printf 'y\n' | sudo task config uda.newTestSort.type numeric
Ran:printf 'y\n' | sudo task config uda.newTestSort.label nTSort

Если я выполняю команду вручную, она возвращается:

$ printf 'y\n' | sudo task config uda.newTestSort.type numeric
Are you sure you want to change the value of 'uda.newTestSort.type' from 'numeric' to 'numeric'? (yes/no) Config file /home/a/.taskrc modified.
$ printf 'y\n' | sudo task config uda.newTestSort.label nTSort
Are you sure you want to change the value of 'uda.newTestSort.label' from 'nTSort' to 'nTSort'? (yes/no) Config file /home/a/.taskrc modified.

Интерпретация/тестирование этого результата обсуждена при "Проверке".

Попытка результата 2, Как предложено в комментариях: Изменение строк 36 и 37 из MWE к:

commands[0]="yes yes "+vd+" sudo task config uda."+udaName+".type "+type;
commands[1]="yes yes "+vd+" sudo task config uda."+udaName+".label "+ label;

Приводит к бесконечному повторению (пока Переполнение стека не происходит):

Adding:yes | sudo task config uda.testSortA.type numeric

Если я установил boolean ignoreOutput ко лжи, когда я называю метод runCommands() это возвращается:

Ran:yes yes | sudo task config uda.testSortA.type numeric
Ran:yes yes | sudo task config uda.testSortA.label tSortA

После проверки я пришел к заключению, что эта команда эффективно не добавила новый UDA.

Проверка, Если я вручную ввожу их в Ubuntu 16.04, они хорошо работают. Я тестирую его путем ввода:

sudo task 2 modify newTestSort:29

Если UDA еще не будет существовать в taskwarrior, то он интерпретирует тот оператор как: "измените описание задачи 2". Однако, если UDA newTestSort действительно существует и имеет тип numeric это установит задачу 2 uda newTestSort (маркированный nTSort) к 2. Эти два результата читаются в выводе команды sudo task 2, сначала, прежде чем создание UDA для проверки UDA еще не существует путем проверки, было ли описание задачи изменено на newTestSort:29 и второй раз, после ввода 2 упомянутых выше команд создания UDA, для проверки UDA действительно создается путем проверки если новый UDA nTSortперечислен со значением 29.

Вопрос: Как я автоматически отвечаю на "да" на подсказку ниже, не создавая дополнительный файл, с помощью Java?

Вы уверены, что хотите изменить значение 'uda.newTestSort.type' от 'числового' до 'числового'? (да/нет) Файл конфигурации/home/a/.taskrc измененный.

Текущее понимание ответа lesmana объясняет, что вертикальный тире соединяет вход для того, что является правильным из тире с выводом того, что оставляют тире. Это говорит что вывод yes бесконечный поток yпоэтому после того, как команда просит вход, это передало бы их потоком y- s в тот вопрос. Я в настоящее время не понимаю, почему это прекратило бы делать это.

Другое сомнение, которое я имею, состоит в том, что команда могла бы быть интерпретирована по-другому по сравнению с тем, когда она вручную вводится из-за способа, которым она дана от a .jar файл к процессу вместо вводимого в терминал. Это могло бы вызвать для другой интерпретации/значения |. Я изучаю, как команды интерпретируются от a .jar файл человечностью.

Дополнительно я проверил, было ли это проблемой с правами что .jar файл имеет, таким образом, я пытался выполнить предложенную команду попытки 2 с:

sudo java -jar commandUbuntu.jar

Но после проверки я пришел к заключению, что это не допускало добавление нового UDA от Java.

0
задан 8 February 2019 в 08:19

1 ответ

Решение сущности проблемы было отправлено Pepe ниже принятого ответа в: https://stackoverflow.com/questions/4157303/how-to-execute-cmd-commands-via-java

С моим текущим пониманием команда может иметь ввод и вывод. Вертикальный тире | используется для передачи по каналу в терминале. Так, например, предположите, что у Вас есть команда, которая генерирует вывод, например yes, затем тот вывод может быть связан непосредственно с входом другого command*. Предположим, что другая команда является командой, которую я пытался выполнить, который имеет вход из-за вопроса:

Вы уверены, что хотите изменить значение 'uda.newTestSort.type' от 'числового' до 'числового'? (да/нет) Файл конфигурации/home/a/.taskrc измененный.

Таким образом, когда, например:

printf 'yes\n' | task config uda.testSortC.type numeric

вводится как команда в нормальном терминале, это вывод команды yes передается по каналу в команду: task config uda.testSortC.type numeric, который отвечает на вопрос выше. Я в настоящее время понимаю, что тем вопросом самим является вывод той команды, но просто сообщение, которое сопровождает вход той команды. Получение входа yes завершает выходной поток большого количества yesи команда выполняется, как она должна с a yes вход.

Теперь, когда можно назвать процесс в Java с:

Process p = Runtime.getRuntime().exec(command);

.exec(command) не точно то же как ввод команды в Terminal^. Одно свойство различия - то, что передача по каналу не функционирует, если указано в команде, что Вы записали в Java с помощью вертикальной строки |. Применять понятие передачи по каналу Вас должно явно получить вход команды и явно включить вывод другой команды в него. Это может быть сделано со следующим кодом в методе runCommands():

Process p;
try {
    p = Runtime.getRuntime().exec(command);
    new Thread(new SyncPipe(p.getErrorStream(), System.err)).start();
    new Thread(new SyncPipe(p.getInputStream(), System.out)).start();
    PrintWriter stdin = new PrintWriter(p.getOutputStream());
    stdin.println("yes");
    // write any other commands you want here
    stdin.close();
    int returnCode = p.waitFor();
    System.out.println("Return code = " + returnCode);

} catch (IOException | InterruptedException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

И путем добавления следующего класса к проекту:

class SyncPipe implements Runnable
{
public SyncPipe(InputStream istrm, OutputStream ostrm) {
      istrm_ = istrm;
      ostrm_ = ostrm;
  }
  public void run() {
      try
      {
          final byte[] buffer = new byte[1024];
          for (int length = 0; (length = istrm_.read(buffer)) != -1; )
          {
              ostrm_.write(buffer, 0, length);
          }
      }
      catch (Exception e)
      {
          e.printStackTrace();
      }
  }
  private final OutputStream ostrm_;
  private final InputStream istrm_;
}

Где, насколько я в настоящее время понимаю, p содержит "получение" процесса, который выполняет команду, затем класс SyncPipe на самом деле канал. Вход процесса p подключен к каналу с помощью a thread и затем новая команда, которая генерирует вывод, выполняется stdin. Так или иначе канал затем получает тот поток вывода и включает его во входной поток первой команды. Это решение сделано максимально явным, чтобы вынудить меня объяснить понятия, как таковые, оно могло бы все еще содержать ошибки, если так, комментируйте/редактируйте.

* (если та команда имеет вход. Я в настоящее время не знаю, имеют ли все команды исходные данные, или в противном случае я в настоящее время не знаю что happends если бесконечный поток вывода, например, yes передается по каналу в команду без входа),

^I в настоящее время точно не знайте, каково различие, оно требует, чтобы у меня было более глубокое понимание того, какой happends в терминале и как обрабатываются команды и как выполняются процессы.

0
ответ дан 26 October 2019 в 08:04

Другие вопросы по тегам:

Похожие вопросы: