while 循环中 break 的奇怪行为
Strange behavior of break inside while loop
我正在尝试编写 bash 脚本来观察 catalina.out
日志文件。每次出现字符串 java.lang.OutOfMemoryError
时,它都应该重新启动 tomcat。
(我知道最好在 webapp 中找到错误,但 webapp 需要 运行 直到开发人员找到错误。所以这只是(希望)短时间的修补程序。 )
问题在于“break”在找到模式后不会立即离开 while 循环。下面有更多详细信息。
这里是脚本:
#!/bin/bash
LOGFILE=/var/log/catalina.out
LOCKFILE=/tmp/pointtest.lock
while [ /bin/true ]
do
echo "Starting tail-Loop"
tail -fn0 ${LOGFILE} | \
while read line
do
echo "Inside tail-Loop"
echo "$line" | grep "java.lang.OutOfMemoryError" > /dev/null
if [ $? = 0 ]
then
echo "Error! java.lang.OutOfMemoryError"
# here should be the command to restart tomcat
break
fi
done
echo "Left tail-Loop"
done
这是一个没有错误的测试输入文件(文件名:noErrors
):
Something
Something
Something
Something
Anything
Something
Something
Do something
And so on
Anything
Something
这是一个测试输入文件(文件名:oomErrors
),内存不足错误:
Something
Something
java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: Java heap space
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at org.apache.catalina.core.ContainerBase.threadStart(ContainerBase.java:1276)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessorMonitor.run(ContainerBase.java:1322)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
java.lang.OutOfMemoryError: Java heap space
Something
Something
Anything
java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: Java heap space
Something
Something
Do something
And so on
java.lang.OutOfMemoryError: Java heap space
Anything
Something
第一个:
touch /var/log/catalina.out
然后启动脚本。
输出:
Starting tail-Loop
现在我正在执行以下命令:
cat noErrors >> /var/log/catalina.out
脚本的输出:
Inside tail-Loop
Inside tail-Loop
Inside tail-Loop
Inside tail-Loop
Inside tail-Loop
Inside tail-Loop
Inside tail-Loop
Inside tail-Loop
Inside tail-Loop
Inside tail-Loop
Inside tail-Loop
Inside tail-Loop
所以直到这里脚本按预期工作。
现在我正在执行以下命令:
cat oomErrors >> /var/log/catalina.out
脚本输出:
Inside tail-Loop
Inside tail-Loop
Inside tail-Loop
Error! java.lang.OutOfMemoryError
oomErrors
的前两行处理正确。然后脚本找到了 OOM 模式,但它没有离开 tail-while-loop。
然后我执行这个命令:
cat noErrors >> /var/log/catalina.out
脚本的输出:
Left tail-Loop
Starting tail-Loop
只有在这里它才离开了 tail-while 循环并重新启动了 tail-while 循环。
似乎在检测到第一行错误后它忽略了以下行并在 break 命令处停止。
所以我的问题是:为什么脚本在找到带有错误字符串的第一行后不立即离开 tail-while-loop,我该如何解决这个问题?
提前致谢:-)
稍微简化并消除 grep
的不必要的开销。
while : # : is a synonym for true
do echo "Starting tail-Loop"
while read line
do echo "Inside tail-Loop"
case "$line" in
*java.lang.OutOfMemoryError*)
echo "Error! java.lang.OutOfMemoryError"
# restart tomcat here
break
;;
esac
done < <( tail -fn0 ${LOGFILE} )
echo "Left tail-Loop"
done
我正在尝试编写 bash 脚本来观察 catalina.out
日志文件。每次出现字符串 java.lang.OutOfMemoryError
时,它都应该重新启动 tomcat。
(我知道最好在 webapp 中找到错误,但 webapp 需要 运行 直到开发人员找到错误。所以这只是(希望)短时间的修补程序。 )
问题在于“break”在找到模式后不会立即离开 while 循环。下面有更多详细信息。
这里是脚本:
#!/bin/bash
LOGFILE=/var/log/catalina.out
LOCKFILE=/tmp/pointtest.lock
while [ /bin/true ]
do
echo "Starting tail-Loop"
tail -fn0 ${LOGFILE} | \
while read line
do
echo "Inside tail-Loop"
echo "$line" | grep "java.lang.OutOfMemoryError" > /dev/null
if [ $? = 0 ]
then
echo "Error! java.lang.OutOfMemoryError"
# here should be the command to restart tomcat
break
fi
done
echo "Left tail-Loop"
done
这是一个没有错误的测试输入文件(文件名:noErrors
):
Something Something Something Something Anything Something Something Do something And so on Anything Something
这是一个测试输入文件(文件名:oomErrors
),内存不足错误:
Something Something java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: Java heap space at java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.util.concurrent.FutureTask.get(FutureTask.java:192) at org.apache.catalina.core.ContainerBase.threadStart(ContainerBase.java:1276) at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessorMonitor.run(ContainerBase.java:1322) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748) java.lang.OutOfMemoryError: Java heap space Something Something Anything java.lang.OutOfMemoryError: Java heap space java.lang.OutOfMemoryError: Java heap space Something Something Do something And so on java.lang.OutOfMemoryError: Java heap space Anything Something
第一个:
touch /var/log/catalina.out
然后启动脚本。
输出:
Starting tail-Loop
现在我正在执行以下命令:
cat noErrors >> /var/log/catalina.out
脚本的输出:
Inside tail-Loop Inside tail-Loop Inside tail-Loop Inside tail-Loop Inside tail-Loop Inside tail-Loop Inside tail-Loop Inside tail-Loop Inside tail-Loop Inside tail-Loop Inside tail-Loop Inside tail-Loop
所以直到这里脚本按预期工作。
现在我正在执行以下命令:
cat oomErrors >> /var/log/catalina.out
脚本输出:
Inside tail-Loop Inside tail-Loop Inside tail-Loop Error! java.lang.OutOfMemoryError
oomErrors
的前两行处理正确。然后脚本找到了 OOM 模式,但它没有离开 tail-while-loop。
然后我执行这个命令:
cat noErrors >> /var/log/catalina.out
脚本的输出:
Left tail-Loop Starting tail-Loop
只有在这里它才离开了 tail-while 循环并重新启动了 tail-while 循环。
似乎在检测到第一行错误后它忽略了以下行并在 break 命令处停止。
所以我的问题是:为什么脚本在找到带有错误字符串的第一行后不立即离开 tail-while-loop,我该如何解决这个问题?
提前致谢:-)
稍微简化并消除 grep
的不必要的开销。
while : # : is a synonym for true
do echo "Starting tail-Loop"
while read line
do echo "Inside tail-Loop"
case "$line" in
*java.lang.OutOfMemoryError*)
echo "Error! java.lang.OutOfMemoryError"
# restart tomcat here
break
;;
esac
done < <( tail -fn0 ${LOGFILE} )
echo "Left tail-Loop"
done