【问题标题】:Bash script won't exit on input commandBash 脚本不会在输入命令时退出
【发布时间】:2021-01-17 03:08:44
【问题描述】:

我有一个在 git post-commit 挂钩上运行的 bash 脚本。它的作用是要求用户输入,并根据输入触发另一个操作并退出。

问题是当动作运行时它不会退出,这意味着例如输入 0 npm version patch 运行并完成但脚本挂在那里。必须使用 ctrl+c 手动关闭它才能退出脚本。

这是我的脚本:

#!/bin/sh

echo "
Script app versioning started! 
"

exec < /dev/tty

while true; do   
read -p "What version should the project update to? 
    - patch[x.x.1] press 0
    - minor[x.1.x] press 1  
    - major[1.x.x] press 2
    - skip patching press 3
    " answer
    case $answer in
            [0] ) 
            npm version patch ;
            exit 0;;
            [1] ) npm version minor;
            exit 0;;
            [2] ) npm version major;
            exit 0;; 
            [3] ) echo "No version patched";
            exit 0;;
            * ) echo "Please answer 0, 1 or 2.";;
    esac
done

echo "
Script app versioning ended!
"
exit 0

是不是由于来自命令exec &lt; /dev/tty 的重定向,当输入0,1 或2 并且npm version patch 命令会中断输出,所以它会继续而不触发exit 0 而只是挂起? 如果是这样,我该如何解决?尝试像exec &gt; /dev/tty 一样将输出重定向回来,但不起作用。

删除exec &lt; /dev/tty 将运行脚本并退出,但不会等待我的命令输入。

【问题讨论】:

  • #/bin/sh --> 应该是#!/bin/sh..好像是错字!
  • 不确定提交挂钩是否可以访问 tty 终端。无论如何,您可以使用select 来实现您的菜单。示例:select a in 'foo' 'bar' 'baz'; do echo "$a"; break; done
  • read -p 是一个仅限 bash 的选项。您需要将 shebang 调整为 bash 并确保脚本在钩子中使用 bash 运行。
  • 为什么exec &lt; /dev/tty 会出现在首位?我从未在脚本中看到过。
  • 你能试试最后按 ctrl-d 吗?它应该关闭输入。

标签: bash git npm post-commit-hook


【解决方案1】:

我已经设法通过像这样重定向回我的标准输出来修复我的脚本:

#!/bin/sh

echo "
Script app versioning started! 
"

exec < /dev/tty

while true; do   
read -p "What version should the project update to? 
    - patch[x.x.1] press 0
    - minor[x.1.x] press 1  
    - major[1.x.x] press 2
    - skip patching press 3
    " answer
    case $answer in
            [0] ) 
            npm version patch ;
            exit 0;;
            [1] ) npm version minor;
            exit 0;;
            [2] ) npm version major;
            exit 0;; 
            [3] ) echo "No version patched";
            exit 0;;
            * ) echo "Please answer 0, 1 or 2.";;
    esac
done  < "${1:-/dev/stdout}" 

【讨论】: