időpontok elemzése bash

Nem tudom hogy kezdjek neki az alábbi feladatnak. 

Írtam egy dtvrip nevű interaktív digitális tévé recorder programot, mely bash szkriptekből áll. Nem tanultam programozást. Ezt mind autodidakta módon, fórumos segítséggel, illetve külföldi oldalak böngészésével, meg rengeteg teszteléssel, tanulással értem el. Ez a program már 98%-osan az elvárásaimnak megfelelően működik. A számítógép automatikusan bekapcsol, felveszi a műsort, majd lekapcsol. Most ott akadtam el, hogy mi van akkor ha az adott cron feladat, nem mindennapos rendszerességű, hanem minden másnapos rendszerességű. A bekapcsolással gondok lesznek, mert most mindennap bekapcsol akkor is, ha nincs szükség rá.

Szép vagy nem szép, a dtvrip un. felvétel_szkripteket gyárt a különböző időpontú felvételekhez. Ezek az időpontok epoch formában egy fájlba kerülnek. rectime.txt
Ez a felvétel_szkript, futása végeztével beletesz +1 napot a rectime.txt-be.

Na a gond az, ha teszem azt csak szerdától szombatig kell a felvétel. A cronban helyes a bejegyzés. A felvétel nem fog elindulni vasárnap, de a gép bekapcsol.
Vagyis a rectime.txt és a cron bejegyzésben lévő időpontokat kellene elemeznem. A nehézség az, hogy  ott ugye lehetnek a napra vonatkozó bejegyzések 2-6 formátumúak is. esetleg 1,3,5. Esetleg ennek kombinációja. 1, 5-7

S akkor ennek ismeretében eltudnám távolítani a rectime.txt-ből azokat az időpontokat, amikor nem kell bekacsolnia a gépnek. Azt tudni kell, hogy a bekapcsolás meghatározása jelenleg úgy zajlik, hogy a gép kikapcsolás előtt megvizsgálja a rectime.txt, és az aktuális időponthoz képest a legközelebbit adja át az rtcwakenak. Tehát mindenképpen a rectime.txt fájlt kell módosítani a cron bejegyzések elemzésével. Ez nyilván regex, meg sed, amiben nem nagyon vagyok otthon.

Készülök a githubra is kitenni, de előtte ezt azért megoldanám. 

Hozzászólások

Hat en tuti azt csinalnam, hogy lenne egy yaml leirom allomanyom arrol, mikor kell felvenni valamit a megadott parameterekkel. Ezt olvasna fel egyetlen python script, ami a yaml alapjan siman kiszamolja, hogy mit kell atadnia az rtcwakenek es lefuttatna felveteleket amig van meg adott napra, akar ki is kapcsolhatja aztan a gepet. Amikor meg a gep elindul, akkor maga a python script is elindulna es ugye azzal kezdene, hogy felolvassa a sajat konfigjat. Igy nem kell cron, meg rectime, meg csomo minden elbonyolitott file, amit mind managelni es kezelni kell, meg egymashoz kepest osszefesulni.

 

Az biztos, hogy egyetlen configot csinalnek csak, nem tobbet.

Kolumbusz tojása: Ugye van egy listád, amikor a felvenni akart műsorok kezdődnek (hosszal együtt). Ennek a listának semmi köze nem kell, hogy legyen a cron-hoz(!), mert nem "olyan" ütemezésről van szó.
Az időpontok listájának a kezelését válasszuk le a felvétel megtörténjen feladatról, mert most az látszik, hogy ez utóbbival vagy gondban.
Fogsz egy scriptet, ami mondjuk percenként "ránéz" erre a listára, és ha kell indítja a felvételt (és megakadályozza, hogy a felvétel időpontja+műsor hossza időszakban a gépet bárki leállítsa(!) - kivéve, ha a felvételt végző program leállításra került).
Ha a feévétel sikeresen végetért, _és_ nincs interaktív user bent a gépen, akkor meg szépen le is lehet állítania a gépet.
A dolog systemd-s unitért kiabál: a start elindítja a scriptet (a percenként lefutó ciklust rád bízom, date +%s és sleep ügyes használatával prímán megoldható, de akár ki isléphet a script, ha az újraindítását 1 percre állítod a unitban).
A unit leállításakor meg annyi a dolga, hogy a következő időpontnak megfelelően (annál néhány perccel korábbra, hiszen el is kell indulnia a gépnek) beállítja a "vekkert", hogy induljon el a gép.

 

