Fórum Root.cz
Hlavní témata => Software => Téma založeno: LarryLin 25. 02. 2019, 11:02:40
-
Potřeboval bych poradit se systemd. Non-root uživatelé si sami spouští "/bin/programX". Do "programX" se musí před vypnutím/rebootem PC poslat určitý příkaz, aby se ukončil korektně. To dělá script "stop.sh", který najde všechny běžící procesy "programX" a pošle do nich daný příkaz pro korektní ukončení. Nevím jak to udělat, aby se "stop.sh" spouštěl před vypnutím/rebotováním PC, ale ještě ve chvíli kdy běží "programX".
Co jsem zkoušel:
1.) Udělat z "programX" službu systemd - to funguje, ale je to pro mě nepraktické.
2.) Vytvořil jsem službu podle tohoto návodu (https://unix.stackexchange.com/questions/347275/how-to-run-a-script-at-shutdown-on-debian-9-or-raspbian-8-jessie/347686#347686)
[Unit]
Description=Something
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/true
ExecStop=/bin/stop.sh
[Install]
WantedBy=multi-user.target
Služba funguje a "stop.sh" se skutečně spustí - bohužel se spouští příliš pozdě, kdy byl "programX" již ukončen.
2b.) Zkoušel jsem přidat "Before=shutdown.target" nebo změnit "WantedBy=default.target", ale nepomohlo.
3.) Umístit "stop.sh" do /usr/lib/systemd/system-shutdown/ - taktéž se spouští až v hodně pozdní fázi kdy programX již neběží.
Podle mě by stačilo u služby z bodu 2 přidat nějaké závislosti (Before=), aby se začala ukončovat v co nejranější fázi vypínání/rebootování, ale nevím co tam dát. Případně pokud existuje jiný způsob, tak budu rád za nějakou radu.
-
Uvedenú možnosť som neskúmal. Ja to mám vyriešené cez /etc/gdm/PostSession/Default v ktorom som dopísal:
LOGOFF="/opt/sys/logoff.sh"
if [ -e $LOGOFF ]; then
$LOGOFF $USER
fi
logoff.sh bude najskôr asi to, čo u teba stop.sh
-
Gnome nepoužívám, ale u mě bych možná taky našel nějakou podobnou událost na kterou to navázat, ale zdá se mi to z principu špatné řešení kvůli přenositelnosti nebo kdybych změnil DE, tak by to přestalo fungovat.
Zkoušel jsem ještě službu systemd (z bodu 2) spouštět jako uživatelskou s parametrem "--user". Sice se spustila když ještě programX běžel, ale než se "stop.sh" stačil dokončit, tak se počítač vypl. Nepomohlo ani přidání "TimeoutStopSec=120" a "KillMode=none".
-
ahoj,
SystemD ma jednu taku nepeknu vlastnost, ze vsetky user session processy, bezia v user scope pod user.slice. Pri shutdowne a reboote, sa tymto procesom posle SIGTERM. Akakolvek unita ktoru spravis, tak sa spusti pravdepodobne neskor ako systemd zakilluje tvoj programx.
Riesenie je, ze programx, bude reagovat na sigterm a ukonci sa korektne.
Napriklad, takto ze uzivatelia nebudu spustat
/usr/bin/programx ale /usr/local/bin/programx ( ak spustaju len programx, tak sa spusti ten, ktory ma vyssiu prioritu v PATH)
a /usr/local/bin/programx bude shellskript asi taky
#!/bin/bash
exit_handler(){
PID=$1
# do whatever you want
}
/usr/bin/programx &
trap "exit_handler $! arg2 argn" TERM INT
wait
-
Čau, trap jsem vyzkoušel a při ručním vypínání pomocí "kill -TERM <pid>" fungoval, ale když jsem vypl PC, tak se "exit_handler()" vůbec nespustil. Musel jsem za "TERM INT" přidat ještě HUP (nemám Ubuntu, ale zde je asi vysvětlení: https://askubuntu.com/questions/819730/no-sigterm-before-sigkill-shutdown-with-systemd-on-ubuntu-16-04 ). Po přidání HUP se "exit_handler()" při vypínání PC skutečně spustil, bohužel "stop.sh" se nestihl dokončit (trvá několik desítek sekund).
Takže v podstatě stejný problém jako u té mé "--user" služby, tzn. stop.sh se spustí, ale během provádění mi systemD KILLne (nebo spíše HUPne) programX. Zkoušel jsem u tvého příkladu změnit "/usr/bin/programx &" na "nohup /usr/bin/programx & disown" (nebo i bez disown), aby programX ignoroval HUP. Bez úspěchu.
Zjistil jsem, že systemD umí vytvářet dočasné služby, takže jediné funční řešení zatím je, že uživatelé musí programX spouštět takto:
systemd-run --user -p ExecStop=/path/to/stop.sh programX
Bylo by lepší kdyby to nějak šlo bez systemd-run, aby to pro uživatele bylo jednodušší, ale jediné co mě napadá je spouštět cron, který bude kontrolovat běžící procesy a pokud najde programX, tak z něj udělá dočasnou službu, ale to už se mi zdá trochu hardcore.
PS: Ještě jsem zkoušel "systemd-inhibit programX" (man systemd-inhibit (https://www.freedesktop.org/software/systemd/man/systemd-inhibit.html)), který by měl zablokovat vypnutí/resetování/spánek... Typickým využitím má být, zablokování vypnutí když se vypalují zálohy na DVD. Příkaz "systemd-inhibit --list" mi ukazoval, že programX tam je, ale k žádnému blokování při vypnutí nedošlo, protože programX se po signálu TERM nebo HUP asi normálně ukončil a tudíž nemohl nic blokovat, takže jsem nějak nepochopil jak to má fungovat.
-
tak potom asi spravit
/usr/local/bin/programx
exec systemd-run --user -p ExecStop=/path/to/stop.sh programX
-
Nevím jak moc je toto řešení běžné, mně se to zdá trochu prasárna podstrkovat uživatelům jiný program, ale je to asi nejjednodušší řešení. Díky.
Takže nakonec /usr/local/bin/programX vypadá takto:
#!/bin/bash
PARAM=Získání parametru z $@
exec systemd-run --user -p ExecStop="/path/to/stop.sh $PARAM" /bin/programX $@
a vypadáto, že vše funguje.
Útěchou je, že alespoň při hibernaci/spánku to jde podstatně jednodušeji - stačí umístit script stop.sh do /usr/lib/systemd/system-sleep/
-
Muzes byt v klidu. Je to naprosto bezne reseni, navic docela elegantni a systemove. Vetsina enterprise produktu pouziva bash skripty pro start aplikaci.
p.s. Asi bys mel dat $@ na konci do uvozovek --> "$@".
Michal