2009-09-22 2 views
1

У меня есть сценарий (точнее, скрипт KSH), который загружает 3 файла с FTP-сервера с помощью команды curl.Странное поведение при запуске скрипта bash из java-программы

Когда я запускаю вручную свой скрипт, т. Е. Выполнив команду ./ftp_download.sh XXX (XXX - параметры для скрипта), загрузка будет выполнена правильно.

Как я хочу, чтобы запустить сценарий из программы Java, я сделал короткий класс Java, который содержит именно это:

public class Run { 

    private static final String CMD = "/.../sh/ftp_download.sh XXX"; 

    public static void main(String[] args) { 
     System.out.println("========================================================"); 
     BufferedReader out = null; 
     try { 
      long startTime = System.currentTimeMillis(); 
      String strOutputline; 
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
      Date now = new Date(); 
      Process processus = Runtime.getRuntime().exec(CMD); 
      out = new BufferedReader(new InputStreamReader(processus.getInputStream())); 
      while ((strOutputline = out.readLine()) != null) { 
       now.setTime(System.currentTimeMillis()); 
       System.out.println(sdf.format(now) + " " + strOutputline); 
      } 
      System.out.println("RESULT : " + processus.waitFor()); 
      out.close(); 
      processus.destroy(); 
      long duration = System.currentTimeMillis() - startTime; 
      System.out.println("Duration : " + duration); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       if (out != null) { 
        out.close(); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
     System.out.println("========================================================"); 
     System.out.println("END"); 
    } 

} 

Однако, когда я запускаю эту простую программу, она просто зависает после точно 3m20 (эта продолжительность всегда одна и та же, даже если я запускаю программу Java несколько раз). Замораживая, я имею в виду, что программа Java все еще работает (curl процесс тоже), но загруженный файл не растет больше (т.е. curl не продолжает загружать любые данные) ...

Таким образом, я никогда не получаю линия RESULT: xxx, напечатанная на консоли ...

Что может объяснить это странное поведение?

ps: В ближайшее время я изменю свой проект, чтобы загрузить эти файлы, используя библиотеку commons-net Apache, но я хочу, чтобы это странное поведение было понято! действительно!


Благодаря derobert, я, наконец, удалось решить эту проблему. Некоторые пояснения: в нормальном режиме curl отображает информацию о ходе (таблица с объемом загруженных данных, оставшееся время и т. Д.). По прошествии некоторого времени буфер, кажется, полностью заполнен, и поэтому процесс зависает ...

+0

Вы можете попробовать strace на java-процессе и посмотреть, где его ждет/висит. – vpram86

+0

Чувак, запуск скрипта bash из java-программы * IS * странное поведение :) Извините, не смог удержаться ... –

ответ

13

Я не человек Java, а скорее Unix, и одно кажется очевидным: буфер на любом уровне или stderr заполняется, а затем завиток блокируется.

Это работает, если вы запускаете завиток в бесшумном режиме, как в curl --silent?

Проверка документации Java, похоже, вы также хотите использовать getErrorStream в дополнение к getInputStream.

+0

Я уведомил, что если я не использую атрибут «-v» (verbose), я выиграю За 20 секунд до замораживания процесса.Я попробую с опцией «-s» (без звука) ... – romaintaz

+0

+1 для отличного диагноза – janko

+0

Безмолвный режим действительно решает мою проблему! Большое спасибо... – romaintaz

1

От Process:

Родительский процесс использует эти потоки, чтобы питать вход, чтобы и получить выход из подпроцесса. Поскольку некоторые собственные платформы обеспечивают ограниченный размер буфера для стандартных потоков ввода и вывода, неспособность оперативно записать входной поток или прочитать выходной поток подпроцесса, может привести к блокировке подпроцесса и даже к взаимоблокировке.

Так что вам нужно, чтобы получить standard output и error output процесса и читать их, пока они не пустой (т.е. возвращение -1 на read()).

Смежные вопросы