Nos. Ti nem látjátok át. A felvételért felelős szkriptben van a hossz megadva. Nem fog elfogyni a diszk. Tök egyszerű az egész.

#!/bin/bash

# A felvétel kezdete: 2-6 / 02:40
# A felvétel hossza: 70 perc - 4200 mp.

dtv_decoder="DVBC/ANNEX_A"
if [ "DVBT" != "${dtv_decoder}" ]; then
    /usr/bin/dvb-fe-tool -d "${dtv_decoder}"
fi
cd "/home/nextra/Videók/dvb-c/TV4"/
_date=$(date +%F_%H%M%S)
udate=$(date +%s)
timeout 4200 /usr/bin/mpv --stream-dump CRON_${_date}.ts dvb://"TV4"

#rectime - add +1 day!
(( rectime = udate + 86400 ))
echo ${rectime} >> /home/nextra/.config/dtvrip/wake/dtvrectime.txt

/usr/bin/sudo /sbin/shutdown -h now

Ez a dtvrip ilyesmiket generál. Ezt a szkriptet hívja meg a cron akkor ha sorozatok vannak.

Na nem ilyeneket kéne generálnia, hanem "mikor, melyik csatornáról, milyen hosszban" listákat, amit aztán egy darab _jól_ összerakott service kezel.

Bónuszként ez a megoldás, ami scriptekben, meg crontab-os időpontmegadással írja le, hogy mikor, honnan, milyen hosszban kell felvenni, nem tud péládul arra a kérdésre választ adni, hogy van-e ütköző/átfedő időpont?

Ha rám hallgatsz, úgy csinálod, ahogy neked tetszik, és tudom, nagyon nehéz az első produktumot újragondolni, de a jelen struktúrával sok bajod lesz még.

Oops amikor még volt 1 db videomagnóm, akkor ha azonos időpontban volt két érdekes műsor, akkor is csak egyet tudtam felvenni. Jelenleg csak 1 dvb-c eszközöm van, s így ha többen is használnák a gépet, akkor is konszenzusra kell jutni hogy mi legyen felvéve. Ezért nem érdekes most a több felhasználó. 

Szerintem tök fölösleges percenként bármit is ellenőrizni - minek? Amíg megy a gép, addig ugyan miért tökölünk azon, hogy mikor kell majd újra bekapcsolni? Leálláskor következik be az a pillanat, amikor tuti nem lesz módosítás a következő boot-ig - na akkor kell meghatározni, hogy mikor kell indulni újra.

Nem a "mikor kell bekapcsolni" miatt javasoltam ellenőrizni a felvételil időpontokat: Egyrészt a futó gépen is változhat a lista, és a "felvétel start" időpont eshet a bekapcsolt állapotra is. Mert nem csak a "mikor kapcsoljuk be" oldalndó meg/kezelendő, hanem a "mikor kell indítani a rögzítést" is.

Szóval ne akard a crontab bejegyzéseket feldolgozni - pláne ne simán bash és "környékén" elérhető alap dolgokkal, mert annál -ahogy te is látod- jóval bonyolultabb - ráadásul a cron nem erre vaó. Szerintem.

A cront nem akarom bántani. Abból csak kiolvasnám a felvétel napjait. Teszem azt a cronban ez van:

# Tv sorozat - TV4 - Minden 2-6 - 02:40 perckor (dtvrip_CRON_20200521_224637.sh)
40 02 * * 2-6 /home/nextra/Videók/dvb-c/TV4/dtvrip_CRON_20200521_224637.sh

Eszerint a felvétel megkezdődik keddtől-szombatig 2:40-kor. Amikor ez a dtvrip_CRON_20200521_224637.sh szkript lefut, ez hozzátesz +1 napot a rectime.txt fájlba, melyben csak epoch időpontok vannak. Ennyi. A probléma az, hogy ezt a plusz 1 napot ugye szombaton is hozzáteszi. Holott vasárnap, hétfőn nem kell felvétel. A cron ezt tudja is. De ettől függetlenül a gép be fog kapcsolni, mert a rectime.txt-ben ott a plusz idő.

Annyi a dolog, hogy a rectime.txt fájlból el kell távolítani a vasárnapi, és a hétfői időpontokat. 

