read: read error: 0:在bash中使用case调用脚本时资源暂时不可用



我试图创建一个菜单,允许用户在当前目录中调用某些shell脚本。菜单循环,直到用户退出脚本(输入5)

下面是我的代码:
until [ "$SELECTION" = "5" ]; do    
echo "# Enter a number to launch:"                            
echo "# 1) Script 1"
echo "# 2) Script 2"
echo "# 3) Script 1 and Script 2"
echo "# 4) Readme"
echo "# 5) Exit"
echo -n "Launch: "
read SELECTION
case $SELECTION in
    1) 
    (exec "./script1") ;;
    2) 
    (exec "./script2") ;;
    3)
    (exec "./script1")
    (exec "./script2") ;;
    4) vi "readme.txt" ;;
    5) exit 0 ;;
    *) echo "Error. Please enter a valid selection." ;;
    esac
done

在用户选择之后,所选脚本运行良好,但是一旦完成,我得到一个重复的错误:

read: read error: 0: Resource temporarily unavailable

它永远不会返回到菜单。我不知道我做错了什么。什么好主意吗?

看看你的菜单,有一些东西没有意义。在每个case语句中调用:

(exec "./script1")

./script1作为命令调用,而不是单独的脚本。其次,由于您将行括在父()中,因此您强制执行在子shell中而不是当前shell中进行。

您在[ "$SELECTION" = "5" ]中使用的SELECTION似乎未初始化,(我认为这是您将其包装在引号中的原因)。引号没有错,但你的值是1-5,所以它不是强制性的,只要它是初始化的。

你的菜单本身很好。事实是,它未能执行多次是你在(exec "./script1")所做的任何结果。由于您似乎试图从case语句调用bash脚本,因此启动脚本(如果它们不能使用chmod 0755执行)的正确方法是使用bash而不是exec。如果脚本不是bash,或者您希望泛化调用,那么使用exec将像注释中提到的那样工作。

虽然until没有什么问题(除了不常用),我建议使用while。此外,由于一行中有多个echo语句,因此可以考虑使用here语句来创建heredoc

代码的缩进使阅读更容易,并保持逻辑清晰。需要注意的是heredoc和它的结束分隔符。要缩进heredoc及其分隔符,它们必须与TABS而不是SPACES 缩进。此外,heredoc必须以<<-开始,而不是简单地以<<开始,以利用TAB缩进。(这就是为什么我一开始没有提出这个问题的原因)

稍微重写一下

可能看起来像下面这样。注意:下面的代码是8-space缩进的,因为SO将TABS转换为SPACES,所以要使用显示缩进的代码,您需要确保代码前面的空白是TAB字符而不是SPACES字符,否则将不会运行:

declare -i SEL=0
while [ $SEL != 5 ]; do
        cat >&2 <<- MENU
          Enter a number to launch:
            1) Script 1
            2) Script 2
            3) Script 1 and Script 2
            4) Readme
            5) Exit
        MENU
        echo -n "  Launch: "
        read SEL
        case $SEL in
            1)  echo "./script1"
                ;;
            2)  echo "./script2"
                ;;
            3)  echo "./script1"
                echo "./script2"
                ;;
            4)  vi "readme.txt"
                ;;
            5)  exit 0
                ;;
            *)  echo "Error. Please enter a valid selection."
                ;;
        esac
done

您可以选择是否要正式缩进heredoc。我更喜欢4-space缩进,所以我只保留heredoc开头和分隔符而不缩进,以保留允许剪切/粘贴示例的的能力。你的选择:

declare -i SEL=0
while [ $SEL != 5 ]; do
cat >&2 << MENU
  Enter a number to launch:
    1) Script 1
    2) Script 2
    3) Script 1 and Script 2
    4) Readme
    5) Exit
MENU
    echo -n "  Launch: "
    read SEL
    case $SEL in
        1)  exec "./script1"
            ;;
        2)  exec "./script2"
            ;;
        3)  exec "./script1"
            exec "./script2"
            ;;
        4)  vi "readme.txt"
            ;;
        5)  exit 0
            ;;
        *)  echo "Error. Please enter a valid selection."
            ;;
    esac
done

最新更新