linux - Bash 脚本 while 循环的意外结果

标签 linux bash shell scripting

我有以下 bash 脚本来停止 Apache 服务器。我没有收到错误,而是收到了意外结果。

#!/bin/bash

/etc/init.d/httpd stop
if [[ $? -ne 0 ]]
then
    exit 1
fi
RTN=10
while [[ $RTN -gt 0 ]]
echo "Before" $RTN
do
    sleep 5
    RTN=`ps -C httpd | wc -l`
    RTN=$(( RTN - 1 ))
echo "After" $RTN
done 

exit 0

我得到了以下我不希望的答案,无限打印:

Before 10
After 0

Before 0
After 0

Before 0
After 0

我希望打印:

Before 10
After -1 
#and exit here

有人能告诉我发生了什么事吗?

最佳答案

这并不像您认为的那样有效:

while [[ $RTN -gt 0 ]]
echo "Before" $RTN
do

您希望 echo do 之后。在 do 之前,它是 list-1 条件的一部分,而不是 list-2 主体。并且,根据 bash 文档(我的粗体):

The while command continuously executes the list list-2 as long as the last command in the list list-1 returns an exit status of zero.

您可以看到以下脚本之间的区别,类似于您的脚本:

#!/usr/bin/bash
RTN=2
while [[ $RTN -gt 0 ]]
echo "Before" $RTN
do
    sleep 1
    RTN=$(( RTN - 1 ))
echo "After" $RTN
done

哪个输出(无穷大):

Before 2
After 1
Before 1
After 0
Before 0
After -1
Before -1
After -2
Before -2

当您将 echo 移动到正文内部时:

#!/usr/bin/bash
RTN=2
while [[ $RTN -gt 0 ]]
do
    echo "Before" $RTN
    sleep 1
    RTN=$(( RTN - 1 ))
    echo "After" $RTN
done

然后它正确终止:

Before 2
After 1
Before 1
After 0
<returns to prompt>

一旦做出更改,循环就会正确终止,因为您的 ps 命令正在生成这些值。


此外,如果您想找出进程列表中的内容(并且可能导致结果为零而不是负数),请在检查计数之前输出进程列表:

:
ps -C httpd                 # Add this line temporarily.
RTN=`ps -C httpd | wc -l`
:

关于linux - Bash 脚本 while 循环的意外结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30434505/

相关文章:

linux - crontab 命令分隔行

linux - 提取和重新格式化字符串/时间键之间的文本

linux - 如何在 UNIX 中使用 if 语句

python - 运行 python 脚本的 Bash 脚本

linux - Linux shell 脚本中的 Pascal 三角形

c++ - 在 C++ 中监听后如何从同一端口发送数据?

Java InputStreamReader,mac 和 linux 上的输出不同

linux - 按包含小数的名称对文件排序

bash - 无法在 docker build 期间使用进程替换,因为 bash 进入 posix 模式

arrays - Shell 脚本形成动态数组并触发基于它的进程