【问题标题】:sh script gets stuck on read command in while loopsh 脚本卡在 while 循环中的读取命令上
【发布时间】:2019-10-15 17:44:53
【问题描述】:

我正在尝试编写一个脚本,我将把它放入我的 pi 的 cron 中,以每 10 秒检查一次网络连接,如果它无法 ping 到 google,它会将一个文本文件写入 false,然后下次它成功,它会重新启动一个程序,因为特定程序有自动重新连接网络的问题。

当我从同一目录的终端执行它时,该脚本似乎正在工作,然后我 cd 回到 / 并添加了一堆 cmets,现在它只是退出脚本而没有任何输出,并且对于我的生活我无法弄清楚我在哪里搞砸了 - 我对脚本仍然比较陌生,所以我可能在这里遗漏了一些绝对明显的东西,但我在谷歌上找不到任何有用的东西。

file heirarchy:
/home/pi/WEB_UI/
inside the WEB_UI folder are both of the scripts i'm running here.
nonet.sh - the script in question
pianobar.sh - a simple script to pkill a program and reload it after 5 seconds.
var.txt - a text file that will only ever contain "true" or "false

我已尝试删除所有 cmets,将文件位置更改为 ./ 并创建 while; do 命令一行,但我不知道问题出在哪里。如果我为脚本运行 sh -x,它会返回:

    pi@raspberrypi:~/WEB_UI $ sh -x nonet.sh
    + ping -q -c 1 -W 1 google.com
    + read line

有趣的是,我从我使用的测试脚本中得到了相同的结果,基本上是

"if var.txt says 'true', echo 'up', else echo 'down'" 
  • 不知道是不是我的 sh 解释器有问题?
    #!/bin/sh

    #ping google, if successful return true
    if ping -q -c 1 -W 1 google.com >/dev/null; then
        #read variable line, perform action do
        while read line
        do
        #leading $ means return previous output. if line is false:
        if [ "$line" = "false" ]
        then
            #return network up text, run pianobar script, set var.txt to true.
            echo "the network is back up"
            sh /home/pi/WEB_UI/pianobar.sh
            echo true > /home/pi/WEB_UI/var.txt
        else
            #otherwise return network is up, set var.txt to true
            echo "the network is up"
            echo true > /home/pi/WEB_UI/var.txt
        #fi ends an if statement, done ends a while loop.
        #text after done tells the while loop where to get the line variable
        fi
        done < /home/pi/WEB_UI/var.txt
    else
        while read line
        do
        if [ "$line" = "false" ]
        then
            #if var.txt is already false, ping google again
            if ping -q -c 1 -W 1 google.com >/dev/null; then
                #if ping works, the network is back, restart pianobar, set var to true
                echo "the network is back up"
                sh /home/pi/WEB_UI/pianobar.sh
                echo true > /home/pi/WEB_UI/var.txt
            else
                #if var.txt is false, network is still down. wait.
                echo "the network is still down"
            fi
        else
            echo "the network is down"
            echo false > /home/pi/WEB_UI/var.txt
        fi
        done < /home/pi/WEB_UI/var.txt
    fi

脚本应该只回显一个简单的行,说明网络是启动、关闭、备份还是仍然关闭,具体取决于它通过/失败的标志数。任何帮助将不胜感激!

【问题讨论】:

  • 这里没有明显的问题。您是否将完整的 shell 脚本粘贴到 shellcheck.net 中?也许它会找到一些东西。否则,我敢打赌/home/pi/WEB_UI/var.txt 有问题,为空,或者cat -vet /home/pi/WEB_UI/var.txt 如果您在每行的末尾看到^M$,然后运行dos2unix /home/pi/WEB_UI/var.txt 以删除^M(这可能会弄脏东西向上)。祝你好运。
  • 我确实通过 shellcheck 运行了它,它告诉我的只是我应该将 -r 添加到我的读取行中,但我不明白这一点,因为我永远不会有反斜杠运行 cat -vet 后的 var.txt,它只输出“false”,所以我假设那端没有任何问题。我想我会继续寻找! pi@raspberrypi:~ $ cat -vet /home/pi/WEB_UI/var falsepi@raspberrypi:~ $
  • 我会补充一点,var.txt 目前只包含“false”——如果我在里面 crtl-A,就没有多余的行或空格,而且我还开放了对 var 的权限.txt 和整个 WEB_UI 文件夹供“任何人”读取、写入和执行,以确保这不是问题
  • 哈!可能就是这样。 ... false 没有 $ 表示结尾不是 \n 字符。我对echo true &gt; file 的快速测试在行尾产生了$。我想我最近看到了另一篇帖子,其中while read... 因缺少\n 字符而感到沮丧,所以也许你想改用printf "false\n" &gt; file。祝你好运。
  • 太棒了。这解决了问题,现在运行顺利!如果您想引用您的评论作为答案,我很乐意将其标记为这样

标签: sh raspberry-pi3 raspbian


【解决方案1】:

正如 Shellter 在上面的 cmets 中所说,问题是我需要在 var.txt 的行尾添加 \n

我想我最近看到了另一篇文章,在阅读时...对丢失的 \n 字符感到沮丧,所以也许你想改用 printf "false\n" > 文件。祝你好运。

【讨论】:

  • while read line || [ -n "$line" ] 将防止非 POSIX eof。而且,“我想知道我的 sh 解释器是否有问题?”——答案通常是——“没有。”
猜你喜欢
  • 2016-05-19
  • 2019-05-06
  • 1970-01-01
  • 1970-01-01
  • 2019-12-19
  • 2014-11-03
  • 1970-01-01
  • 2019-04-25
  • 1970-01-01
相关资源
最近更新 更多