【问题标题】:while true loop works perfectly when run manually but gets stuck when run at startupwhile true 循环在手动运行时完美运行,但在启动时运行时卡住
【发布时间】:2017-02-25 00:05:16
【问题描述】:

我的 RPi 上的这个 while true 循环有问题。我希望它在启动后始终等待用户输入。以下脚本在我手动运行时完美运行:

#!/bin/bash

while true; do
  read input
  if [ "$input" = "1" ]; then
    echo "message1"
  elif [ "$input" = "2" ]; then
    echo "message2"
  elif [ "$input" = "3" ]; then
    echo "message3"
  else
    echo "error"
  fi
done

但是当我在启动时通过将脚本添加到 rc.local 来运行脚本时,它不会等待输入。相反,它只是无限地呼应“错误”。我不明白。为什么手动运行时可以,开机时卡住?

谢谢!

【问题讨论】:

标签: bash while-loop


【解决方案1】:

您不能在未连接到终端的 shell 中等待用户输入。启动脚本不是在交互式 shell 中执行的,所以您看到的是意料之中的:read 失败,返回一个空字符串,并导致达到else 条件。

也许您真正想要的是从 shell 的启动脚本中调用您的脚本,以便在登录时将其呈现给用户。查看您的 shell/disto 的文档以了解使用哪个。

您可能想在脚本的开头添加类似这样的内容:

[ -t 0 ] || exit

[ -t 0 ] 如果标准输入连接到终端,则返回 0。请注意,如果脚本是源而不是在其自己的 shell 中执行,“exit”将导致执行源的 shell 退出:您可能希望将代码放在函数中并使用 return 而不是 exit ,或将测试用作包含其余代码的if/then/fi 块的条件。

此外,case 语句可能比级联 elif 子句更具可读性。

【讨论】:

  • 谢谢!从 .bashrc 运行脚本就可以了!我肯定会考虑使用“case”语句而不是“elif”,感谢您的建议!
【解决方案2】:

正如@Fred 所说,您的命令将无法实现其目的,主要是因为脚本根本没有连接到任何交互式终端。

它不起作用的原因应该通过了解rc.local文件:https://www.raspberrypi.org/documentation/linux/usage/rc-local.md来清楚。这样,只要 Pi 启动,脚本就会执行。但是,您希望它在每个用户提示时执行。而且它可以在你已经交互的 shell 中工作,因为它写得很好而且非常正确——耶!

除了来自@Fred 的所有好建议之外,如果您想阅读一些用户 输入,您应该尝试将您的脚本包含在您的.bashrc 文件中,这是被解释的文件任何时候用户(pi,默认情况下,在/home/pi/.bashrc 中)进入交互式 shell。

如果您想要使其全局,当任何 用户以交互方式登录时,您可以将其添加到“全局”.bashrc。如需进一步阅读:https://unix.stackexchange.com/questions/36762 或者更好!看看这个:http://www.linuxfromscratch.org/blfs/view/svn/postlfs/profile.html

最后,关于脚本本身:因为它是一个简单的while 循环,它使用read 来获取一些用户输入(同样,@Fred 关于case 语句是正确的),它可以是通过向read 进程发出信号来停止,例如,使用 control-C (^C)。所以,如果你想捕捉这些信号,你应该看到help trap(例如:trap 'echo "YOU WON'T STOP ME"' INT KILL TERM 不会让你使用 ^C 杀死一个进程——小心使用它),并列出可能的信号,使用kill -l

【讨论】:

  • 小心:通常.bashrc 每次交互启动shell 时都会调用,包括不是登录shell 时。这意味着当您从交互式会话中启动 Bash 时,会执行其中的内容,这可能(或可能不是)您想要的。见这里:gnu.org/software/bash/manual/bashref.html#Bash-Startup-Files.
  • 也感谢您提供的其他提示和那些非常有用的链接!现在一切正常! :)
最近更新 更多