1
0
Fork 0
mirror of https://github.com/sdr-enthusiasts/docker-adsb-ultrafeeder.git synced 2024-11-22 05:40:10 +00:00

improve s6wrap usage, make sure service stop is respected

alias can only be used in interactive shell scripts, replace with bash array var
This commit is contained in:
Matthias Wirth 2023-05-05 10:16:32 +02:00
parent 46d77e8117
commit 75ee015381
6 changed files with 75 additions and 72 deletions

View file

@ -20,6 +20,4 @@ source /scripts/common
# If not, see <https://www.gnu.org/licenses/>. # If not, see <https://www.gnu.org/licenses/>.
#--------------------------------------------------------------------------------------------- #---------------------------------------------------------------------------------------------
alias s6wrap='s6wrap --quiet' [[ -f /.CONTAINER_VERSION ]] && s6wrap --quiet --prepend=01-print-container-version --timestamps --args echo "Container Version: $(cat /.CONTAINER_VERSION), build date $(stat -c '%y' /.CONTAINER_VERSION |sed 's|\(.*\)\.[0-9]* \(.*\)|\1 \2|g')" || true
[[ -f /.CONTAINER_VERSION ]] && s6wrap --prepend=01-print-container-version --timestamps --args echo "Container Version: $(cat /.CONTAINER_VERSION), build date $(stat -c '%y' /.CONTAINER_VERSION |sed 's|\(.*\)\.[0-9]* \(.*\)|\1 \2|g')" || true

View file

@ -25,4 +25,4 @@ then
echo "$UUID" > /run/uuid echo "$UUID" > /run/uuid
fi fi
exit 0 exit 0

View file

