我正在尝试将bash脚本转换为批处理,但是在此问题上遇到了麻烦。该脚本在后台运行Java服务器,等待5秒钟,然后使用exitcode退出。但是批量时,我无法...
runserver.sh
java -jar java_server.jar &
pid=$!
sleep 5
kill -0 $pid
cmdStatus=$?
if [ $cmdStatus -ne 0 ]
then
exit 1
fi
exit 0
runserver.bat
@echo off
set EXITCODE=0
start /b java -jar java_server.jar
timeout /t 5
for /f "tokens=1 delims= " %%i in ('jps -m ^| findstr java_server') do set PID=%%i
IF "%PID" == "" (
set EXITCODE=1
)
EXIT EXITCODE
但是如果我运行上述批处理脚本,我将永远无法放弃Java进程,并且它永远不存在
答案 0 :(得分:0)
批处理文件代码中的第一个错误是在%
行中缺少IF "%PID" == ""
来真正比较双引号中包含的环境变量PID
与字符串""
的值。因此正确的是IF "%PID%" == ""
。有关字符串比较的更多详细信息,请参见Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files。
第二个错误是未在环境变量%
的最后一个命令行EXIT EXITCODE
上两次使用EXITCODE
来引用其值,该值将正确地写为EXIT %EXITCODE%
。
但是批处理文件最好编写如下:
@echo off
cd /D "%~dp0"
start "" /B javaw.exe -jar "%~dp0java_server.jar"
%SystemRoot%\System32\timeout.exe /T 5 /NOBREAK >nul
jps -m 2>nul | %SystemRoot%\System32\findstr.exe /L "java_server" >nul
批处理文件首先使该批处理文件的目录成为当前目录,因为java_server.jar
最有可能在批处理文件的目录中。 %~dp0
扩展到批处理文件参数0的驱动器和路径。用%~dp0
引用的文件路径始终以反斜杠结尾,反斜杠是Windows上的目录分隔符,在将此字符串与文件或文件夹名称连接时应考虑在内。仅当批处理文件存储在使用UNC path访问的网络资源上时,命令 CD 才会失败,因为Windows默认情况下会阻止使用UNC路径而不是驱动器号引用的目录成为当前目录是出于向下兼容性的原因,因为许多控制台应用程序无法正常工作,并且当前目录不在具有驱动器号的驱动器上。
命令 START 将第一个双引号字符串解释为在单独的命令过程中运行Windows控制台应用程序时打开的控制台窗口的标题。在这种情况下,尽管/B
是Windows控制台应用程序,但由于使用了选项java.exe
,因此没有打开任何控制台窗口。因此,建议像启动Windows GUI应用程序一样,以""
作为窗口标题明确指定一个空字符串,以避免将任何其他双引号参数字符串都解释为可选窗口标题。
选项/B
被解释为背景。大多数人认为启动的应用程序与当前的命令过程分离。对于Windows GUI应用程序,这是正确的,但对于java.exe
之类的控制台应用程序则不是。当前命令进程的句柄 STDIN 与已启动的控制台应用程序的 STDIN 绑定。此外,已启动应用程序的句柄 STDOUT 和 STDERR 的输出将重定向到正在运行的命令进程的控制台窗口,但该窗口将立即继续执行批处理脚本。选项/B
意味着仅在不打开新控制台窗口的情况下与当前命令进程并行运行控制台应用程序,而不是在与运行命令进程完全分离的应用程序中运行。
在这种情况下,该解决方案非常简单,因为还有javaw.exe
,这是Windows版本的 Java ,旨在从后台启动Java应用程序,使其完全脱离后台运行。< / p>
一般使用的批处理文件最适合在指定所有具有完整限定文件名的文件时使用,即具有完整路径,文件名和文件扩展名。 Java 可执行文件可以安装在任何地方,因此无法在批处理文件中指定该可执行文件的文件夹路径。 Windows命令处理器必须在当前目录中或 local 环境变量javaw
的文件夹列表中的任何文件夹中找到可执行文件PATH
。但是至少可以指定具有文件扩展名javaw
的可执行文件.exe
,因为此文件扩展名是众所周知的。
假定该文件与批处理文件存储在同一目录中,则使用完整路径指定JAR文件java_server.jar
。批处理文件目录应该已经是当前目录,因此完全不需要%~dp0
,但是为了安全起见,使用完整路径指定文件也没有关系。
接下来,标准Windows控制台应用程序 TIMEOUT 会以完整的合格文件名进行调用,并具有等待5秒钟不间断(需要Windows 7或更高版本)并将其输出重定向到设备 NUL 的选项strong>。
我对文件jps
一无所知,甚至都没有安装Java。因此,我假设jps
是可执行文件或脚本,其文件扩展名在 local 环境变量PATHEXT
中列出并存储在批处理文件的目录中或任何其他目录中路径列在 local 环境变量PATH
中。当然,最好使用文件扩展名指定该文件,如果可能的话,还应使用完整路径。
jps
的标准输出重定向到Windows标准控制台应用程序 FINDSTR 的标准输入,错误输出重定向到设备 NUL 以对其进行抑制。
FINDSTR 在java_server
的标准输出上对jps
运行区分大小写的文字字符串搜索。 FINDSTR 的输出没有意义,因此也重定向到设备 NUL 来抑制它。
FINDSTR 在真正找到的搜索字符串上以0
退出,在没有找到的字符串上以1
退出。在未成功启动Java服务器时,批处理文件应以1
退出,而在Java服务器运行时应以0
退出。这与 FINDSTR 的退出代码完全匹配,因此无需执行其他任何操作。
cmd.exe
总是在批处理文件执行期间退出应用程序或命令设置的最后一个退出代码的批处理文件执行。可以使用rem
注释掉第二条命令行并保存,然后在命令提示符窗口中运行此批处理文件,然后在命令提示符窗口if errorlevel 1 echo Java server not running!
中运行下一步,以得到预期的输出{{1} }。然后需要从批处理文件的第二个命令行中删除Java server not running!
,然后再保存从命令提示符窗口再次运行的批处理文件。在第二个批处理文件执行完成之后,再次运行rem
将导致没有输出,而运行if errorlevel 1 echo Java server not running!
则会导致输出if errorlevel 0 echo Java server is running.
。
要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。
Java server is running.
...解释call /?
%~dp0
cd /?
echo /?
findstr /?
if /?
另请参阅: