Bash while 循环的脚本意外结果
Bash script unexpected result for while loop
我有以下 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`
:
你的ps -C httpd
命令总是returns一行:PID TTY TIME CMD
(基本上是ps
输出的标题)被wc -l
计为1当没有进程时 运行。如果 httpd
是 运行,则行数将大于 1。
因此$((RTN -1))
变成了0
。
编辑:
我注意到,您的 while 循环有一个错误:
while [[ $RTN -gt 0 ]]
echo "Before" $RTN
do
改为:
while [[ $RTN -gt 0 ]]
do
echo "Before" $RTN
我有以下 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 listlist-2
as long as the last command in the listlist-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`
:
你的ps -C httpd
命令总是returns一行:PID TTY TIME CMD
(基本上是ps
输出的标题)被wc -l
计为1当没有进程时 运行。如果 httpd
是 运行,则行数将大于 1。
因此$((RTN -1))
变成了0
。
编辑:
我注意到,您的 while 循环有一个错误:
while [[ $RTN -gt 0 ]]
echo "Before" $RTN
do
改为:
while [[ $RTN -gt 0 ]]
do
echo "Before" $RTN