Я предлагаю изменить rcu.bat
на:
@REM Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
@REM Wrapper script to launch Oracle home base rcu script
@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
SET "INTERNAL_SCRIPT=rcu_internal.bat"
SET "WLS_ORACLE_HOME=C:\Oracle\Middleware\Oracle_Home"
SET "INTERNAL_SCRIPTPATH="
IF EXIST "%WLS_ORACLE_HOME%" (
SET "INTERNAL_SCRIPTPATH=%WLS_ORACLE_HOME%\oracle_common\bin\"
) ELSE (
SET "INTERNAL_SCRIPTPATH=%~dp0"
)
CALL "%INTERNAL_SCRIPTPATH%%INTERNAL_SCRIPT%" %*
ENDLOCAL
Каждая строка аргумента, ссылающаяся на файл или папку, должна быть заключена в двойные кавычки, чтобы она работала даже с именем файла / папки без или с путем содержит пробел или один из этих символов &()[]{}^=;!'+,`~
.
Выражение %~dp0
расширяется до полного пути к пакетному файлу, который всегда заканчивается обратным символом sh. Поэтому %~dp0
никогда не следует объединять прямо или косвенно, как это делается здесь через переменную окружения INTERNAL_SCRIPTPATH
с дополнительным обратным символом sh с именем файла / папки. В противном случае \\
приведет к расширенному пути, который Windows необходимо исправить до одного \
, прежде чем он передаст имя файла / папки с путем к файловой системе. По этой причине добавляется обратная строка sh в конце %WLS_ORACLE_HOME%\oracle_common\bin
и удаляется обратная строка sh в строке аргумента команды CALL .
Использование команды SETLOCAL просто приводит к выталкиванию текущего пути к каталогу в стеке и указателя на текущий список переменных среды. Состояние расширений команд и состояние отложенного расширения переменных среды не изменяются при использовании просто SETLOCAL без каких-либо параметров. Таким образом, среда выполнения будет определена вне пакетного файла. Это не хорошо. Пакетный файл не должен зависеть от того, какие другие приложения или пакетные файлы установлены в качестве среды выполнения. Этот пакетный файл требует, чтобы включенные расширения команд и отключенное отложенное расширение переменной среды работали независимо от того, какой путь указан в полном пакете. Поэтому команда SETLOCAL используется с двумя необязательными аргументами для определения требуемой среды выполнения. Пожалуйста, прочитайте этот ответ для получения подробной информации о командах SETLOCAL и ENDLOCAL .
Я рекомендую прочитать мои ответы на Как установить переменные окружения с пробелами? и Почему нет строкового вывода с 'echo% var%' после использования 'set var = text' в командной строке? , чтобы понять, почему рекомендуется заключать в оболочку строка аргумента variable=value
для команды SET в двойных кавычках с первым "
слева от имени переменной, а не в начале значения переменной. Это имеет большое значение.
Использование SET INTERNAL_SCRIPTPATH="%WLS_ORACLE_HOME%\oracle_common\bin"
приводит к командной строке CALL %INTERNAL_SCRIPTPATH%\%INTERNAL_SCRIPT% %*
в расширенной командной строке:
CALL "C:\Oracle\Middleware\Oracle_Home\oracle_common\bin"\rcu_internal.bat %*
Первый аргумент команды CALL не указано правильно. Второй "
должен находиться в конце строки аргумента после .bat
, а не где-то посередине. Приведенный выше код приводит к всегда 100% правильной строке первого аргумента для команды CALL .
Я предлагаю для rcu_internal.bat
следующий код:
@rem Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
@echo off
setlocal EnableExtensions DisableDelayedExpansion
@rem ORACLE_HOME is the parent directory of the "oracle_common\bin"
@rem directory where the rcu script is located.
@rem Set the ORACLE_HOME relative to this script...
for %%I in ("%~dp0..\..") do set "ORACLE_HOME=%%~fI"
@rem Make sure the ORACLE_HOME path does not end with a
@rem backslash even on being the root directory of a drive.
if "%ORACLE_HOME:~-1%" == "\" set "ORACLE_HOME=%ORACLE_HOME:~0,-1%"
@set "LOG_LOCATION_VAR="
@set "LOG_LEVEL_VAR="
@set "LOG_NAME_VAR="
@set "LOG_FORMATTER_VAR="
@set "TIMESTAMP_LOG_DIR_VAR="
@set "PRETTY_NAME_VAR="
@set "OPERATION1_NAME_VAR="
@set "OPERATION2_NAME_VAR="
@set "OPERATION1_CMDLINE_VAR="
@set "OPERATION2_CMDLINE_VAR="
@set "DBMS_OUTPUT_IN_SEPARATE_FILE_VAR="
@set "RCU_PRODUCT_NAME_VAR="
@set "RCU_TWO_PHASE_VAR="
@set "ENABLE_JAVADB_VAR="
@if defined RCU_TIMESTAMP_LOG_DIR set "TIMESTAMP_LOG_DIR_VAR=-DRCU_TIMESTAMP_LOG_DIR=%RCU_TIMESTAMP_LOG_DIR%"
@if not defined RCU_TIMESTAMP_LOG_DIR set "TIMESTAMP_LOG_DIR_VAR=-DRCU_TIMESTAMP_LOG_DIR=true"
@if defined RCU_LOG_LOCATION set "LOG_LOCATION_VAR=-DRCU_LOG_LOCATION="%RCU_LOG_LOCATION%" "
@if defined RCU_LOG_LEVEL set "LOG_LEVEL_VAR=-DRCU_LOG_LEVEL=%RCU_LOG_LEVEL%"
@if not defined RCU_LOG_LEVEL set "LOG_LEVEL_VAR=-DRCU_LOG_LEVEL=NOTIFICATION"
@if defined RCU_LOG_NAME set "LOG_NAME_VAR= -DRCU_LOG_NAME="%RCU_LOG_NAME%""
@if defined CU_LOG_FORMATTER set "LOG_FORMATTER_VAR= -DRCU_LOG_FORMATTER=%RCU_LOG_FORMATTER%"
@if defined USE_PRETTY_NAMES set "PRETTY_NAME_VAR= -DUSE_PRETTY_NAMES=%USE_PRETTY_NAMES%"
@if defined RCU_OPERATION1_NAME set "OPERATION1_NAME_VAR= -DRCU_OPERATION1_NAME=%RCU_OPERATION1_NAME%"
@if defined RCU_OPERATION2_NAME set "OPERATION2_NAME_VAR= -DRCU_OPERATION2_NAME=%RCU_OPERATION2_NAME%"
@if defined RCU_OPERATION1_CMDLINE set "OPERATION1_CMDLINE_VAR= -DRCU_OPERATION1_CMDLINE=%RCU_OPERATION1_CMDLINE%"
@if defined RCU_OPERATION2_CMDLINE set "OPERATION2_CMDLINE_VAR= -DRCU_OPERATION2_CMDLINE=%RCU_OPERATION2_CMDLINE%"
@if defined RCU_DBMS_OUTPUT_IN_SEPARATE_FILE set "DBMS_OUTPUT_IN_SEPARATE_FILE_VAR= -DRCU_DBMS_OUTPUT_IN_SEPARATE_FILE=%RCU_DBMS_OUTPUT_IN_SEPARATE_FILE%"
@if defined RCU_PRODUCT_NAME set "RCU_PRODUCT_NAME_VAR= -DRCU_PRODUCT_NAME=%RCU_PRODUCT_NAME%"
@if defined USE_TWO_PHASE_RCU set "RCU_TWO_PHASE_VAR= -DUSE_TWO_PHASE_RCU=%USE_TWO_PHASE_RCU%"
@if defined ENABLE_JAVADB set "ENABLE_JAVADB_VAR= -DENABLE_JAVADB=%ENABLE_JAVADB%"
@set "RCU_ENV_VARS=%LOG_LOCATION_VAR%%LOG_LEVEL_VAR%%LOG_NAME_VAR%%LOG_FORMATTER_VAR% %TIMESTAMP_LOG_DIR_VAR%%PRETTY_NAME_VAR%%OPERATION1_NAME_VAR%%OPERATION2_NAME_VAR%%OPERATION1_CMDLINE_VAR%%OPERATION2_CMDLINE_VAR%%DBMS_OUTPUT_IN_SEPARATE_FILE_VAR%%RCU_PRODUCT_NAME_VAR%%RCU_TWO_PHASE_VAR%%ENABLE_JAVADB_VAR%"
@set "OH=%ORACLE_HOME%"
@set "RCU_HOME=%ORACLE_HOME%\oracle_common"
@set "OH_J2EE=%ORACLE_HOME%\j2ee\home"
@set "JLIB_DIR=%RCU_HOME%\jlib"
@set "JRE_DIR=%OH%\jdk\jre"
@set "RCUHELP_FILE=rchlp.jar"
if not defined LANG (
for /F "skip=1 tokens=3" %%G in ('%SystemRoot%\System32\reg.exe query "HKLM\System\CurrentControlSet\Control\Nls\Language" /v Default') do (
if "%%G" == "0407" set "RCUHELP_FILE=rchlp_de.jar" & goto MoreVars
if /I "%%G" == "040c" set "RCUHELP_FILE=rchlp_fr.jar" & goto MoreVars
if /I "%%G" == "040a" set "RCUHELP_FILE=rchlp_es.jar" & goto MoreVars
if "%%G" == "0410" set "RCUHELP_FILE=rchlp_it.jar" & goto MoreVars
if "%%G" == "0411" set "RCUHELP_FILE=rchlp_ja.jar" & goto MoreVars
if "%%G" == "0412" set "RCUHELP_FILE=rchlp_ko.jar" & goto MoreVars
if "%%G" == "0416" set "RCUHELP_FILE=rchlp_pt_BR.jar" & goto MoreVars
if "%%G" == "0804" set "RCUHELP_FILE=rchlp_zh_CN.jar" & goto MoreVars
if "%%G" == "0404" set "RCUHELP_FILE=rchlp_zh_TW.jar" & goto MoreVars
)
) else (
echo %LANG%|%SystemRoot%\System32\find.exe /C /I "de" >nul && ( set "RCUHELP_FILE=rchlp_de.jar" & goto MoreVars )
echo %LANG%|%SystemRoot%\System32\find.exe /C /I "fr" >nul && ( set "RCUHELP_FILE=rchlp_fr.jar" & goto MoreVars )
echo %LANG%|%SystemRoot%\System32\find.exe /C /I "es" >nul && ( set "RCUHELP_FILE=rchlp_es.jar" & goto MoreVars )
echo %LANG%|%SystemRoot%\System32\find.exe /C /I "it" >nul && ( set "RCUHELP_FILE=rchlp_it.jar" & goto MoreVars )
echo %LANG%|%SystemRoot%\System32\find.exe /C /I "ja" >nul && ( set "RCUHELP_FILE=rchlp_ja.jar" & goto MoreVars )
echo %LANG%|%SystemRoot%\System32\find.exe /C /I "ko" >nul && ( set "RCUHELP_FILE=rchlp_ko.jar" & goto MoreVars )
echo %LANG%|%SystemRoot%\System32\find.exe /C /I "pt_BR" >nul && ( set "RCUHELP_FILE=rchlp_pt_BR.jar" & goto MoreVars )
echo %LANG%|%SystemRoot%\System32\find.exe /C /I "zh_CN" >nul && ( set "RCUHELP_FILE=rchlp_zh_CN.jar" & goto MoreVars )
echo %LANG%|%SystemRoot%\System32\find.exe /C /I "zh_TW" >nul && ( set "RCUHELP_FILE=rchlp_zh_TW.jar" & goto MoreVars )
)
:MoreVars
@set "RCU_CLASSPATH=%JLIB_DIR%\rcu.jar"
@set "HELPSET_CLASSPATH=%JLIB_DIR%\%RCUHELP_FILE%"
@set "PATH=%RCU_HOME%\bin;%PATH%"
@set "CLASSPATH=%RCU_CLASSPATH%;%HELPSET_CLASSPATH%"
rem If no parameter passed, RCU should start run as silent mode.
if not defined JAVA_HOME (
set "JAVA_HOME=%JRE_DIR%"
) else (
if exist "%JAVA_HOME%\jre\bin\javaw.exe" set "JAVA_HOME=%JAVA_HOME%\jre"
)
if not exist "%JAVA_HOME%\bin\java.exe" (
if exist "%RCU_HOME%\..\oui\bin\getVariable.cmd" (
@rem INVOKE SCRIPT TO SET THE JAVA_HOME
call "%RCU_HOME%\..\oui\bin\getVariable.cmd" JAVA_HOME JAVA_HOME
)
)
if not exist "%JAVA_HOME%\bin\java.exe" (
if exist "%RCU_HOME%\jdk\" (
@rem Set the JAVA_HOME to oracle_common\jdk
set "JAVA_HOME=%RCU_HOME%\jdk"
)
)
for %%I in ("%JAVA_HOME%") do set "JAVA_HOME=%%~fI"
if not exist "%JAVA_HOME%\bin\java.exe" (
echo Unable to locate Java at the following location: "%JAVA_HOME%\bin\java".
echo Please set the correct value for JAVA_HOME or ORACLE_HOME and try again.
@rem Command endlocal is implicit executed by cmd.exe
exit /B 1
)
if not "%~1" == "" (
"%JAVA_HOME%\bin\java.exe" %RCU_JAVA_OPTIONS% -DRCU_HOME="%RCU_HOME%" -DSQLPLUS_HOME="%OH%" -DORACLE_HOME="%OH%" %RCU_ENV_VARS% -DLAUNCH_MODE=%LAUNCH_MODE% -mx128m -classpath "%CLASSPATH%" oracle.sysman.assistants.rcu.Rcu -lockSchemas false %*
) else (
"%JAVA_HOME%\bin\java.exe" -DRCU_HOME="%RCU_HOME%" -DSQLPLUS_HOME="%OH%" -DORACLE_HOME="%OH%" -DRANDOMIZE_PASSWORDS=true %RCU_ENV_VARS% -DLAUNCH_MODE=%LAUNCH_MODE% -mx128m %RCU_JAVA_OPTIONS% -classpath "%CLASSPATH%" oracle.sysman.assistants.rcu.Rcu
)
endlocal
Примечание: Надеюсь, этот исправленный пакетный файл работает, потому что я не смог его протестировать.
Сообщение об ошибке вызвано %JAVA_HOME%\bin\java
, не заключенным в "
в конце пакетный файл.
Быстрее и безопаснее проверять наличие переменной среды, используя if defined
вместо if not "variable" == ""
, если расширения команд включены, как было подтверждено в третьей строке этого пакетного файла , if not defined
лучше, чем if "variable" == ""
.
Переменные среды, которые в конечном итоге создают RCU_ENV_VARS
, определяются таким образом, чтобы избежать двух или более пробелов в командной строке между аргументами, если не определены одна или несколько опций на выполнение этого скрипта. Больше чем один пробел между опциями не является проблемой, но выглядит лучше иметь только один пробел между опциями, и это может быть легко достигнуто, как это видно здесь.
Ключ реестра ControlSet001
должен быть никогда не используется в запросах реестра. Нет никаких гарантий, что этот раздел реестра существует вообще. Существует CurrentControlSet
, который существует всегда. У меня есть P C, на котором ControlSet002
- последний известный исправный набор управления, ControlSet003
- текущий набор управления, а ControlSet001
вообще не существует, как определено автоматически Windows в соответствии со значениями в HKLM\System\Select
.
Не используйте [
и ]
при сравнении двух строк. Они не имеют особого значения для Windows командного процессора. Более безопасно использовать "
для двух строк для сравнения с условием IF . Но учтите, что IF не удаляет "
из строк перед выполнением сравнения строк. Таким образом, если строка с левой стороны заключена в "
, строка с правой стороны также должна быть заключена в "
.
Оператор сравнения строк - ==
, а не EQU
. EQU
в основном для сравнения двух целочисленных значений и интерпретируется как оператор сравнения строк, только если одно из двух чисел для сравнения не может быть успешно преобразовано в 32-разрядное целочисленное значение со знаком, как при заключении двух строк в квадратные скобки или двойные кавычки , См. Также мой ответ на Символ, эквивалентный NEQ, LSS, GTR и т. Д. c. в Windows пакетных файлах для очень подробного объяснения, как сравнение строк выполняется командой IF .
Всегда должен быть пробел слева и пробел справа ==
для 100% правильного синтаксиса, как в if not "%~1" == ""
, для которого cmd.exe
не нужно автоматически вносить c исправления, как в if not "%~1"==""
. Примененную автоматическую коррекцию c можно увидеть при отладке командного файла при просмотре командной строки IF , действительно выполненной после анализа и обработки командной строки с помощью IF состояние и весь командный блок (ы). Что ж, для отладки командного файла все @
контрпродуктивны, за исключением первых двух.