在 shell 脚本中执行的批处理文件不等待用户输入
Batch file executed in shell script not waiting for user input
我偶然发现了 git-hooks,并试图在 Windows 上创建一个 运行。所以我决定使用批处理文件来这样做,因为它看起来很简单。
首先,我将 pre-commit 示例重命名为 pre-commit 并在那里调用了我的 bat 步骤:
#!/bin/sh
$(pwd)/git-hooks/hooks/unit_test.bat &&
$(pwd)/git-hooks/hooks/integration_test.bat
unit_test.bat 仅显示一些消息和 运行s 单元测试任务,但 integration_test.bat 提示用户是否要 运行 这些测试,因为它们通常比较慢。
问题是提示(通过'choice'或'set /p'完成)没有得到用户输入:
- 'set /p' 不等待用户输入
- 'choice' 冻结并且不允许任何用户输入
我尝试添加 start 来调用 .bat 文件,但它会在另一个 cmd 上打开它们,因此无法停止提交。
引用的文件
unit_test.bat
@echo off
echo ^> Testes unitários
call gradlew testReport || (echo(& echo Testes unitários falharam! Acesse o relatório de testes para conferir.& exit 1))
integration_test.bat
@echo off
echo(echo ^> Testes integrados
%SystemRoot%\System32\choice.exe /C sn /M "Esses testes geralmente são mais lentos. Quer rodar os testes integrados"
if ERRORLEVEL 2 goto nao
call gradlew integrationTests || (echo(echo Testes integrados falharam! Acesse o relatório de testes para conferir.) && exit 1)
:nao
echo(echo Não se esqueça de confirmar que os testes integrados passam antes de fazer o 'git push'!)
exit /B
我认为 gradlew
实际上是另一个批处理文件,gradlew.bat
,所以我假设,如果您希望它在完成后 return 到脚本,您应该使用Call
命令。此外,您应该知道 &
将两个单独的命令连接在一行中,而 &&
运行 只有在前一个命令成功时才执行一个命令。在您的情况下,Echo
命令不可能不成功,因此只需要 &
。此外,如果错误代码为 1
或更高,If ErrorLevel 1
表示,这意味着在您发布的代码中,代码将始终为 goto sim
。您应该改用 If Not ErrorLevel 2
、If %ErrorLevel% Equ 1
或 If "%ErrorLevel%" == "1"
.
示例:(请插入 gradlew.bat
的完整路径,而不是依赖容易损坏或受影响的 %Path%
变量,如果包含空格,请将路径和可执行文件名称用双引号引起来或有问题的字符)。我已经删除了下面示例中不必要的连接,因为脚本中不需要它。
unit_test.bat
@Echo Off
Echo ^> Testes unitários
Call gradlew.bat testReport || (Echo(& Echo Testes unitários falharam! Acesse o relatório de testes para conferir.& Exit 1)
integration_test.bat
@Echo Off
Echo(
Echo ^> Testes integrados
%SystemRoot%\System32\choice.exe /C sn /M "Esses testes geralmente são mais lentos. Quer rodar os testes integrados"
If Not ErrorLevel 2 GoTo sim
Echo(
Echo Não se esqueça de confirmar que os testes integrados passam antes de fazer o 'git push'!
Exit /B
:sim
Call gradlew.bat integrationTests || (
Echo(
Echo Testes integrados falharam! Acesse o relatório de testes para conferir.
)
Exit 1
或:
@Echo Off
Echo(
Echo ^> Testes integrados
%SystemRoot%\System32\choice.exe /C sn /M "Esses testes geralmente são mais lentos. Quer rodar os testes integrados"
If ErrorLevel 2 GoTo nao
Call gradlew.bat integrationTests || (
Echo(
Echo Testes integrados falharam! Acesse o relatório de testes para conferir.
)
Exit 1
:nao
Echo(
Echo Não se esqueça de confirmar que os testes integrados passam antes de fazer o 'git push'!
Exit /B
我还建议,根据您使用的一些字符,确保脚本 运行 使用适当的代码页(可能是 1252)。
冻结错误是由于 git-hooks 禁用了交互性,正如@AnthonySotille 指出的那样。
我通过将提示提取到另一个 .bat 文件并使用 start /wait
调用它们来绕过这种情况。这会打开另一个 cmd,运行提示,然后使用成功代码表示 Y 和失败代码表示 N 退出。这似乎不是一个好的做法,但就目前而言,它完成了工作。
这个问题可能被认为是 How do I prompt the user from within a commit-msg hook?
的重复问题
我偶然发现了 git-hooks,并试图在 Windows 上创建一个 运行。所以我决定使用批处理文件来这样做,因为它看起来很简单。
首先,我将 pre-commit 示例重命名为 pre-commit 并在那里调用了我的 bat 步骤:
#!/bin/sh
$(pwd)/git-hooks/hooks/unit_test.bat &&
$(pwd)/git-hooks/hooks/integration_test.bat
unit_test.bat 仅显示一些消息和 运行s 单元测试任务,但 integration_test.bat 提示用户是否要 运行 这些测试,因为它们通常比较慢。
问题是提示(通过'choice'或'set /p'完成)没有得到用户输入:
- 'set /p' 不等待用户输入
- 'choice' 冻结并且不允许任何用户输入
我尝试添加 start 来调用 .bat 文件,但它会在另一个 cmd 上打开它们,因此无法停止提交。
引用的文件
unit_test.bat
@echo off echo ^> Testes unitários call gradlew testReport || (echo(& echo Testes unitários falharam! Acesse o relatório de testes para conferir.& exit 1))
integration_test.bat
@echo off echo(echo ^> Testes integrados %SystemRoot%\System32\choice.exe /C sn /M "Esses testes geralmente são mais lentos. Quer rodar os testes integrados" if ERRORLEVEL 2 goto nao call gradlew integrationTests || (echo(echo Testes integrados falharam! Acesse o relatório de testes para conferir.) && exit 1) :nao echo(echo Não se esqueça de confirmar que os testes integrados passam antes de fazer o 'git push'!) exit /B
我认为 gradlew
实际上是另一个批处理文件,gradlew.bat
,所以我假设,如果您希望它在完成后 return 到脚本,您应该使用Call
命令。此外,您应该知道 &
将两个单独的命令连接在一行中,而 &&
运行 只有在前一个命令成功时才执行一个命令。在您的情况下,Echo
命令不可能不成功,因此只需要 &
。此外,如果错误代码为 1
或更高,If ErrorLevel 1
表示,这意味着在您发布的代码中,代码将始终为 goto sim
。您应该改用 If Not ErrorLevel 2
、If %ErrorLevel% Equ 1
或 If "%ErrorLevel%" == "1"
.
示例:(请插入 gradlew.bat
的完整路径,而不是依赖容易损坏或受影响的 %Path%
变量,如果包含空格,请将路径和可执行文件名称用双引号引起来或有问题的字符)。我已经删除了下面示例中不必要的连接,因为脚本中不需要它。
unit_test.bat
@Echo Off
Echo ^> Testes unitários
Call gradlew.bat testReport || (Echo(& Echo Testes unitários falharam! Acesse o relatório de testes para conferir.& Exit 1)
integration_test.bat
@Echo Off
Echo(
Echo ^> Testes integrados
%SystemRoot%\System32\choice.exe /C sn /M "Esses testes geralmente são mais lentos. Quer rodar os testes integrados"
If Not ErrorLevel 2 GoTo sim
Echo(
Echo Não se esqueça de confirmar que os testes integrados passam antes de fazer o 'git push'!
Exit /B
:sim
Call gradlew.bat integrationTests || (
Echo(
Echo Testes integrados falharam! Acesse o relatório de testes para conferir.
)
Exit 1
或:
@Echo Off
Echo(
Echo ^> Testes integrados
%SystemRoot%\System32\choice.exe /C sn /M "Esses testes geralmente são mais lentos. Quer rodar os testes integrados"
If ErrorLevel 2 GoTo nao
Call gradlew.bat integrationTests || (
Echo(
Echo Testes integrados falharam! Acesse o relatório de testes para conferir.
)
Exit 1
:nao
Echo(
Echo Não se esqueça de confirmar que os testes integrados passam antes de fazer o 'git push'!
Exit /B
我还建议,根据您使用的一些字符,确保脚本 运行 使用适当的代码页(可能是 1252)。
冻结错误是由于 git-hooks 禁用了交互性,正如@AnthonySotille 指出的那样。
我通过将提示提取到另一个 .bat 文件并使用 start /wait
调用它们来绕过这种情况。这会打开另一个 cmd,运行提示,然后使用成功代码表示 Y 和失败代码表示 N 退出。这似乎不是一个好的做法,但就目前而言,它完成了工作。
这个问题可能被认为是 How do I prompt the user from within a commit-msg hook?
的重复问题