在 shell 脚本中执行的批处理文件不等待用户输入
Posted
技术标签:
【中文标题】在 shell 脚本中执行的批处理文件不等待用户输入【英文标题】:Batch file executed in shell script not waiting for user input 【发布时间】:2021-06-08 21:06:57 【问题描述】:我偶然发现了 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 只显示一些消息并运行单元测试任务,但 integration_test.bat 会提示用户是否要运行这些测试因为它们通常较慢。
问题在于提示(使用“choice”或“set /p”完成)没有得到用户输入:
'set /p' 不等待用户输入 “选择”冻结,不允许任何用户输入我尝试添加 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
【问题讨论】:
/bin/sh
与 /bin/bash
不同,您实际上运行的是常规 shell 脚本而不是 bash 脚本,因为您的脚本调用的是 /bin/sh
解释器而不是 /bin/bash
解释器. bash 的路径在您的系统上可能不同,因此您可能需要运行 which bash
来确认它。
感谢您指出,那时我应该将其引用为 shell 脚本而不是 bash。这个细节是否也应该解决这种情况?我尝试使用 /bin/bash
解释器运行,但似乎没有帮助
我认为这不是你问题中的问题,但我会尽量确保所有细节尽可能准确,这就是我提到的原因。
这是一个很好的观点,感谢您指出这一点。
git 钩子没有交给 tty,如果你需要它,你必须自己重新打开它(尽管钩子期间的交互性有点 imo)——在 Windows 上,我相信它正在打开 @987654330 @
【参考方案1】:
我认为gradlew
实际上是另一个批处理文件gradlew.bat
,所以我假设,如果您希望它在完成后返回到脚本,您应该使用Call
命令。此外,您应该知道&
将两个单独的命令连接在一行上,而&&
仅在前一个命令成功时才运行一个命令。在您的情况下,Echo
命令不可能不成功,因此只需&
是必要的。此外,If ErrorLevel 1
表示如果错误代码为 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)运行脚本。
【讨论】:
感谢您纠正我的错误并以清晰的方式解释它们,这将有助于知道错误可能不是因为这些更改后的脚本语法。我将编辑原始帖子。然而,当用户必须写下他们的选择时,冻结问题仍然存在。也许我忘了添加一些有意义的东西来帮助人们重现它。【参考方案2】:正如@AnthonySotille 指出的那样,冻结错误是由于 git-hooks 禁用交互性造成的。
我通过将提示提取到另一个 .bat 文件并使用 start /wait
调用它们来绕过这种情况。这会打开另一个 cmd,运行提示符,然后使用成功代码表示 Y 并将失败代码表示为 N 退出。这似乎不是一个好的做法,但现在,它可以完成这项工作。
此问题可能被视为与How do I prompt the user from within a commit-msg hook? 重复
【讨论】:
以上是关于在 shell 脚本中执行的批处理文件不等待用户输入的主要内容,如果未能解决你的问题,请参考以下文章
jenkins执行shell脚本,使用scp免密传输失败问题