0

I know this question has been asked a lot of time, but trust me i have tried many suggestions. What i am trying to do is continiously monitor the logfile of a tomcat server to detect its startup. Its based on this stack post

I have modified it a little bit to add a timeout so that it won't wait for ever if the string is not present at all in the file. The code looks like below.

echo 0 > flag timeout $DEPLOY_WAIT tail -n0 -F $TOMCAT_LOG | while read LOGLINE do [[ "${LOGLINE}" == *"INFO: Server startup in"* ]] && echo 1 > flag && pkill -P $$ timeout done x=$(cat flag) if [ $x -ne 0 ];then 

Here you can see i am writing to a flag file to detect whether the tail timed out out or if it found a matching string in the file. If i change it to a variable like

flag=0 timeout $DEPLOY_WAIT tail -n0 -F $TOMCAT_LOG | while read LOGLINE do [[ "${LOGLINE}" == *"INFO: Server startup in"* ]] && flag=1 && pkill -P $$ timeout done if [ $flag -ne 0];then 

then the variable flag always have the value 0. The update done in the while loop is lost. I did some research and found out that this is because the pipe is causing bash to spawn a new sub shell and parameter are passed from parent to child and not vice versa. A solution suggested by this post was to rewrite the thing without using pipes like

flag=0 while read LOGLINE; do [[ "${LOGLINE}" == *"INFO: Server startup in"* ]] && flag=1 && pkill -P $$ timeout done <<< $(timeout $DEPLOY_WAIT tail -n0 -F $TOMCAT_LOG) if [ $flag -ne 0];then 

The problem with this solution is that the data is give to the while loop only after the command timeout completes[and the code to detect the timeout process and kill it also changes. But doesn't matter, so not included] and i am not able to detect the string as soon as it arrives in the file. The script waits for the period of the timeout, no matter what. I am looking for way to combine the two into a single elegant solution not using files as flag.

1
  • You are making things hard on yourself. Search for inotifywait on StackOverflow. You can use it to monitor your log for changes and do whatever you need when your log changes. (pay attention to the -m and -e options) Commented Aug 10, 2018 at 6:09

2 Answers 2

1

Use PIPESTATUS to check, if the timeout has been reached. In case of an timeout, the return value is 124.

$ timeout 1 sleep 2 | read Terminated $ echo $PIPESTATUS 124 $ timeout 2 sleep 1 | read $ echo $PIPESTATUS 0 

And do not kill timeout. It terminates itself, if the child dies.

Sign up to request clarification or add additional context in comments.

Comments

0

The problem with the solution you tried:

done <<< $(timeout $DEPLOY_WAIT tail -n0 -F $TOMCAT_LOG) 

is that you're capturing the entire output of the timeout ... command with $( ) as a string (which means that it must wait until the process exits), and then passing that to the loop as a here-string (with <<<). In order for the loop to process output as it's produced, you need to mimic a pipe, like this:

done < <(timeout $DEPLOY_WAIT tail -n0 -F $TOMCAT_LOG) 

This looks similar, but it's quite different in the details. The <( ) part is called process substitution -- it runs the timeout ... command as a subprocess, and effectively inserts a the filename of a named pipe connected to that process's stdout. Then the resulting < pipename part makes the loop read from that named pipe. The effect is pretty much the same as a regular pipe (as in your first attempt), except that the loop isn't forced into a subshell.

1 Comment

this worked for me but had t modify the script a little bit to find and kill the timeout process. Earlier the timeout process had the shell script process itself has its parent. After this change a new process is created similar to the original shell scirpt and the timeout is running as a child of this process. so had to use the below comamnd to detect it. depoy.sh is the script name. pkill -P `pgrep -P $$ deploy` timeout

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.