shutdown előtt lefutó program

Fórumok

A cím kicsit pongyola. De szeretném, hogy amikor ráklikkelnek a Leállításra, akkor még mielőtt az egész procedúra elkezdődik, lefutna egy program. Ezért azt a szkriptet melynek le kéne futnia, beletettem az /usr/lib/systemd/system-shutdown mappába shutdown kiterjesztéssel.. Viszont nem történt semmi.

Készítettem egy teszt fájlt, mely csak annyit tesz hogy 3 percig várakoztatja a gépet a kikapcsolás előtt. Ugyanide tettem, és az meg működik. Arra jutottam, hogy a szkript lefut ugyan, de a /dev/null-ban. Fogjuk rá hogy jó helyen van, de a legutolsó a sorban, holott a legelsőnek kellene lennie. Magyarul az ide berakott szkriptek melyeknek talán még fájlműveleteket is kellene folytatniuk, nem fognak működni, mert eddigre (addigra?) már lecsatolódott a fájlrendszer, kiléptek a felhasználók, és ennyi.

Jó, akkor jöjjön a service. Készítettem egyet, mely meghívta a szkriptemet, de ugyanez lett a jelenség. Nem történt semmi. Nos. Most ott tartok, hogy meg kell határoznom, melyik service után fusson le.

Jól gondolom-e hogy ez talán disztrófüggő? Ha pl. megadom hogy After=local-fs.target, akkor le is késtem a dologról, mert lecsatolta a fájlrendszert. No de akkor mi után? Azt egyelőre nem tudom hogy miként fedezzem fel, az egyes service folyamatok sorrendjét kikapcsolás esetén. Van erre valami lehetőség, vagy ötletek, hogy mit állítsak be?

Hozzászólások

amikor ráklikkelnek a Leállításra

Ha csak akkor kell, amikor ráklikkelsz a leállításra, akkor dobj egy drop-in-t a display-manager.service-re, amiben adsz egy újabb ExecStop-ot neki :)

Magyarul az ide berakott szkriptek melyeknek talán még fájlműveleteket is kellene folytatniuk, nem fognak működni, mert eddigre (addigra?) már lecsatolódott a fájlrendszer, kiléptek a felhasználók, és ennyi.

Igen, jól látod.

Jól gondolom-e hogy ez talán disztrófüggő?

Vannak standard target-ek (pl. az általad is említett local-fs.target), lásd https://www.freedesktop.org/software/systemd/man/systemd.special.html

Ha jól tippelek, neked a shutdown.target kell (lásd a fenti linken).

BlackY

"Gyakran hasznos ugyanis, ha számlálni tudjuk, hányszor futott le már egy végtelenciklus." (haroldking)

Ok. ok. Nem voltam elég világos. Nem CSAK akkor, hanem bármikor amikor a gép leállni készül. Legyen az akár szkript által indított shutdown -h now. 

Tehát van egy fájlom, melyben UTC formában időpontok lehetnek. Ebből a fájlból kinyerem az aktuális időponthoz képest a legközelebbi jövő időt. (Na ezt szépen megfogalmaztam.)  S ezt átadom az rtcwake parancsnak hogy állítsa be az automatikus bekapcsolást. Ennek a szkriptnek kellene lefutnia. A szkript manuálisan meghívva működik. A hozzá készült service: 

Jelenleg ez van benne:

[Unit]
Description=Wake dtvRip
DefaultDependencies=no
Before=shutdown.target
RequiresMountsFor=/home

[Service]
Type=oneshot
ExecStart=/usr/local/bin/dtvrip_poweron --stop
#RemainAfterExit=yes

[Install]
WantedBy=shutdown.target
 

Szerkesztve: 2020. 05. 27., sze - 08:26

DE függő. KDE alatt szkriptelhető ez egészen biztos.

LXDE alatt és egyébként más DE alatt is egyszerűen cseréld le  - itt kattintásról van szó, ahogyan fent írtad - az ikonhoz tartozó menü parancsát. Megnéztem, LXDE alatt "lxqt-leave --shutdown" fut le.

Nezd at a leallitas logjait:

journalctl -b -1

Nalam pl igy neznek ki a targetek:

May 22 15:24:38 eff-tp systemd[955]: Stopped target Bluetooth.
May 22 15:24:38 eff-tp systemd[955]: Stopped target Main User Target.
May 22 15:24:38 eff-tp systemd[955]: Stopped target Basic System.
May 22 15:24:38 eff-tp systemd[955]: Stopped target Paths.
May 22 15:24:38 eff-tp systemd[955]: Stopped target Sockets.
May 22 15:24:38 eff-tp systemd[955]: Stopped target Timers.
May 22 15:24:38 eff-tp systemd[955]: Reached target Shutdown.
May 22 15:24:38 eff-tp systemd[955]: Reached target Exit the Session.
May 22 15:24:38 eff-tp systemd[1]: Stopped target Network.
May 22 15:24:38 eff-tp systemd[1]: Stopped target Remote File Systems.
May 22 15:24:38 eff-tp systemd[1]: Stopped target Basic System.
May 22 15:24:38 eff-tp systemd[1]: Stopped target Paths.
May 22 15:24:38 eff-tp systemd[1]: Stopped target Slices.
May 22 15:24:38 eff-tp systemd[1]: Stopped target Sockets.
May 22 15:24:38 eff-tp systemd[1]: Stopped target System Initialization.
May 22 15:24:38 eff-tp systemd[1]: Stopped target Local Encrypted Volumes.
May 22 15:24:38 eff-tp systemd[1]: Stopped target Local File Systems.
May 22 15:24:38 eff-tp systemd[1]: Stopped target Local File Systems (Pre).
May 22 15:24:38 eff-tp systemd[1]: Stopped target Swap.
May 22 15:24:38 eff-tp systemd[1]: Reached target Unmount All Filesystems.
May 22 15:24:38 eff-tp systemd[1]: Reached target Shutdown.
May 22 15:24:38 eff-tp systemd[1]: Reached target Final Step.
May 22 15:24:38 eff-tp systemd[1]: Reached target Power-Off.

Ebbol ugye az latszik, hogy a system szintu shutdown.target az mar unmount utan van. Viszont a user szintu shutdown.target (955-os pid), az pl teljesen jo lehet.
A masik lehetoseged, hogy csinalsz egy olyan service-t, ami a Local FS utan indul el, es az ExecStop-ban van a tenyleges mukodes, ugyanis a fuggoseg miatt ezt elotte fogja leallitani:
 

[Unit]
Description=Wake dtvRip
After=local-fs.target
RequiresMountsFor=/home

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/true

ExecStop=/usr/local/bin/dtvrip_poweron --stop

[Install]
WantedBy=multi-user.target 

sub

Psszt, elárulom az IP-címemet: 192.168.0.14

Slackware alatt a /etc/rc.d/rc.6 script tartalma:
 


# Run any local shutdown scripts:
if [ -x /etc/rc.d/rc.local_shutdown ]; then
  /etc/rc.d/rc.local_shutdown stop
fi

Az elmélet az, amikor mindent ismerünk, de semmi nem működik. A gyakorlat az, amikor minden működik, de senki nem tudja, miért.

Azt hiszem megvan a probléma. A gond az, hogy a lefutó szkriptben változókat használok, mert muszáj, és az útvonal is egy változó. Éppen ezért a systemd nem értelmezi.

Tesztnek kiírattam vele egy fájlba a pontos időt. Betette a gyökérbe. Utána pontosan megadtam a felhasználó egyik rejtett almappáját, és oda is betette. Ha a felhasználó ugyanezen mappája egy változóban volt, akkor már nem tette bele.

Vagyis a környezeti változók ugrottak. Úgy tűnik EnvironmentFiles használata lesz a megoldás. De ez egyelőre kínai. S ha jól értelmezem, emiatt a nagy probléma, talán a hordozhatóság lesz. 

A környezeti változókat szépen berakod egy jól irányzott fájlba - arra figyelj, hogy név=érték párosok vannak csak, behelyettesítés, mint shellben az (még) nincs - és megadod a unitban, hogy EnvironmentFile=/etc/sysconfig/sajatunitenv és ennyi. Ha a Fájl létezése nem kötelező, akkor meg EnvironmentFile=-/etc/sysconfig/sajatunitenv

Igen. Köszi. De az csak ott lehet?

Lássuk egészben. Ahogy a bevezetőben írtam, van egy fájl időpontokkal teli. A szkript amit szándékozok lefuttatni, az a következőket teszi.

Először is megkeresi a fájlt.

wake_path=$(/usr/bin/find $HOME/ -maxdepth 3 -name "rectime.txt" -exec dirname {} \; 2>/dev/null)
wake_file="rectime.txt"

Az aktuális dátumhoz képest letörli a régieket. 

awk -v _now="${actualtime}" '$1 > _now {print $1}' < "${wake_path}/${wake_file}" > /tmp/"${wake_file}"

Majd ezt a tisztított fájlt mv-vel visszateszem a helyére. Utána kiveszem az aktuális időhöz legközelebb eső időpontot amikor be kell kapcsolnia a gépnek.

nextTime=$(head -n1 < "${wake_path}/${wake_file}" | sort)

Majd az így kapott időt átadom az rtcwake-nak. Nos itt  gyenge pont az az, hogy a wake_path és a wake_file a felhasználó valamelyik mappájában van. S emiatt, mivel a felhasználó bárki lehet, muszáj változóba tenni az útvonalat. Esetleg milyen más alternatívák lehetnek? /usr/local/etc/ s ide tenni a wake_filet-? Akkor lehetne abszolút útvonalat használni. S nem kell törődni a felhasználókkal, ellenben hozzáférést kell biztosítani a felhasználó részére az /usr/share/etc fájlhoz. Ha itt harapom meg itt fáj, ha ott akkor ott. Ötletek? Esetleg más megközelítés?

Nomostan egy systemd-s unit adott user nevében (User=...) fog futni (vagy root, ha nem adod meg), tehát már a feladat megfogalmazása is erősen szuboptimális, ez az egyik. A másik, hogy nem törődik azzal, hogy "a" user bemegy, leállítás előtt bedob egy mondjuk "4 óra mulva" értéket, majd "b" user a leállított gépet elindítja 2 óra múlva, és mond egy "3 óra mulva"-t.
Nomostan a kettő közül melyik lesz az érvényes?
A wake_path önállóan sehol nincs használva, ergo kidobható. A unitból induló scriptben én végigmennék az _összes_ adott nevű fájlon (Ez jöhet env-ből, hogy mi legyen a neve, amit keres) a /home/*/ alatt, és az összes fájlból takarítanám a múltbéli időpontokat, a takarítottakat visszaraknám a helyükre _és_ összemásolnám egy temp fájlba, amiből egy jól irányzott sort -n meg head -1 kimenete az, amire szükséged van.
A /tmp/${wake_file} használata nem szép, és nem jó. Tessék az mktemp-et használni, illetve a "trap" használatát is megszokni az átmeneti állomány takarításához.
 

Parancs értettem! Kérek engedélyt meghunyászkodni. Zeller őrmester elvtársnak jelentem ezt a trap nevű fickót nem ismerem. Én még csak most jöttem. Az mktemp meg kimaradáson van, és mivel nem láttam, kiment a fejemből. De ha visszajön majd beállítom a takarítók közé.

a és b user. Értem hogy mire gondolsz, de itt nem arról van szó, hogy egy gépen 20 felhasználó, és mind beírkálnak dolgokat. Hanem ha a kész projektet megosztom a nagyérdeművel, és ki tudja ki tölti le, az ő felhasználó neveikre gondoltam. Úgy gondolom, hogy otthoni környezetben általában egy gépet, egy ember használ. Amúgy amit leírtál: 

én végigmennék az _összes_ adott nevű fájlon (Ez jöhet env-ből, hogy mi legyen a neve, amit keres) a /home/*/ alatt, és az összes fájlból takarítanám a múltbéli időpontokat, a takarítottakat visszaraknám a helyükre _és_ összemásolnám egy temp fájlba, amiből egy jól irányzott sort -n meg head -1 kimenete az, amire szükséged van.

Azt hiszem ezt is csináltam.

No de ott most megakadtam, hogy megtalálja, de hogyan hivatkozik rá, ha nincs meg az útvonal?  Hiszen azt mondod a wake_path-ra nincs is szükség.

find $HOME/ -maxdepth 3 -name "rectime.txt"

Ez szvsz kevés. Én nem tanultam a programozást iskolában. S lehet hogy elég. Akkor hogy hivatkozzak rá? OK, meg van a fájl. És...? S hogy tudjam hol van, ezért lett a wake_path meghatározva. 

wake_path=$(/usr/bin/find $HOME/ -maxdepth 3 -name "rectime.txt" -exec dirname {} \; 2>/dev/null)

No de a systemd miatt ez az út nem lesz járható. A kérdés, amire nem kaptam választ. Az env fájl csak az /etc/sysconfig mappában lehet? Az mktempet én így tudom használni. 

tmp_wake_file="$(mktemp -p /tmp)" && chmod 0700 ${tmp_wake_file}
awk -v _now="${actualtime}" '$1 > _now {print $1}' < "${wake_path}/${wake_file}" > /tmp/"${tmp_wake_file}"

Ha ez így nem jó, akkor szívesen veszem a javaslatokat.

A "find /home -maxdepth 3 -type f -name rectime.txt" kimenetén a rectime.txt fájlok teljes útvonallal jelennek meg, minden user állományát felsorolva.
A systemd-s unitnak ezeket kell feldolgoznia a leállításkor (mindet!), hiszen nem tudhatja, hogy melyik user írt be valamit a sajátjába. Mert attól, hogy jozsika állítja le a gépet, és neki van holnaputánra egy bejegyzése, még pistike simán beírhatott a sajátjába egy holnapit úgy, hogy közben nem volt újraindítva a gép. Tehát mindenkinek a fájlját tessék feldolgozni :-)

Innentől kezdve meg minden fájllal két dolgot kell csinálni: kipucolni a múlbéli bejegyzéseket, a kipucolt fájllal felülcsapni az eredetit, majd ezt a takarított fájlt hozzáírni egy átmeneti fájlhoz, és a végén ezt a mindenki bejegyzéseit tartalmazót sort -n, és az első sorban lévő időre beállítani az ébresztést.

A trap meg legyen a barátod, ha átmeneti állományokat gyárt a scripted: a trap-ben hívott eljárásban takaríts, mert nagyon nem szép, ha ottmarad a /tmp (vagy bármi) alatt a szemét.

A systemd-s unitban megadott fájlt használja env fájlként, ha akarod, a /ide/rakom/az/env/fájlokat/mert/csak/fittyfene.env.de.a.kiterjesztés.sem.fontos.meg.lényeges állományt is megadhatod :-)

jajjaj, systemd service vs variable substitution meg ugy egyaltalan a valtozok kezelese egy csodas dolog, sokat lehet szenvedni vele:
https://www.freedesktop.org/software/systemd/man/systemd.service.html#E…

ez meg az environment szekcio: https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Envi…

Valamint kornyezeti valtozok is trukkosek, pl PATH modification: https://unix.stackexchange.com/questions/347873/set-path-for-a-systemd-…

Nos. Megoldottam, meg nem is. Első körben visszavettem az arcomból, és teljesen felhasználói szintre mentem. systemd ott is van. Némiképp módosítottam a service fájlt, és jelentem működik. DE csak egy feltétellel, ha előtte manuálisan elindítom a service-t. A gép bekapcsolása után jelenleg:

$ systemctl --user status dtvrip-wake.service 
● dtvrip-wake.service - Wake dtvRip
   Loaded: loaded (/home/nextra/.config/systemd/user/dtvrip-wake.service; enabled; vendor preset: enabled)
   Active: inactive (dead)

Engedélyezve van, ahogy írja, és arra számítottam, hogy elindul ha itt az ideje. Persze, ha manuálisan "bestartolom", akkor minden rendben. Lefut és be is kapcsolja a gépet a megfelelő időben. Most azt keresem, hogy miként lehetne ezt a problémát megoldani. 

Valahol ezt olvastam. "Alapértelmezés szerint a systemd elindítja az engedélyezett felhasználói egységeket, amikor a felhasználó bejelentkezik, és leállítja őket, miután a felhasználó kijelentkezett ." No de akkor?

A # loginctl user-status USER nem jeleníti meg ezt a service-t. Valami linger is képben lehet. Nem vagyok otthon ebben.