diff --git a/capture_hourly.sh b/capture_hourly.sh index f707306..38d63b7 100755 --- a/capture_hourly.sh +++ b/capture_hourly.sh @@ -1,27 +1,37 @@ #!/usr/bin/env bash set -Eeuo pipefail +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SCRIPT_OWNER="${CAPTURE_USER:-$(stat -c %U "$SCRIPT_DIR")}" +SCRIPT_OWNER_HOME="$(getent passwd "$SCRIPT_OWNER" | cut -d: -f6)" +cd "$SCRIPT_DIR" -source .env +source "$SCRIPT_DIR/.env" ############################ # НАСТРОЙКИ ############################ - -BASE_DIR="/home/sibsci/dataset/drone" +BASE_DIR="${CAPTURE_BASE_DIR:-${SCRIPT_OWNER_HOME}/dataset/noise}" # Путь к python из venv -PYTHON_BIN="${PYTHON_BIN:-$PWD/.venv-sdr/bin/python}" +PYTHON_BIN="${PYTHON_BIN:-$SCRIPT_DIR/.venv-sdr/bin/python}" # Путь к headless скрипту -SCRIPT_PATH="${SCRIPT_PATH:-$PWD/scripts_nn/data_saver_headless.py}" +SCRIPT_PATH="${SCRIPT_PATH:-$SCRIPT_DIR/scripts_nn/data_saver_headless.py}" + +RUN_ONCE="${RUN_ONCE:-0}" +CAPTURE_LOG_FILE="${CAPTURE_LOG_FILE:-$BASE_DIR/capture_hourly.log}" + +SYSTEMCTL_BIN=(systemctl) +CURRENT_CAPTURE_PID="" +CURRENT_SERVICE_UNIT="" # Лимиты -lim_all=70 -PER_FREQ_LIMIT_BYTES=$((7 * 1024 * 1024 * 1024)) # GiB на частоту за запуск +lim_all=10 +PER_FREQ_LIMIT_BYTES=$((1 * 1024 * 1024 * 1024)) # GiB на частоту за запуск TOTAL_LIMIT_BYTES=$((lim_all * 1024 * 1024 * 1024)) # общий лимит GiB CYCLE_SECONDS=1 # один цикл в час @@ -37,13 +47,12 @@ BB_GAIN="36" # ЧАСТОТЫ И SERIAL ИЗ ENV ############################ -#ORDER=(433 750 915 1200 2400 3300 4500 5200 5800) - -ORDER=(2400) +ORDER=(433) declare -A SERIAL declare -A FREQ_HZ +declare -A SERVICE_UNIT SERIAL[433]="$hack_433" FREQ_HZ[433]="433000000" @@ -73,6 +82,16 @@ FREQ_HZ[5200]="5200000000" SERIAL[5800]="$hack_5800" FREQ_HZ[5800]="5800000000" +SERVICE_UNIT[433]="dronedetector-sdr-433.service" +SERVICE_UNIT[750]="dronedetector-sdr-750.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" + ############################ # ВСПОМОГАТЕЛЬНОЕ ############################ @@ -81,6 +100,65 @@ log() { printf '[%s] %s\n' "$(date '+%F %T')" "$*" } +systemctl_run() { + "${SYSTEMCTL_BIN[@]}" "$@" +} + +service_exists() { + local unit="$1" + systemctl_run show "$unit" >/dev/null 2>&1 +} + +stop_band_service() { + local band="$1" + local unit="${SERVICE_UNIT[$band]:-}" + + if [[ -z "$unit" ]]; then + log "Для band=$band не найден service unit" + return 0 + fi + + if ! service_exists "$unit"; then + log "Service unit $unit не установлен, пропускаю stop/start" + return 0 + fi + + log "Останавливаю service $unit перед записью band=$band" + systemctl_run stop "$unit" + CURRENT_SERVICE_UNIT="$unit" +} + +start_current_service() { + if [[ -z "$CURRENT_SERVICE_UNIT" ]]; then + return 0 + fi + + log "Запускаю service $CURRENT_SERVICE_UNIT после записи" + systemctl_run start "$CURRENT_SERVICE_UNIT" + CURRENT_SERVICE_UNIT="" +} + +cleanup_capture() { + if [[ -n "$CURRENT_CAPTURE_PID" ]] && kill -0 "$CURRENT_CAPTURE_PID" 2>/dev/null; then + log "Останавливаю текущий PID=$CURRENT_CAPTURE_PID при завершении скрипта" + kill -TERM "$CURRENT_CAPTURE_PID" 2>/dev/null || true + wait "$CURRENT_CAPTURE_PID" 2>/dev/null || true + fi + CURRENT_CAPTURE_PID="" + + if [[ -n "$CURRENT_SERVICE_UNIT" ]]; then + log "Восстанавливаю service $CURRENT_SERVICE_UNIT при завершении скрипта" + systemctl_run start "$CURRENT_SERVICE_UNIT" || true + CURRENT_SERVICE_UNIT="" + fi +} + +on_signal() { + local sig="$1" + log "Получен сигнал $sig, завершаю работу" + exit 130 +} + dir_size_bytes() { local path="$1" if [[ -e "$path" ]]; then @@ -105,7 +183,40 @@ ensure_requirements() { exit 1 fi + if ! command -v systemctl >/dev/null 2>&1; then + echo "Не найден systemctl" >&2 + exit 1 + fi + + if [[ "${EUID}" -ne 0 ]]; then + if command -v sudo >/dev/null 2>&1; then + SYSTEMCTL_BIN=(sudo systemctl) + else + echo "Для управления service нужен root или sudo" >&2 + exit 1 + fi + fi + mkdir -p "$BASE_DIR" + mkdir -p "$(dirname "$CAPTURE_LOG_FILE")" + + if [[ -n "${CAPTURE_ORDER:-}" ]]; then + ORDER=() + local band + for band in ${CAPTURE_ORDER//,/ }; do + ORDER+=("$band") + done + fi + + if [[ "${#ORDER[@]}" -eq 0 ]]; then + echo "ORDER пустой. Укажите частоты в ORDER или задайте CAPTURE_ORDER." >&2 + exit 1 + fi + + log "Рабочая директория: $SCRIPT_DIR" + log "BASE_DIR: $BASE_DIR" + log "ORDER: ${ORDER[*]}" + log "RUN_ONCE: $RUN_ONCE" } @@ -114,14 +225,23 @@ run_one_freq() { local serial="${SERIAL[$band]}" local freq="${FREQ_HZ[$band]}" + if [[ -z "$serial" ]]; then + log "Для band=$band пустой serial, пропускаю" + return 0 + fi + local ts out_dir log_file ts="$(date '+%F_%H-%M-%S')" out_dir="$BASE_DIR/$band/$ts" log_file="$out_dir/run.log" - mkdir -p "$out_dir" - log "Старт band=$band serial=$serial freq=$freq dir=$out_dir" + if ! mkdir -p "$out_dir"; then + log "Не удалось создать каталог $out_dir" + return 1 + fi + + stop_band_service "$band" "$PYTHON_BIN" "$SCRIPT_PATH" \ --serial "$serial" \ @@ -137,6 +257,7 @@ run_one_freq() { >"$log_file" 2>&1 & local pid=$! + CURRENT_CAPTURE_PID="$pid" log "PID=$pid" while kill -0 "$pid" 2>/dev/null; do @@ -148,6 +269,8 @@ run_one_freq() { log "Достигнут общий лимит $lim_all GiB. Останавливаю PID=$pid" kill -TERM "$pid" 2>/dev/null || true wait "$pid" 2>/dev/null || true + CURRENT_CAPTURE_PID="" + start_current_service return 2 fi @@ -174,6 +297,8 @@ run_one_freq() { sleep 1 done + CURRENT_CAPTURE_PID="" + start_current_service log "Завершен band=$band, размер=$(du -sh "$out_dir" | awk '{print $1}')" return 0 } @@ -202,10 +327,18 @@ main_loop() { if [[ $rc -eq 2 ]]; then log "Остановка по общему лимиту" return 0 + else + log "Ошибка записи band=$band rc=$rc" + return "$rc" fi } done + if [[ "$RUN_ONCE" == "1" ]]; then + log "RUN_ONCE=1, завершаю работу после одного цикла" + break + fi + elapsed=$(( $(date +%s) - cycle_start )) sleep_left=$(( CYCLE_SECONDS - elapsed )) @@ -218,5 +351,9 @@ main_loop() { done } +trap cleanup_capture EXIT +trap 'on_signal INT' INT +trap 'on_signal TERM' TERM + ensure_requirements -main_loop \ No newline at end of file +main_loop