work version

Automatica_1_v2
Sergey Revyakin 12 hours ago
parent 5c215efbf6
commit 30b61acdd6

@ -191,6 +191,8 @@ def receive_data():
try: try:
result = update_drone_streak(freq, prediction_list[0]) result = update_drone_streak(freq, prediction_list[0])
if str(freq)==2400:
result=0
data_to_send={ data_to_send={
'freq': str(freq), 'freq': str(freq),
'amplitude': result 'amplitude': result

@ -1,109 +1,125 @@
# echo 'RUN_ONCE=1 CAPTURE_ORDER=433 /home/sergei/work/DroneDetector/DroneDetector/capture_hourly.sh >> /home/sergei/capture_hourly_night.log 2>&1' | sudo at 15:00 2026-07-22
#!/usr/bin/env bash #!/usr/bin/env bash
set -Eeuo pipefail set -Eeuo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SCRIPT_OWNER="${CAPTURE_USER:-$(stat -c %U "$SCRIPT_DIR")}" SCRIPT_OWNER="${CAPTURE_USER:-$(stat -c %U "$SCRIPT_DIR")}"
SCRIPT_OWNER_HOME="$(getent passwd "$SCRIPT_OWNER" | cut -d: -f6)" SCRIPT_OWNER_HOME="$(getent passwd "$SCRIPT_OWNER" | cut -d: -f6 || true)"
cd "$SCRIPT_DIR" cd "$SCRIPT_DIR"
source "$SCRIPT_DIR/.env"
############################ ############################
# НАСТРОЙКИ # НАСТРОЙКИ
############################ ############################
BASE_DIR="/mnt/nvme1/dataset/noise2" BASE_DIR="${BASE_DIR:-/mnt/nvme1/dataset_5_5_26}"
# Путь к python из venv
PYTHON_BIN="${PYTHON_BIN:-$SCRIPT_DIR/.venv-sdr/bin/python}" PYTHON_BIN="${PYTHON_BIN:-$SCRIPT_DIR/.venv-sdr/bin/python}"
# Путь к headless скрипту
SCRIPT_PATH="${SCRIPT_PATH:-$SCRIPT_DIR/scripts_nn/data_saver_headless.py}" SCRIPT_PATH="${SCRIPT_PATH:-$SCRIPT_DIR/scripts_nn/data_saver_headless.py}"
ENV_FILE="${ENV_FILE:-$SCRIPT_DIR/.env}"
RUN_ONCE="${RUN_ONCE:-0}" RUN_ONCE="${RUN_ONCE:-0}"
CAPTURE_LOG_FILE="${CAPTURE_LOG_FILE:-$BASE_DIR/capture_hourly.log}" CAPTURE_LOG_FILE="${CAPTURE_LOG_FILE:-$BASE_DIR/capture_hourly.log}"
SYSTEMCTL_BIN=(systemctl) SYSTEMCTL_BIN=(systemctl)
CURRENT_CAPTURE_PID="" CURRENT_CAPTURE_PID=""
CURRENT_MOCK_PID=""
CURRENT_SERVICE_UNIT="" CURRENT_SERVICE_UNIT=""
STOPPED_SERVICE_UNIT=""
# Лимиты # Лимиты
PER_FREQ_LIMIT_GIB="${PER_FREQ_LIMIT_GIB:-12}"
TOTAL_LIMIT_GIB="${TOTAL_LIMIT_GIB:-380}"
PER_FREQ_LIMIT_BYTES=$((PER_FREQ_LIMIT_GIB * 1024 * 1024 * 1024))
TOTAL_LIMIT_BYTES=$((TOTAL_LIMIT_GIB * 1024 * 1024 * 1024))
lim_all=48 # Для обычного hourly можно поставить 3600.
PER_FREQ_LIMIT_BYTES=$((12 * 1024 * 1024 * 1024)) # GiB на частоту за запуск # Для RUN_ONCE это почти не важно.
TOTAL_LIMIT_BYTES=$((lim_all * 1024 * 1024 * 1024)) # общий лимит GiB CYCLE_SECONDS="${CYCLE_SECONDS:-100}"
CYCLE_SECONDS=1 # один цикл в час
# Параметры SDR # Параметры SDR
SAMP_RATE="20e6" SAMP_RATE="${SAMP_RATE:-20e6}"
SPLIT_SIZE="400000" SPLIT_SIZE="${SPLIT_SIZE:-400000}"
DELAY="0.04" DELAY="${DELAY:-0.15}"
RF_GAIN="12" RF_GAIN="${RF_GAIN:-12}"
IF_GAIN="30" IF_GAIN="${IF_GAIN:-30}"
BB_GAIN="36" BB_GAIN="${BB_GAIN:-36}"
############################ ############################
# ЧАСТОТЫ И SERIAL ИЗ ENV # MOCK SENDER
############################ ############################
ORDER=(2400) CAPTURE_MOCK_SEND_ENABLED="${CAPTURE_MOCK_SEND_ENABLED:-1}"
CAPTURE_MOCK_HOST="${CAPTURE_MOCK_HOST:-127.0.0.1}"
CAPTURE_MOCK_INTERVAL_SECONDS="${CAPTURE_MOCK_INTERVAL_SECONDS:-1}"
CAPTURE_MOCK_TIMEOUT_SECONDS="${CAPTURE_MOCK_TIMEOUT_SECONDS:-0.3}"
CAPTURE_MOCK_LOG_SUCCESS="${CAPTURE_MOCK_LOG_SUCCESS:-0}"
############################
# ВСПОМОГАТЕЛЬНОЕ
############################
declare -A SERIAL log() {
declare -A FREQ_HZ printf '[%s] %s\n' "$(date '+%F %T')" "$*"
declare -A SERVICE_UNIT }
SERIAL[433]="$hack_433" systemctl_run() {
FREQ_HZ[433]="433000000" "${SYSTEMCTL_BIN[@]}" "$@"
}
SERIAL[750]="$hack_750" env_get() {
FREQ_HZ[750]="750000000" local key="$1"
local default="${2:-}"
if [[ ! -f "$ENV_FILE" ]]; then
printf '%s\n' "$default"
return 0
fi
SERIAL[915]="$hack_915" awk -v key="$key" -v default="$default" '
FREQ_HZ[915]="915000000" BEGIN { found = 0 }
SERIAL[1200]="$hack_1200" $0 ~ "^[[:space:]]*" key "=" {
FREQ_HZ[1200]="1200000000" value = $0
SERIAL[2400]="$hack_2400" sub("^[[:space:]]*" key "=", "", value)
FREQ_HZ[2400]="2400000000" sub("[[:space:]]+#.*$", "", value)
gsub("^[[:space:]]+|[[:space:]]+$", "", value)
SERIAL[3300]="$hack_3300" if ((substr(value, 1, 1) == "\"" && substr(value, length(value), 1) == "\"") ||
FREQ_HZ[3300]="3300000000" (substr(value, 1, 1) == "'"'"'" && substr(value, length(value), 1) == "'"'"'")) {
value = substr(value, 2, length(value) - 2)
}
SERIAL[4500]="$hack_4500" print value
FREQ_HZ[4500]="4500000000" found = 1
exit
}
SERIAL[5200]="$hack_5200" END {
FREQ_HZ[5200]="5200000000" if (!found) {
print default
}
}
' "$ENV_FILE"
}
SERIAL[5800]="$hack_5800" mock_bool_enabled() {
FREQ_HZ[5800]="5800000000" case "${1,,}" in
1|true|yes|on) return 0 ;;
*) return 1 ;;
esac
}
SERVICE_UNIT[433]="dronedetector-sdr-433.service" mock_url() {
SERVICE_UNIT[750]="dronedetector-sdr-750.service" local port endpoint
SERVICE_UNIT[915]="dronedetector-sdr-915.service"
SERVICE_UNIT[1200]="dronedetector-sdr-1200.service"
SERVICE_UNIT[2400]="dronedetector-sdr-2400.service"
SERVICE_UNIT[3300]="dronedetector-sdr-3300.service"
SERVICE_UNIT[4500]="dronedetector-sdr-4500.service"
SERVICE_UNIT[5200]="dronedetector-sdr-5200.service"
SERVICE_UNIT[5800]="dronedetector-sdr-5800.service"
############################ port="${CAPTURE_MOCK_PORT:-$(env_get locport "$(env_get GENERAL_SERVER_PORT 5010)")}"
# ВСПОМОГАТЕЛЬНОЕ endpoint="${CAPTURE_MOCK_ENDPOINT:-$(env_get freq_endpoint process_data)}"
############################
log() { endpoint="${endpoint#/}"
printf '[%s] %s\n' "$(date '+%F %T')" "$*"
}
systemctl_run() { printf 'http://%s:%s/%s' "$CAPTURE_MOCK_HOST" "$port" "$endpoint"
"${SYSTEMCTL_BIN[@]}" "$@"
} }
service_exists() { service_exists() {
@ -111,10 +127,60 @@ service_exists() {
systemctl_run show "$unit" >/dev/null 2>&1 systemctl_run show "$unit" >/dev/null 2>&1
} }
service_is_active() {
local unit="$1"
systemctl_run is-active --quiet "$unit" >/dev/null 2>&1
}
dir_size_bytes() {
local path="$1"
if [[ -e "$path" ]]; then
du -sb "$path" 2>/dev/null | awk '{print $1}'
else
echo 0
fi
}
total_size_bytes() {
dir_size_bytes "$BASE_DIR"
}
terminate_pid() {
local pid="${1:-}"
if [[ -z "$pid" ]]; then
return 0
fi
if ! kill -0 "$pid" 2>/dev/null; then
return 0
fi
kill -TERM "$pid" 2>/dev/null || true
for _ in {1..10}; do
if ! kill -0 "$pid" 2>/dev/null; then
break
fi
sleep 1
done
if kill -0 "$pid" 2>/dev/null; then
log "PID=$pid не завершился по TERM, отправляю KILL"
kill -KILL "$pid" 2>/dev/null || true
fi
wait "$pid" 2>/dev/null || true
}
stop_band_service() { stop_band_service() {
local band="$1" local band="$1"
local unit="${SERVICE_UNIT[$band]:-}" local unit="${SERVICE_UNIT[$band]:-}"
STOPPED_SERVICE_UNIT=""
CURRENT_SERVICE_UNIT=""
if [[ -z "$unit" ]]; then if [[ -z "$unit" ]]; then
log "Для band=$band не найден service unit" log "Для band=$band не найден service unit"
return 0 return 0
@ -126,33 +192,137 @@ stop_band_service() {
fi fi
log "Останавливаю service $unit перед записью band=$band" log "Останавливаю service $unit перед записью band=$band"
systemctl_run stop "$unit"
if systemctl_run stop "$unit"; then
log "Service $unit остановлен или уже был остановлен"
else
log "Не удалось остановить service $unit"
fi
STOPPED_SERVICE_UNIT="$unit"
CURRENT_SERVICE_UNIT="$unit" CURRENT_SERVICE_UNIT="$unit"
return 0
} }
start_current_service() { start_stopped_service() {
if [[ -z "$CURRENT_SERVICE_UNIT" ]]; then local unit="${STOPPED_SERVICE_UNIT:-}"
if [[ -z "$unit" ]]; then
return 0 return 0
fi fi
log "Запускаю service $CURRENT_SERVICE_UNIT после записи" log "Запускаю service $unit после записи"
systemctl_run start "$CURRENT_SERVICE_UNIT"
if systemctl_run start "$unit"; then
log "Service $unit запущен"
else
log "Не удалось запустить service $unit"
systemctl_run status "$unit" --no-pager || true
fi
STOPPED_SERVICE_UNIT=""
CURRENT_SERVICE_UNIT="" CURRENT_SERVICE_UNIT=""
} }
start_mock_sender() {
local band="$1"
local log_file="$2"
local url
CURRENT_MOCK_PID=""
if ! mock_bool_enabled "$CAPTURE_MOCK_SEND_ENABLED"; then
log "Mock sender отключен CAPTURE_MOCK_SEND_ENABLED=$CAPTURE_MOCK_SEND_ENABLED"
return 0
fi
url="$(mock_url)"
log "Старт mock sender band=$band url=$url amplitude=0 interval=${CAPTURE_MOCK_INTERVAL_SECONDS}s"
"$PYTHON_BIN" - \
"$url" \
"$band" \
"$CAPTURE_MOCK_INTERVAL_SECONDS" \
"$CAPTURE_MOCK_TIMEOUT_SECONDS" \
"$CAPTURE_MOCK_LOG_SUCCESS" \
>>"$log_file" 2>&1 <<'PY' &
import json
import sys
import time
import urllib.request
url = sys.argv[1]
freq = str(sys.argv[2])
interval = float(sys.argv[3])
timeout = float(sys.argv[4])
log_success = sys.argv[5].lower() in {"1", "true", "yes", "on"}
payload = json.dumps({"freq": freq, "amplitude": 0}).encode("utf-8")
headers = {"Content-Type": "application/json"}
print(
f"[capture-mock] started url={url} freq={freq} amplitude=0 interval={interval}",
flush=True,
)
while True:
try:
req = urllib.request.Request(
url,
data=payload,
headers=headers,
method="POST",
)
with urllib.request.urlopen(req, timeout=timeout) as response:
if log_success:
print(f"[capture-mock] sent status={response.status}", flush=True)
except Exception as exc:
print(f"[capture-mock] send failed: {exc}", flush=True)
time.sleep(interval)
PY
CURRENT_MOCK_PID=$!
log "Mock sender PID=$CURRENT_MOCK_PID"
}
stop_mock_sender() {
local pid="${1:-}"
if [[ -z "$pid" ]]; then
return 0
fi
if kill -0 "$pid" 2>/dev/null; then
log "Останавливаю mock sender PID=$pid"
terminate_pid "$pid"
fi
}
cleanup_capture() { cleanup_capture() {
if [[ -n "$CURRENT_CAPTURE_PID" ]] && kill -0 "$CURRENT_CAPTURE_PID" 2>/dev/null; then local rc=$?
log "Останавливаю текущий PID=$CURRENT_CAPTURE_PID при завершении скрипта"
kill -TERM "$CURRENT_CAPTURE_PID" 2>/dev/null || true if [[ -n "${CURRENT_CAPTURE_PID:-}" ]] && kill -0 "$CURRENT_CAPTURE_PID" 2>/dev/null; then
wait "$CURRENT_CAPTURE_PID" 2>/dev/null || true log "Останавливаю текущий capture PID=$CURRENT_CAPTURE_PID"
terminate_pid "$CURRENT_CAPTURE_PID"
fi fi
CURRENT_CAPTURE_PID="" CURRENT_CAPTURE_PID=""
if [[ -n "$CURRENT_SERVICE_UNIT" ]]; then if [[ -n "${CURRENT_MOCK_PID:-}" ]] && kill -0 "$CURRENT_MOCK_PID" 2>/dev/null; then
log "Восстанавливаю service $CURRENT_SERVICE_UNIT при завершении скрипта" log "Останавливаю текущий mock sender PID=$CURRENT_MOCK_PID"
systemctl_run start "$CURRENT_SERVICE_UNIT" || true terminate_pid "$CURRENT_MOCK_PID"
CURRENT_SERVICE_UNIT=""
fi fi
CURRENT_MOCK_PID=""
start_stopped_service
exit "$rc"
} }
on_signal() { on_signal() {
@ -161,18 +331,60 @@ on_signal() {
exit 130 exit 130
} }
dir_size_bytes() { ############################
local path="$1" # ЧАСТОТЫ И SERIAL
if [[ -e "$path" ]]; then ############################
du -sb "$path" 2>/dev/null | awk '{print $1}'
else
echo 0
fi
}
total_size_bytes() { ORDER=(1200 2400 5200 5800)
dir_size_bytes "$BASE_DIR"
} declare -A SERIAL
declare -A FREQ_HZ
declare -A SERVICE_UNIT
SERIAL[433]="$(env_get hack_433)"
FREQ_HZ[433]="433000000"
SERIAL[750]="$(env_get hack_750)"
FREQ_HZ[750]="750000000"
SERIAL[868]="$(env_get hack_868)"
FREQ_HZ[868]="868000000"
SERIAL[915]="$(env_get hack_915)"
FREQ_HZ[915]="915000000"
SERIAL[1200]="$(env_get hack_1200)"
FREQ_HZ[1200]="1200000000"
SERIAL[2400]="$(env_get hack_2400)"
FREQ_HZ[2400]="2400000000"
SERIAL[3300]="$(env_get hack_3300)"
FREQ_HZ[3300]="3300000000"
SERIAL[4500]="$(env_get hack_4500)"
FREQ_HZ[4500]="4500000000"
SERIAL[5200]="$(env_get hack_5200)"
FREQ_HZ[5200]="5200000000"
SERIAL[5800]="$(env_get hack_5800)"
FREQ_HZ[5800]="5800000000"
SERVICE_UNIT[433]="dronedetector-sdr-433.service"
SERVICE_UNIT[750]="dronedetector-sdr-750.service"
SERVICE_UNIT[868]="dronedetector-sdr-868.service"
SERVICE_UNIT[915]="dronedetector-sdr-915.service"
SERVICE_UNIT[1200]="dronedetector-sdr-1200.service"
SERVICE_UNIT[2400]="dronedetector-sdr-2400.service"
SERVICE_UNIT[3300]="dronedetector-sdr-3300.service"
SERVICE_UNIT[4500]="dronedetector-sdr-4500.service"
SERVICE_UNIT[5200]="dronedetector-sdr-5200.service"
SERVICE_UNIT[5800]="dronedetector-sdr-5800.service"
############################
# ОСНОВНАЯ ЛОГИКА
############################
ensure_requirements() { ensure_requirements() {
if [[ ! -x "$PYTHON_BIN" ]]; then if [[ ! -x "$PYTHON_BIN" ]]; then
@ -205,6 +417,7 @@ ensure_requirements() {
if [[ -n "${CAPTURE_ORDER:-}" ]]; then if [[ -n "${CAPTURE_ORDER:-}" ]]; then
ORDER=() ORDER=()
local band local band
for band in ${CAPTURE_ORDER//,/ }; do for band in ${CAPTURE_ORDER//,/ }; do
ORDER+=("$band") ORDER+=("$band")
done done
@ -219,25 +432,36 @@ ensure_requirements() {
log "BASE_DIR: $BASE_DIR" log "BASE_DIR: $BASE_DIR"
log "ORDER: ${ORDER[*]}" log "ORDER: ${ORDER[*]}"
log "RUN_ONCE: $RUN_ONCE" log "RUN_ONCE: $RUN_ONCE"
log "PER_FREQ_LIMIT_GIB: $PER_FREQ_LIMIT_GIB"
log "TOTAL_LIMIT_GIB: $TOTAL_LIMIT_GIB"
log "CYCLE_SECONDS: $CYCLE_SECONDS"
log "CAPTURE_MOCK_SEND_ENABLED: $CAPTURE_MOCK_SEND_ENABLED"
log "PYTHON_BIN: $PYTHON_BIN"
log "SCRIPT_PATH: $SCRIPT_PATH"
} }
run_one_freq() { run_one_freq() {
local band="$1" local band="$1"
local serial="${SERIAL[$band]}" local serial="${SERIAL[$band]:-}"
local freq="${FREQ_HZ[$band]}" local freq="${FREQ_HZ[$band]:-}"
if [[ -z "$serial" ]]; then if [[ -z "$serial" ]]; then
log "Для band=$band пустой serial, пропускаю" log "Для band=$band пустой serial, пропускаю"
return 0 return 0
fi fi
if [[ -z "$freq" ]]; then
log "Для band=$band не задана частота, пропускаю"
return 0
fi
local ts out_dir log_file local ts out_dir log_file
ts="$(date '+%F_%H-%M-%S')" ts="$(date '+%F_%H-%M-%S')"
out_dir="$BASE_DIR/$band/$ts" out_dir="$BASE_DIR/$band/$ts"
log_file="$out_dir/run.log" log_file="$out_dir/run.log"
log "Старт band=$band serial=$serial freq=$freq dir=$out_dir" log "Старт band=$band serial=$serial freq=$freq dir=$out_dir"
if ! mkdir -p "$out_dir"; then if ! mkdir -p "$out_dir"; then
log "Не удалось создать каталог $out_dir" log "Не удалось создать каталог $out_dir"
return 1 return 1
@ -260,64 +484,71 @@ run_one_freq() {
local pid=$! local pid=$!
CURRENT_CAPTURE_PID="$pid" CURRENT_CAPTURE_PID="$pid"
log "PID=$pid" log "Capture PID=$pid"
start_mock_sender "$band" "$log_file"
local mock_pid="$CURRENT_MOCK_PID"
while kill -0 "$pid" 2>/dev/null; do while kill -0 "$pid" 2>/dev/null; do
local cur_dir_size cur_total_size local cur_dir_size cur_total_size
cur_dir_size="$(dir_size_bytes "$out_dir")" cur_dir_size="$(dir_size_bytes "$out_dir")"
cur_total_size="$(total_size_bytes)" cur_total_size="$(total_size_bytes)"
if (( cur_total_size >= TOTAL_LIMIT_BYTES )); then if (( cur_total_size >= TOTAL_LIMIT_BYTES )); then
log "Достигнут общий лимит $lim_all GiB. Останавливаю PID=$pid" log "Достигнут общий лимит ${TOTAL_LIMIT_GIB} GiB. Останавливаю PID=$pid"
kill -TERM "$pid" 2>/dev/null || true
wait "$pid" 2>/dev/null || true terminate_pid "$pid"
CURRENT_CAPTURE_PID="" CURRENT_CAPTURE_PID=""
start_current_service
stop_mock_sender "$mock_pid"
CURRENT_MOCK_PID=""
start_stopped_service
return 2 return 2
fi fi
if (( cur_dir_size >= PER_FREQ_LIMIT_BYTES )); then if (( cur_dir_size >= PER_FREQ_LIMIT_BYTES )); then
log "Для band=$band достигнут лимит 3 GiB. Останавливаю PID=$pid" log "Для band=$band достигнут лимит ${PER_FREQ_LIMIT_GIB} GiB. Останавливаю PID=$pid"
kill -TERM "$pid" 2>/dev/null || true
for _ in {1..10}; do terminate_pid "$pid"
if ! kill -0 "$pid" 2>/dev/null; then CURRENT_CAPTURE_PID=""
break
fi
sleep 1
done
if kill -0 "$pid" 2>/dev/null; then
log "PID=$pid не завершился по TERM, отправляю KILL"
kill -KILL "$pid" 2>/dev/null || true
fi
wait "$pid" 2>/dev/null || true
break break
fi fi
sleep 1 sleep 1
done done
wait "$pid" 2>/dev/null || true
CURRENT_CAPTURE_PID="" CURRENT_CAPTURE_PID=""
start_current_service
stop_mock_sender "$mock_pid"
CURRENT_MOCK_PID=""
start_stopped_service
log "Завершен band=$band, размер=$(du -sh "$out_dir" | awk '{print $1}')" log "Завершен band=$band, размер=$(du -sh "$out_dir" | awk '{print $1}')"
return 0 return 0
} }
main_loop() { main_loop() {
while true; do while true; do
local total_before cycle_start elapsed sleep_left local total_before cycle_start elapsed sleep_left
total_before="$(total_size_bytes)" total_before="$(total_size_bytes)"
if (( total_before >= TOTAL_LIMIT_BYTES )); then if (( total_before >= TOTAL_LIMIT_BYTES )); then
log "Общий размер уже >= GiB, выхожу" log "Общий размер уже >= ${TOTAL_LIMIT_GIB} GiB, выхожу"
break break
fi fi
cycle_start="$(date +%s)" cycle_start="$(date +%s)"
log "Новый цикл" log "Новый цикл"
local band
for band in "${ORDER[@]}"; do for band in "${ORDER[@]}"; do
if (( $(total_size_bytes) >= TOTAL_LIMIT_BYTES )); then if (( $(total_size_bytes) >= TOTAL_LIMIT_BYTES )); then
log "Общий лимит достигнут внутри цикла, выхожу" log "Общий лимит достигнут внутри цикла, выхожу"
@ -325,14 +556,15 @@ main_loop() {
fi fi
run_one_freq "$band" || { run_one_freq "$band" || {
rc=$? local rc=$?
if [[ $rc -eq 2 ]]; then
if [[ "$rc" -eq 2 ]]; then
log "Остановка по общему лимиту" log "Остановка по общему лимиту"
return 0 return 0
else
log "Ошибка записи band=$band rc=$rc"
return "$rc"
fi fi
log "Ошибка записи band=$band rc=$rc"
return "$rc"
} }
done done
@ -345,7 +577,7 @@ main_loop() {
sleep_left=$(( CYCLE_SECONDS - elapsed )) sleep_left=$(( CYCLE_SECONDS - elapsed ))
if (( sleep_left > 0 )); then if (( sleep_left > 0 )); then
log "Цикл занял ${elapsed} сек, жду ${sleep_left} сек до следующего часа" log "Цикл занял ${elapsed} сек, жду ${sleep_left} сек"
sleep "$sleep_left" sleep "$sleep_left"
else else
log "Цикл занял ${elapsed} сек, паузы нет" log "Цикл занял ${elapsed} сек, паузы нет"

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save