BASH: массивы, пример – скрипт получения логов из Docker-контейнеров

Автор: | 18/11/2016
 

terminalЕсть приложение, которое включает в себя 5 Docker-контейнеров.

Для наблюдения за логами используется Loggly, но мне он жутко неудобен – в консоли логи удобнее смотреть и грепать.

Запущенное приложение выглядит так:

ubuntu@ip-10-5-3-54:~$ docker ps
CONTAINER ID        IMAGE                                                                                                     COMMAND                  CREATED             STATUS                         PORTS                    NAMES
63937e07a5cf        tag-docker.jfrog.io/api-gateway:staging-test-eureka-cloud-versioning-124         "java -Djava.security"   30 minutes ago      Up 30 minutes                  0.0.0.0:8080->8080/tcp   peaceful_blackwell
cbf2394197bc        tag-docker.jfrog.io/producers:staging-test-eureka-cloud-versioning-124           "java -Djava.security"   30 minutes ago      Up 30 minutes                  0.0.0.0:8090->8090/tcp   cocky_nobel
1884543d61b1        tag-docker.jfrog.io/configuration:staging-test-eureka-cloud-versioning-124       "java -Djava.security"   30 minutes ago      Restarting (1) 2 minutes ago   0.0.0.0:8084->8084/tcp   kickass_kirch
65be0b7bb07e        tag-docker.jfrog.io/profile:staging-test-eureka-cloud-versioning-124             "java -Djava.security"   30 minutes ago      Up 30 minutes                  0.0.0.0:8083->8083/tcp   nauseous_kowalevski
947a92a1a629        tag-docker.jfrog.io/oauth2-authserver:staging-test-eureka-cloud-versioning-124   "java -Djava.security"   30 minutes ago      Up 30 minutes                  0.0.0.0:9999->9999/tcp   nauseous_wescoff

Задача скрипта – создать файл лога для каждого сервиса и начать в него писать STDERR и STDOUT из контейнера.

Сам скрипт:

#!/usr/bin/env bash

# To catch STDERR and STDOUT from each Docker container with $API_SERVICES
# to a propriate log file from $API_LOGS
# run: tail -f *.log to watch them
# объявляем два именованных массива
declare -A API_SERVICES
declare -A API_LOGS

# наполняем их
API_SERVICES=( [GATEWAY]=api-gateway \
    [PRODUCERS]=producers \
    [CONFIGURATION]=configuration \
    [PROFILE]=profile \
    [AUTHSERVER]=oauth2-authserver )

API_LOGS=( [GATEWAY]=gateway.log \
    [PRODUCERS]=producers.log \
    [CONFIGURATION]=configuration.log \
    [PROFILE]=profile.log \
    [AUTHSERVER]=authserver.log )

# получаем имя ключа из массива (GATEWAY и т.д.)
for service in ${!API_SERVICES[@]}; do

    # используя имя ключа в виде имени сервиса - получаем значение этой пары ключ-значение
    # например, для GATEWAY - это будет api-gateway
    # по значению находим контейнер (grep), и получаем его ID (awk - print первое поле)
    container_id=$(docker ps | grep ${API_SERVICES[$service]} | awk '{print $1}')

    # используя имя ключа в виде имени сервиса - находим в массиве API_LOGS значение
    # например, для GATEWAY - это будет gateway.log
    log_name=${API_LOGS[$service]}
    echo Service: $service Container ID: $container_id Log file: $log_name

    # и используя $container_id (666555444) и $log_name (gateway.log)
    # выполняем docker logs -f перенаправляя STDERR и STDOUT в соответствующий файл
    docker logs -f $container_id >> $log_name 2>&1 &
done

Запускаем:

ubuntu@ip-10-5-3-54:~$ ./logs.sh 
Service: CONFIGURATION Container ID: 1884543d61b1 Log file: configuration.log
Service: PROFILE Container ID: 65be0b7bb07e Log file: profile.log
Service: PRODUCERS Container ID: cbf2394197bc Log file: producers.log
Service: GATEWAY Container ID: 63937e07a5cf Log file: gateway.log
Service: AUTHSERVER Container ID: 947a92a1a629 Log file: authserver.log

Проверяем:

ubuntu@ip-10-5-3-54:~$ tail -f *.log
==> authserver.log <==
profile: 15:46:40.248 o.a.tomcat.util.net.NioSelectorPool - Using a shared selector for servlet write/read

==> configuration.log <==
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:138)
        at 

==> gateway.log <==
profile: 16:05:11.247 o.s.b.a.e.mvc.EndpointHandlerMapping - Returning handler method [public java.lang.Object 
...

Готово.