Сценарии оболочки зависают при запуске через ProcessBuilder - PullRequest
0 голосов
/ 28 мая 2020

У меня есть программа Java, в которой я запускаю сценарии оболочки. Java Пример кода:

 ProcessBuilder pb = new ProcessBuilder(cmdList);
        p = pb.start();
        p.waitFor();

Где cmdList содержит все необходимые входные аргументы для выполнения оболочки. Этот сценарий оболочки имеет внутри l oop и выполняет некоторые сценарии БД в этом l oop и выводит информацию о результатах и ​​журналы ошибок в файл.

Ниже приведен пример кода сценария оболочки:

#!/bin/bash

экспорт ПУТЬ = / apps / PostgresPlus / as9.6 / bin: / usr / local / sbin: / usr / local / bin: / usr / sbin: / usr / bin: / sbin: / bin

set -eE

##################################### ############# НАЧАЛО

TIME_ELAPSED = "" TIME_ELAPSED_IN_HOURS = "" SCRIPT_START_TIME_FORMATTED = date '+%F %T' SCRIPT_START_TIME_IN_SEC = date +%s* 1015 / * 1016_ATH_LOG_ATH_LOG_Data_log_data_log_ / "PROCESS_LOG =" $ PROCESS_LOG_BASE_PATH / purge.log "

trap 'err = $ ?; logError 2> & 1 "Ошибка при очистке. Выход со статусом $ err в строке $ LINENO: $ {BASH_COMMAND}. Пожалуйста, проверьте журналы для получения дополнительной информации." >> $ PROCESS_LOG 'ERR trap' logError 2> & 1 «Произошла ошибка во время очистки. Было получено завершение выполнения сценария оболочки из-за внешнего прерывания. Пожалуйста, проверьте журналы для получения дополнительной информации.» >> $ PROCESS_LOG; trap ERR 'INT

banner () {echo "+ --------------------------------- -------------------------------------------------- ------------- + "printf" | tput bold [% -40s tput sgr0 | \ n "" $ 1] tput setaf 2 $ 2 "echo" + ------- -------------------------------------------------- --------------------------------------- + "}

logError ( ) {printf "[ProcessId- $$] [date "+%Y-%m-%d %H:%M:%S"] tput setaf 1 tput bold [ОШИБКА] tput setaf 1% -40s tput sgr0 \ n" "$ @"}

logInfo () {printf " [ProcessId- $$] [date "+%Y-%m-%d %H:%M:%S"] tput setaf 6 bold [INFO]% -40s tput sgr0 \ n "" $ @ "} logWarn () {printf" [ProcessId- $$] [date "+%Y-%m-%d %H:%M:%S"] tput setaf 3 tput bold [ПРЕДУПРЕЖДЕНИЕ]% -40s tput sgr0 \ n "" $ @ "}

logHint () {printf" [ProcessId- $$] [date "+%Y-%m-%d %H:%M:%S"] tput setaf 5 tput sitm % -40s tput sgr0 \ n "" $ @ "}

main () {
banner" $ SCRIPT_START_TIME_FORMATTED "" Обработка запущена "| tee -a $ PROCESS_LOG logInfo "Выполнение начато в $ SCRIPT_START_TIME_FORMATTED" | tee -a $ PROCESS_LOG

set PGPASSWORD=$DB_PASSWORD
export PGPASSWORD=$DB_PASSWORD

# Call DB function for audit and category wise data purging, population of schema names
SCHEMA_NAMES_RESULT=$(psql -h $HOST_NAME -d $DB_NAME -U $DB_USER -p $DB_PORT -At -c "SELECT $COMMON_SCHEMA_NAME.purge_audit_and_populate_schema_names('$COMMON_SCHEMA_NAME', $PURGE_DATA_INTERVAL_IN_DAYS,'$SCHEMA_NAMES',$NUM_TOP_CONTRIBUTING_TENANTS)")

SCHEMA_NAMES_RESULT=$(echo "$SCHEMA_NAMES_RESULT" | sed 's/{//g; s/}//g; s/"//g' )

SCHEMA_NAMES=$(echo $SCHEMA_NAMES_RESULT | rev | cut -d"," -f2-  | rev)

#Convert comma separated string of tenants to array
SCHEMA_NAMES=($(echo "$SCHEMA_NAMES" | tr ',' '\n'))

# loop for multi schema
for element in "${SCHEMA_NAMES[@]}"
do
    logInfo "Effective tenant - $element, Script start time - $SCRIPT_START_TIME_FORMATTED" | tee -a $PROCESS_LOG

    # PGSQL call to DB function to execute purging

    logInfo "Time elapsed since script execution started - $TIME_ELAPSED" | tee -a $PROCESS_LOG
done

#logInfo "Purge completed!" | tee -a $PROCESS_LOG
logInfo "Purge execution completed successfully at `date '+%F %T'`" | tee -a $PROCESS_LOG
exit 0

}

mkdir -p $ PROCESS_LOG_BASE_PATH main «$ @»

############### ################################## END

Ниже приведены мои наблюдения с этой программой.

  1. При запуске сценария оболочки непосредственно на шпатлевке он выполняется правильно без каких-либо ошибок.
  2. При запуске сценария оболочки через java запрограммируйте следующее поведение, которое я заметил.

    а. Он зависает после определенной итерации для l oop.

    b. По мере того, как я уменьшаю количество записей в журналах из сценариев оболочки, число итераций (для l oop) продолжает расти.

    c. Когда я удалил все информационные журналы и продолжил печатать только журнал ошибок, он успешно завершился.

Может ли кто-нибудь помочь в определении причины такого поведения.

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

С уважением

Кушагра

Ответы [ 2 ]

0 голосов
/ 19 июня 2020

Спасибо, что многопоточность у меня сработала.

Для однопоточной опции не удалось выполнить skip ().

Еще раз спасибо за помощь в решении проблемы.

0 голосов
/ 29 мая 2020

Вы должны использовать потоки процессов, чтобы собственные буферы не заполнялись. Будет лучше, если вы создадите потоки для использования каждого потока. Хакерская однопоточная версия выглядит примерно так:

ProcessBuilder pb = new ProcessBuilder(cmdList);
p = pb.start();
try (InputStream in = p.getInputStream();
            InputStream err = p.getErrorStream();
            OutputStream closeOnly = p.getOutputStream()) {
    while (p.isAlive()) {                
        long skipped = in.skip(in.available()) 
                     + err.skip(err.available());
        if(skipped == 0L) {
           p.waitFor(5L, TimeUnit.MILLISECONDS);
        }
    }
} finally {
   p.destroy();
}

Способ потока работает так:

public void foo() {
    class DevNull implements Runnable {

        private final InputStream is;
        DevNull(final InputStream is) {
            is = Objects.requireNonNull(is);
        }

        public void run() {
            byte[] b = new byte[64];
            try {
                while (is.read(b) >= 0);
            } catch(IOException ignore) {
            }
        }
    }

    ExecutorService e = Executors.newCachedThreadPool();
    ProcessBuilder pb = new ProcessBuilder(cmdList);
    Process p = pb.start();
    try (InputStream in = p.getInputStream();
            InputStream err = p.getErrorStream();
            OutputStream closeOnly = p.getOutputStream()) {
        e.execute(new DevNull(in));
        e.execute(new DevNull(err));
        p.waitFor();
    } finally {
        p.destroy();
        e.shutdown();
    }
}
...