Запуск сценария оболочки из Java - не завершает задачу - PullRequest
1 голос
/ 11 декабря 2011

У меня есть Java-программа, которая должна запускать скрипт оболочки. Скрипт содержит 6 заданий, которые должны быть выполнены последовательно. Java-программа запускает скрипт и запускается (как я вижу логи). Но через 10-15 секунд выполнение останавливается, даже до того, как первая задача в сценарии оболочки завершена. Странно то, что скрипт запускается нормально, когда я запускаю его в терминале. Чтобы не рисковать зависанием программы во время выполнения скрипта, я запускаю ее в отдельном потоке. Что может быть вероятной причиной?

Java-код -

try {   
            log.info("run cmd - "+optionsRun);

            String[] cmdLine = (String[]) optionsRun.toArray(new     String[optionsRun.size()]);

            Process process = Runtime.getRuntime().exec(cmdLine);
            log.info("end run cmd " + this.getScriptPath());

//          
//          BufferedWriter writer = new BufferedWriter(new     OutputStreamWriter(process.getOutputStream()));
//          writer.write("mypwd");
//          writer.flush();
//          writer.close();


            InputStream is = process.getErrorStream();
            String error = inputStreamToStringValue(is);
            log.trace("Eventual error was : " + error);

            InputStream os = process.getInputStream();
        String output = inputStreamToStringValue(os);
            log.info("Eventual output was : " + output);

            if (error!=null & error.length()>0) {
                throw new ActionProcessingException("An error occurred when     running the script :'"+this.getScriptPath()+"' with following error message : "+error);    
            }else {
                log.info("Script run ended successfully.");
            }

И скрипт оболочки выглядит так -

#!/bin/sh
# ./publish <path-to-publish-home-folder> <workspace_id> <start_date> <end_date>
# ./publish <path-to-publish-home-folder> 100011 2010-01-06-12:00:00-CET     2012-01-14-19:00:00-CET

rm -f $1/publish.log
echo 'Start publish' >> $1/publish.log
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 >> $1/publish.log

# lancement de l'export RDF du domaine
cd $1/1-export-domain
echo "Starting export domain with the command - ./export.sh $2" >> $1/publish.log
./export.sh $2

# lancement de l'export des translations du domaine
cd $1/2-export-trans
echo "Starting export domain(translated) with the command - ./export.sh $2" >>         $1/publish.log
./export.sh $2
.....
.....
a couple of more steps like 1 and 2
....

Заранее спасибо,

Ответы [ 2 ]

1 голос
/ 11 декабря 2011

Я не могу быть уверен, я думаю, проблема в вашем методе inputStreamToStringValue(is). Он читает STDERR и блокирует чтение. Когда ему нечего читать из STDERR, но процесс еще не завершен, вы будете заблокированы навсегда.

Я бы порекомендовал вам использовать ProcessBuilder:

    ProcessBuilder b = new ProcessBuilder();
    b.redirectErrorStream(true);

Теперь вы можете читать STDIN и STDERR вместе.

Если вы все еще хотите прочитать их отдельно, у вас есть 2 решения.

Сначала делайте так, как вы делаете сейчас, но не блокируйте чтение, т. Е. Вызывайте in.available() перед каждым вызовом чтения, а затем читайте только количество байтов, которые были ранее доступны.

Второй способ - использовать перенаправление оболочки. Запустите ваш скрипт и перенаправьте его STDOUT и STDERR во временные файлы. Затем подождите, пока ваш процесс не прекратится, и затем прочитайте из файлов. Я лично считаю, что это решение проще и надежнее.

Удачи.

1 голос
/ 11 декабря 2011

Я не уверен, но я порекомендую две ссылки, которые могут помочь вам разобраться.

Первый - очень старый, о Runtime.exec():

http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html

Второй - это ProcessBuilder, новый класс, предназначенный для замены Runtime.exec():

http://www.java -tips.org / Java-се-советы / java.util / из-Runtime.exec к processbuilder.html

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