0

I am quite new to bash (barely any experience at all) and I need some help with a bash script.

I am using docker-compose to create multiple containers - for this example let's say 2 containers. The 2nd container will execute a bash command, but before that, I need to check that the 1st container is operational and fully configured. Instead of using a sleep command I want to create a bash script that will be located in the 2nd container and once executed do the following:

  1. Execute a command and log the console output in a file
  2. Read that file and check if a String is present. The command that I will execute in the previous step will take a few seconds (5 - 10) seconds to complete and I need to read the file after it has finished executing. I suppose i can add sleep to make sure the command is finished executing or is there a better way to do this?
  3. If the string is not present I want to execute the same command again until I find the String I am looking for
  4. Once I find the string I am looking for I want to exit the loop and execute a different command

I found out how to do this in Java, but if I need to do this in a bash script.

The docker-containers have alpine as an operating system, but I updated the Dockerfile to install bash.

I tried this solution, but it does not work.

#!/bin/bash

[command to be executed] > allout.txt 2>&1

until 
  tail -n 0 -F /path/to/file | \
  while read LINE
  do
    if echo "$LINE" | grep -q $string
    then
      echo -e "$string found in the console output"
  fi
  done
do
    echo "String is not present. Executing command again"
    sleep 5
    [command to be executed] > allout.txt 2>&1
done

echo -e "String is found"
andrei1986
  • 25
  • 9
  • Sure. In point 3 - do you need to re-read the whole file or not? In other words, the searched string will be appended to the file or the file will be truncated? – KamilCuk Dec 29 '19 at 10:08
  • Ideally, if the string is not found, once I execute the command again I would like to delete the original console output, record the new console output and only search for the string in the new output. – andrei1986 Dec 29 '19 at 10:14
  • I repeat myself. After finding out that the searched string is __not__ found in the file, in point 3. When the next time searching for the string in the file. Do you need to scan the whole file for the searched string or the searched string will be appended to the file, so you only need to scan new data added to the file? How is a "console output" related to what you are searching? What is modifying the file? – KamilCuk Dec 29 '19 at 10:16
  • Neither appended nor truncated. Once the string is found in the file I want to exit the loop. – andrei1986 Dec 29 '19 at 10:19

2 Answers2

1

In your docker-compose file make use of depends_on option.

depends_on will take care of startup and shutdown sequence of your multiple containers.

But it does not check whether a container is ready before moving to another container startup. To handle this scenario check this out.

As described in this link,

  • You can use tools such as wait-for-it, dockerize, or sh-compatible wait-for. These are small wrapper scripts which you can include in your application’s image to poll a given host and port until it’s accepting TCP connections.

OR

  • Alternatively, write your own wrapper script to perform a more application-specific health check.

In case you don't want to make use of above tools then check this out. Here they use a combination of HEALTHCHECK and service_healthy condition as shown here. For complete example check this.

mchawre
  • 10,744
  • 4
  • 35
  • 57
0

Just:

while :; do
   # 1. Execute a command and log the console output in a file
   command > output.log
   # TODO: handle errors, etc.
   # 2. Read that file and check if a String is present.
   if grep -q "searched_string" output.log; then
       # Once I find the string I am looking for I want to exit the loop
       break;
   fi
   # 3. If the string is not present I want to execute the same command again until I find the String I am looking for
   # add ex. sleep 0.1 for the loop to delay a little bit, not to use 100% cpu
done
# ...and execute a different command
different_command

You can timeout a command with timeout.

Notes:

  • colon is a utility that returns a zero exit status, much like true, I prefer while : instead of while true, they mean the same.
  • The code presented should work in any posix shell.
KamilCuk
  • 120,984
  • 8
  • 59
  • 111