@ -17,10 +17,12 @@
# If not, see <https://www.gnu.org/licenses/>. # If not, see <https://www.gnu.org/licenses/>.
#--------------------------------------------------------------------------------------------- #---------------------------------------------------------------------------------------------
APPNAME="mlat-client" trap "pkill -P $$ || true; s6wrap --quiet --timestamps --prepend=mlat-client --args echo 'service stopping'; exit 0" SIGTERM SIGINT SIGHUP SIGQUIT
alias s6wrap='s6wrap --quiet'
s6wrap --prepend="${APPNAME}" --timestamps --args echo "Started as an s6 service" APPNAME="mlat-client"
s6wrap=(s6wrap --quiet --timestamps --prepend="${APPNAME}")
"${s6wrap[@]}" --args echo "Started as an s6 service"
source /scripts/common source /scripts/common
source /scripts/interpret_ultrafeeder_config source /scripts/interpret_ultrafeeder_config
@ -32,28 +34,28 @@ declare -A pid_array
if [[ -z "${MLAT_CONFIG}" ]] if [[ -z "${MLAT_CONFIG}" ]]
then then
s6wrap --prepend="${APPNAME}" --timestamps --args echo "Warning: MLAT_CONFIG not defined - MLAT will be disabled." "${s6wrap[@]}" --args echo "Warning: MLAT_CONFIG not defined - MLAT will be disabled."
sleep infinity exec sleep infinity
fi fi
if [[ -z "${MLAT_USER}" ]] && [[ -z "${UUID}" ]] if [[ -z "${MLAT_USER}" ]] && [[ -z "${UUID}" ]]
then then
s6wrap --prepend="${APPNAME}" --timestamps --args echo "ERROR: either UUID or MLAT_USER must be defined - MLAT will be disabled." "${s6wrap[@]}" --args echo "ERROR: either UUID or MLAT_USER must be defined - MLAT will be disabled."
sleep infinity exec sleep infinity
fi fi
if [[ -z "$LAT$READSB_LAT" ]]; then if [[ -z "$LAT$READSB_LAT" ]]; then
s6wrap --prepend="${APPNAME}" --timestamps --args echo "ERROR: READSB_LAT or LAT must be defined - MLAT will be disabled." "${s6wrap[@]}" --args echo "ERROR: READSB_LAT or LAT must be defined - MLAT will be disabled."
sleep infinity exec sleep infinity
fi fi
if [[ -z "$LONG$READSB_LON" ]]; then if [[ -z "$LONG$READSB_LON" ]]; then
s6wrap --prepend="${APPNAME}" --timestamps --args echo "ERROR: READSB_LON or LONG must be defined - MLAT will be disabled." "${s6wrap[@]}" --args echo "ERROR: READSB_LON or LONG must be defined - MLAT will be disabled."
sleep infinity exec sleep infinity
fi fi
if [[ -z "$ALT$READSB_ALT" ]]; then if [[ -z "$ALT$READSB_ALT" ]]; then
s6wrap --prepend="${APPNAME}" --timestamps --args echo "ERROR: READSB_ALT or ALT must be defined - MLAT will be disabled." "${s6wrap[@]}" --args echo "ERROR: READSB_ALT or ALT must be defined - MLAT will be disabled."
sleep infinity exec sleep infinity
fi fi
# MLAT_CONFIG has the following format: # MLAT_CONFIG has the following format:
@ -69,6 +71,21 @@ MLAT_CONFIG="${MLAT_CONFIG#"${MLAT_CONFIG%%[![:space:]]*}"}" # strip leading s
MLAT_CONFIG="${MLAT_CONFIG//; /;}" MLAT_CONFIG="${MLAT_CONFIG//; /;}"
readarray -td ";" mlat_configs < <(printf '%s' "${MLAT_CONFIG}") readarray -td ";" mlat_configs < <(printf '%s' "${MLAT_CONFIG}")
# wait until readsb is established...
if ! pgrep readsb >/dev/null; then
if [[ -z "${LOGLEVEL}" ]] || [[ "${LOGLEVEL,,}" == "verbose" ]]; then
"${s6wrap[@]}" --args echo "Delaying start of MLAT client(s) until container is established..."
fi
while ! pgrep readsb >/dev/null
do
sleep 2 &; wait $!
done
# wait 2 seconds after readsb process exists
sleep 2 &; wait $!
fi
# Now loop through the MLAT_CONFIG items and start up an Mlat_client for each of them: # Now loop through the MLAT_CONFIG items and start up an Mlat_client for each of them:
for instance in "${mlat_configs[@]}" for instance in "${mlat_configs[@]}"
do do
@ -79,10 +96,10 @@ do
# Check if the params array has values for the mandatory elements: # Check if the params array has values for the mandatory elements:
if [[ -z "${params[0]}" ]] || [[ -z "${params[1]}" ]] if [[ -z "${params[0]}" ]] || [[ -z "${params[1]}" ]]
then then
s6wrap --prepend="${APPNAME}" --timestamps --args echo "ERROR -- MLAT_CONFIG is malformed: \"${instance}\". Stopping MLAT execution." "${s6wrap[@]}" --args echo "ERROR -- MLAT_CONFIG is malformed: \"${instance}\". Stopping MLAT execution."
# shellcheck disable=SC2046 # shellcheck disable=SC2046
kill $(ps -s $$ -o pid=) kill $(ps -s $$ -o pid=)
sleep infinity exec sleep infinity
fi fi
# Now process the the arguments # Now process the the arguments
@ -92,7 +109,7 @@ do
# If the argument isn't any of the above, then it's an "extra argument" # If the argument isn't any of the above, then it's an "extra argument"
unset uuid_arg lat_arg lon_arg alt_arg input_connect_arg return_port_arg extra_args unset uuid_arg lat_arg lon_arg alt_arg input_connect_arg return_port_arg extra_args
for ((i=2; i<${#params[*]}; i++)) for ((i=2; i<${#params[*]}; i++))
do do
if [[ -n "${params[i]}" ]] && [[ "${params[i]}" =~ ^[0-9]+$ ]]; then if [[ -n "${params[i]}" ]] && [[ "${params[i]}" =~ ^[0-9]+$ ]]; then
@ -124,6 +141,8 @@ do
MLAT_PARAM=(--input-type "${MLAT_INPUT_TYPE:-auto}") MLAT_PARAM=(--input-type "${MLAT_INPUT_TYPE:-auto}")
MLAT_PARAM+=(--server "${params[0]}:${params[1]}") MLAT_PARAM+=(--server "${params[0]}:${params[1]}")
servername=${params[0]}
# add return port: # add return port:
[ -n "${return_port_arg}" ] && MLAT_PARAM+=("--results beast,listen,${return_port_arg}") || true [ -n "${return_port_arg}" ] && MLAT_PARAM+=("--results beast,listen,${return_port_arg}") || true
@ -134,7 +153,7 @@ do
MLAT_PARAM+=(--user "${MLAT_USER}") MLAT_PARAM+=(--user "${MLAT_USER}")
else else
rnd="${RANDOM}" rnd="${RANDOM}"
s6wrap --prepend="${APPNAME}" --timestamps --args echo "WARNING: MLAT_USER is not set - using random number \"${rnd}\" as MLAT_USER" "${s6wrap[@]}" --args echo "WARNING: MLAT_USER is not set - using random number \"${rnd}\" as MLAT_USER"
MLAT_PARAM+=(--user "${rnd}") MLAT_PARAM+=(--user "${rnd}")
fi fi
@ -169,11 +188,7 @@ do
elif [ -n "${UUID}" ]; then elif [ -n "${UUID}" ]; then
MLAT_PARAM+=("--uuid ${UUID}") MLAT_PARAM+=("--uuid ${UUID}")
else else
# generate a random UUID "${s6wrap[@]}" --args echo "WARNING: UUID is not defined, proceeding without UUID"
UUID="$(cat /proc/sys/kernel/random/uuid)"
[[ -z "${UUID}" ]] && UUID="$(printf '00000000-ffff-aaaa-%04x-%012x\n' "$RANDOM" "$(date +%s)")"
s6wrap --prepend="${APPNAME}" --timestamps --args echo "WARNING: UUID is not defined - using randomized uuid \"${UUID}\""
MLAT_PARAM+=("--uuid ${UUID}")
fi fi
# Now add the extra_args, if any: # Now add the extra_args, if any:
@ -184,27 +199,20 @@ do
# shellcheck disable=SC2048,SC2086 # shellcheck disable=SC2048,SC2086
execstring="$(echo ${MLAT_CMD} ${MLAT_PARAM[*]} | xargs)" execstring="$(echo ${MLAT_CMD} ${MLAT_PARAM[*]} | xargs)"
# stagger by 1 second so they don't all start at the same time
sleep 1 &; wait $!
# ------------------------------------------------ # ------------------------------------------------
# Ready to launch, but wait until readsb is established...
if ! pgrep readsb >/dev/null; then
s6wrap --prepend="${APPNAME}" --timestamps --args echo "Delaying start of MLAT client(s) until container is established..."
while ! pgrep readsb >/dev/null
do
sleep 2
done
fi
sleep 10 # sleep a bit so everything is well established - starting readsb may take a bit
# run this Mlat_client instance in the background: # run this Mlat_client instance in the background:
s6wrap --prepend="${APPNAME}" --timestamps --args echo "starting: ${MLAT_CMD} ${MLAT_PARAM[*]}"
#shellcheck disable=SC2069,SC2086 #shellcheck disable=SC2069,SC2086
if [[ -z "${LOGLEVEL}" ]] || [[ "${LOGLEVEL,,}" == "verbose" ]]; then if [[ -z "${LOGLEVEL}" ]] || [[ "${LOGLEVEL,,}" == "verbose" ]]; then
{ exec s6wrap --prepend="${APPNAME}][${params[0]}" --timestamps --args ${execstring}; } & "${s6wrap[@]}" --prepend="${APPNAME}][${servername}" --args echo "starting: ${MLAT_CMD} ${MLAT_PARAM[*]}"
"${s6wrap[@]}" --prepend="${APPNAME}][${servername}" --args ${execstring} &
elif [[ "${LOGLEVEL,,}" == "error" ]]; then elif [[ "${LOGLEVEL,,}" == "error" ]]; then
{ exec s6wrap --prepend="${APPNAME}][${params[0]}" --timestamps --args ${execstring} 2>&1 >/dev/null; } & "${s6wrap[@]}" --ignore-stdout --prepend="${APPNAME}][${servername}" --args ${execstring} &
elif [[ "${LOGLEVEL,,}" == "none" ]]; then elif [[ "${LOGLEVEL,,}" == "none" ]]; then
{ exec ${execstring} >/dev/null 2>/dev/null; } & "${s6wrap[@]}" --ignore-stderr --ignore-stdout --prepend="${APPNAME}][${servername}" --args ${execstring} &
fi fi
# pid_array is indexed by the PID of each mlat_client and contains the MLAT_PARAMs for that instance # pid_array is indexed by the PID of each mlat_client and contains the MLAT_PARAMs for that instance
@ -212,7 +220,7 @@ do
pid_array[$!]="${MLAT_PARAM[*]}" pid_array[$!]="${MLAT_PARAM[*]}"
done done
sleep 5 sleep 5 &; wait $!
# All MLAT Clients are up, so set the flag. This flag is read by MLATHUB as a sign that it's # All MLAT Clients are up, so set the flag. This flag is read by MLATHUB as a sign that it's
# safe to start up # safe to start up
@ -226,26 +234,26 @@ do
if ! kill -0 "${mlat_pid}" >/dev/null 2>&1 if ! kill -0 "${mlat_pid}" >/dev/null 2>&1
then then
# it exited - let's restart: # it exited - let's restart:
sleep "${RESTARTTIMER}" sleep "${RESTARTTIMER}" &; wait $!
servername="$(awk '{print $4}' <<< "${pid_array[$mlat_pid]}")" servername="$(awk '{print $4}' <<< "${pid_array[$mlat_pid]}")"
servername="${servername%%:*}" servername="${servername%%:*}"
[[ "${LOGLEVEL,,}" != "none" ]] && s6wrap --prepend="${APPNAME}[${servername}" --timestamps --args echo "MLAT_Client ${servername} exited. Attempting to restart." || true [[ "${LOGLEVEL,,}" != "none" ]] && "${s6wrap[@]}" --prepend="${APPNAME}[${servername}" --args echo "MLAT_Client ${servername} exited. Attempting to restart." || true
# shellcheck disable=SC2086 # shellcheck disable=SC2086
execstring="$(echo ${MLAT_CMD} ${pid_array[$mlat_pid]} | xargs)" execstring="$(echo ${MLAT_CMD} ${pid_array[$mlat_pid]} | xargs)"
#shellcheck disable=SC2069,SC2086 #shellcheck disable=SC2069,SC2086
if [[ -z "${LOGLEVEL}" ]] || [[ "${LOGLEVEL,,}" == "verbose" ]]; then if [[ -z "${LOGLEVEL}" ]] || [[ "${LOGLEVEL,,}" == "verbose" ]]; then
{ exec s6wrap --prepend="${APPNAME}][${servername}" --timestamps --args ${execstring} 2>&1; } & "${s6wrap[@]}" --prepend="${APPNAME}][${servername}" --args ${execstring} &
elif [[ "${LOGLEVEL,,}" == "error" ]]; then elif [[ "${LOGLEVEL,,}" == "error" ]]; then
{ exec s6wrap --prepend="${APPNAME}][${servername}" --timestamps --args ${execstring} 2>&1 >/dev/null; } & "${s6wrap[@]}" --ignore-stdout --prepend="${APPNAME}][${servername}" --args ${execstring} &
elif [[ "${LOGLEVEL,,}" == "none" ]]; then elif [[ "${LOGLEVEL,,}" == "none" ]]; then
{ exec ${execstring} >/dev/null 2>/dev/null; } & "${s6wrap[@]}" --ignore-stderr --ignore-stdout --prepend="${APPNAME}][${servername}" --args ${execstring} &
fi fi
pid_array[$!]="${pid_array[${mlat_pid}]}" pid_array[$!]="${pid_array[${mlat_pid}]}"
unset "pid_array[${mlat_pid}]" unset "pid_array[${mlat_pid}]"
fi fi
done done
sleep 10 sleep 10 &; wait $!
done done

View file

@ -4,15 +4,15 @@
APPNAME="mlathub" APPNAME="mlathub"
source /scripts/common source /scripts/common
source /scripts/interpret_ultrafeeder_config source /scripts/interpret_ultrafeeder_config
alias s6wrap='s6wrap --quiet' s6wrap=(s6wrap --quiet --timestamps --prepend="${APPNAME}")
if [[ -z "${MLAT_CONFIG}" ]] && [[ -z "$MLATHUB_NET_CONNECTOR" ]]; then if [[ -z "${MLAT_CONFIG}" ]] && [[ -z "$MLATHUB_NET_CONNECTOR" ]]; then
s6wrap --prepend="${APPNAME}" --timestamps --args echo "No MLAT servers have been defined in MLAT_CONFIG and no external sources have been defined in MLATHUB_NET_CONNECTOR - no need to start MLATHUB" "${s6wrap[@]}" --args echo "No MLAT servers have been defined in MLAT_CONFIG and no external sources have been defined in MLATHUB_NET_CONNECTOR - no need to start MLATHUB"
sleep infinity sleep infinity
fi fi
if chk_enabled "${MLATHUB_DISABLED}"; then if chk_enabled "${MLATHUB_DISABLED}"; then
s6wrap --prepend="${APPNAME}" --timestamps --args echo "MLATHUB is disabled." "${s6wrap[@]}" --args echo "MLATHUB is disabled."
sleep infinity sleep infinity
fi fi
@ -60,7 +60,7 @@ done
if (( mlat_result_sources == 0 )) if (( mlat_result_sources == 0 ))
then then
s6wrap --prepend="${APPNAME}" --timestamps --args echo "No MLAT servers have been defined in MLAT_CONFIG - no need to start MLATHUB" "${s6wrap[@]}" --args echo "No MLAT servers have been defined in MLAT_CONFIG - no need to start MLATHUB"
sleep infinity sleep infinity
fi fi
@ -110,7 +110,9 @@ MLATHUB_CMD+=("--net-heartbeat=${READSB_NET_HEARTBEAT:-35}")
if [[ ! -f /run/mlathub_up ]] if [[ ! -f /run/mlathub_up ]]
then then
s6wrap --prepend="${APPNAME}" --timestamps --args echo "Delaying MLAT hub start until container is established..." if [[ -z "${LOGLEVEL}" ]] || [[ "${LOGLEVEL,,}" == "verbose" ]]; then
"${s6wrap[@]}" --args echo "Delaying MLAT hub start until container is established..."
fi
while [[ ! -f /run/mlathub_up ]] while [[ ! -f /run/mlathub_up ]]
do do
sleep 2 sleep 2
@ -118,16 +120,13 @@ then
fi fi
sleep 5 # sleep a bit so everything is well established sleep 5 # sleep a bit so everything is well established
s6wrap --prepend="${APPNAME}" --timestamps --args echo "Starting MLATHUB..." "${s6wrap[@]}" --args echo "Starting MLATHUB..."
# shellcheck disable=SC2086,SC2069 # shellcheck disable=SC2086,SC2069
if [[ -z "${LOGLEVEL}" ]] || [[ "${LOGLEVEL,,}" == "verbose" ]]; then if [[ -z "${LOGLEVEL}" ]] || [[ "${LOGLEVEL,,}" == "verbose" ]]; then
s6wrap --prepend="${APPNAME}" --timestamps --args "${MLATHUB_BIN}" "${MLATHUB_CMD[@]}" $MLATHUB_EXTRA_ARGS 2>&1 exec "${s6wrap[@]}" --args "${MLATHUB_BIN}" "${MLATHUB_CMD[@]}" $MLATHUB_EXTRA_ARGS
elif [[ "${LOGLEVEL,,}" == "error" ]]; then elif [[ "${LOGLEVEL,,}" == "error" ]]; then
s6wrap --prepend="${APPNAME}" --timestamps --args "${MLATHUB_BIN}" "${MLATHUB_CMD[@]}" $MLATHUB_EXTRA_ARGS 2>&1 >/dev/null exec "${s6wrap[@]}" --ignore-stdout --args "${MLATHUB_BIN}" "${MLATHUB_CMD[@]}" $MLATHUB_EXTRA_ARGS
elif [[ "${LOGLEVEL,,}" == "none" ]]; then elif [[ "${LOGLEVEL,,}" == "none" ]]; then
s6wrap --prepend="${APPNAME}" --timestamps --args "${MLATHUB_BIN}" "${MLATHUB_CMD[@]}" $MLATHUB_EXTRA_ARGS >/dev/null 2>/dev/null exec "${s6wrap[@]}" --ignore-stdtout --ignore-stderr --args "${MLATHUB_BIN}" "${MLATHUB_CMD[@]}" $MLATHUB_EXTRA_ARGS
fi fi
s6wrap --prepend="${APPNAME}" --timestamps --args echo "WARNING: The mlathub instance has exited. Restarting in 10 seconds."
sleep 10

View file

@ -8,7 +8,9 @@ if chk_enabled "$PROMETHEUS_ENABLE"; then
do do
sleep 1 sleep 1
done done
echo -e "HTTP/1.1 200 OK\nContent-Type: text/plain\n\n$(cat /run/readsb-prometheus.prom)" | ncat -l 9274 > /dev/null 2>&1 trap "pkill -P $$ || true; s6wrap --timestamps --prepend=prometheus-readsb --quiet --args echo 'service stopping'; exit 0" SIGTERM SIGINT SIGHUP SIGQUIT
echo -e "HTTP/1.1 200 OK\nContent-Type: text/plain\n\n$(cat /run/readsb-prometheus.prom)" | ncat -l 9274 > /dev/null 2>&1 &
wait
else else
sleep infinity exec sleep infinity
fi fi

View file

@ -5,7 +5,7 @@ APPNAME="readsb"
source /scripts/common source /scripts/common
source /scripts/interpret_ultrafeeder_config source /scripts/interpret_ultrafeeder_config
alias s6wrap='s6wrap --quiet' s6wrap=(s6wrap --quiet --timestamps --prepend="${APPNAME}")
mkdir -p /run/readsb mkdir -p /run/readsb
@ -65,12 +65,12 @@ if ! chk_enabled "$READSB_NET_SBS_DISABLE_REDUCE"; then
fi fi
if chk_enabled "${READSB_FORWARD_MLAT}"; then if chk_enabled "${READSB_FORWARD_MLAT}"; then
s6wrap --prepend="${APPNAME}" --timestamps --args echo "WARNING -- READSB_FORWARD_MLAT has been set! Do not feed the output of this container to any aggregators!" "${s6wrap[@]}" --quiet --args echo "WARNING -- READSB_FORWARD_MLAT has been set! Do not feed the output of this container to any aggregators!"
READSB_CMD+=("--forward-mlat") READSB_CMD+=("--forward-mlat")
fi fi
if chk_enabled "${READSB_FORWARD_MLAT_SBS}"; then if chk_enabled "${READSB_FORWARD_MLAT_SBS}"; then
s6wrap --prepend="${APPNAME}" --timestamps --args echo "WARNING -- READSB_FORWARD_MLAT_SBS has been set! Do not feed the SBS (BaseStation) output of this container to any aggregators!" "${s6wrap[@]}" --quiet --args echo "WARNING -- READSB_FORWARD_MLAT_SBS has been set! Do not feed the SBS (BaseStation) output of this container to any aggregators!"
READSB_CMD+=("--forward-mlat-sbs") READSB_CMD+=("--forward-mlat-sbs")
fi fi
@ -322,14 +322,10 @@ fi
# shellcheck disable=SC2086,SC2069 # shellcheck disable=SC2086,SC2069
if [[ -z "${LOGLEVEL}" ]] || [[ "${LOGLEVEL,,}" == "verbose" ]]; then if [[ -z "${LOGLEVEL}" ]] || [[ "${LOGLEVEL,,}" == "verbose" ]]; then
s6wrap --prepend="${APPNAME}" --timestamps --args "${READSB_BIN}" "${READSB_CMD[@]}" $READSB_EXTRA_ARGS 2>&1 exec "${s6wrap[@]}" --args "${READSB_BIN}" "${READSB_CMD[@]}" $READSB_EXTRA_ARGS
elif [[ "${LOGLEVEL,,}" == "error" ]]; then elif [[ "${LOGLEVEL,,}" == "error" ]]; then
s6wrap --prepend="${APPNAME}" --timestamps --args "${READSB_BIN}" "${READSB_CMD[@]}" $READSB_EXTRA_ARGS 2>&1 1>/dev/null exec "${s6wrap[@]}" --quiet --ignore-stdout --args "${READSB_BIN}" "${READSB_CMD[@]}" $READSB_EXTRA_ARGS
elif [[ "${LOGLEVEL,,}" == "none" ]]; then elif [[ "${LOGLEVEL,,}" == "none" ]]; then
"${READSB_BIN}" "${READSB_CMD[@]}" $READSB_EXTRA_ARGS >/dev/null 2>/dev/null exec "${s6wrap[@]}" --quiet --ignore-stdout --ignore-stderr --args "${READSB_BIN}" "${READSB_CMD[@]}" $READSB_EXTRA_ARGS
fi fi
s6wrap --prepend="${APPNAME}" --timestamps --args echo "WARNING: The main readsb instance has exited. Restarting in 10 seconds."
sleep 10