Vitatható, hogy a cron vagy az at a barátunk - egyedi felvételekhez inkább at, sorozatokhoz inkább cron. De egyedi is bebarkácsolható cron alá - ha már megvan, maradjon.

A feladat tehát az, hogy meg kell határozni, hogy mi a "legközelebbi" cron esemény. A date parancs szolgáltat minden információt, amely ehhez szükséges: megadja, hogy melyik hónap melyik napja van, de azt is megtudhatjuk, hogy a hét hanyadik napjánál járunk. Hogy algoritmust is adjak - bár az már vitatható, hogy mennyire optimális, de a feladat megoldására vélhetően alkalmas -a következő:
- a date parancs eredményét átkonvertálod az 1970.01.01 00:00:00 óta eltelt másodpercekre,
- minden egyes cron bejegyzéshez képzel egy hasonló értéket azzal a megkötéssel, hogy ilyen sok lehet, tehát amelyikre szükséged van, az az első olyan, amely nagyobb az előző lépésben kapott értéknél - ez mondjuk szép feladat lesz,
- az eredményül kapott lista legkisebb eleme megadja azt az értéket, amikor be kell kapcsolni a masinát.

Húúú. Te nem is olvastad az előzményeket? 

#!/bin/bash

# colors
Yellow=$(tput bold; tput setaf 3)
Magenta=$(tput bold; tput setaf 5)
Cyan=$(tput bold; tput setaf 6)
NC=$(tput sgr0) # Reset: No Color, offblink

printf "\n%s\n" "${Magenta}Az alábbi időpontok vannak beállítva tévé felvételekhez:"
readarray arrayRECtime <<< "$(cat ~/.config/dtvrip/wake/dtvrectime.txt)"
echo 
for num in "${arrayRECtime[@]}"; do 
    numSP=$(echo "${num}")
    echo "${Yellow}${numSP} - ${Cyan}$(date -d @"${numSP}")${NC}"
done 
unset arrayRECtime

Itt megtudom nézni olvasható formában hogy mik vannak a már emlegetett rectime.txt fájlban.

wake_file=$(find /home -maxdepth 5 -name "dtvrectime.txt" 2>/dev/null)
datenow=$(date +%s)
if [ ! -f "${wake_file}" ]; then
    exit
else
    if [ ! -s "${wake_file}" ]; then
        exit
    else 
        tmp_wake_file=$(mktemp -p "$HOME"/tmp) && chmod 0600 "${tmp_wake_file}"
        # no trap, because use mv command
        # törli a már lejárt dátumokat, és sorrendbe teszi.
        awk -v _now="${datenow}" '$1 > _now {print $1}' < "${wake_file}" | sort > "${tmp_wake_file}"
        mv -f "${tmp_wake_file}" "${wake_file}"

        # következő felvétel kezdete.
        nextTime=$(head -n1 < "${wake_file}")
        
        # 5 perccel korábban kapcsoljon be a gép.
        (( turnon = nextTime - 300 ))
        sudo rtcwake -m no -t "${turnon}"
    fi
fi        

Ezt a fájlt hívja meg a systemd kikapcsoláskor. S ez adja át az rtcwakenak az aktuális dátumhoz képest a legközelebbi időpontot.

Szerintem az se lenne nagy gond ha idéznél egy részletet a rectime.txt-ből, azon belül is megjelölve a sorokat, amiket törölni kellene (legalábbis úgy értem, hogy ezt szeretnéd: feltétel alapján sorokat törölni).

 Mint a hogy  írtam  a nyitóban. Ezek az időpontok epoch formában egy fájlba kerülnek. rectime.txt

1590854460
1592250334
1592350334
1592450331
1592550332
1592650334
1592750338
1592850334
1592950394
1593150334
1593250334
1593350334
1591144803

Ezt most éppen a tesztfájlomból másoltam be. Vagyis nem aktuális. Ezeket frissíti a már közzétett szkript, és ebből kapja meg a bekapcsolási időt az rtcwake.
 

Szupi. Ahogy már írták is többen, a date című segédprogram ebből szívesen megmondja a hét napját. Innen már csak egy `if` utasítás kérdése.

while read Epoch; do
    Dow=$(date -d @"$Epoch" +"%u"); echo "$Dow" "$Epoch"
done <rectime.txt