Skip to content

Commit 293f843

Browse files
authored
Create check_updates_notify.sh
1 parent d349f6e commit 293f843

File tree

1 file changed

+294
-0
lines changed

1 file changed

+294
-0
lines changed
Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
#!/bin/bash
2+
3+
# _ _ _ ___ ____
4+
# | | | | __ _ ___| | _____ _ __ / _ \/ ___|
5+
# | |_| |/ _` |/ __| |/ / _ \ '__| | | \___ \
6+
# | _ | (_| | (__| < __/ | | |_| |___) |
7+
# |_| |_|\__,_|\___|_|\_\___|_| \___/|____/ _
8+
# | | | |_ __ __| | __ _| |_ ___ / ___| |__ ___ ___| | __
9+
# | | | | '_ \ / _` |/ _` | __/ _ \ | | | '_ \ / _ \/ __| |/ /
10+
# | |_| | |_) | (_| | (_| | || __/ | |___| | | | __/ (__| <
11+
# \___/| .__/ \__,_|\__,_|\__\___| \____|_| |_|\___|\___|_|\_\
12+
# |_|
13+
14+
LOGFILE="/tmp/hackeros-update-check.log"
15+
UPDATE_SCRIPT="/usr/share/HackerOS/Scripts/Bin/update_system.sh"
16+
AUTOSTART_FILE="/etc/xdg/autostart/hackeros-update-check.desktop"
17+
18+
# Proste logowanie (bez błędów jeśli brak praw)
19+
log() {
20+
echo "$(date --iso-8601=seconds) - $1" >> "$LOGFILE" 2>/dev/null || true
21+
}
22+
23+
command_exists() { command -v "$1" >/dev/null 2>&1; }
24+
25+
log "=== START check_updates_gui.sh ==="
26+
27+
# ---------------------------
28+
# BACKEND: tylko sprawdzenia (BEZ GUI)
29+
# ---------------------------
30+
31+
# APT
32+
if command_exists apt; then
33+
APT_UPDATES=$(apt list --upgradable 2>/dev/null | sed '/^Listing.../d;/^$/d' | wc -l)
34+
: $((APT_UPDATES=APT_UPDATES+0))
35+
else
36+
APT_UPDATES=0
37+
fi
38+
39+
# Flatpak
40+
if command_exists flatpak; then
41+
# remote-ls --updates może nie istnieć wszędzie; próbujemy i liczymy linie
42+
FLATPAK_UPDATES=$(flatpak remote-ls --updates 2>/dev/null | sed '/^$/d' | wc -l)
43+
: $((FLATPAK_UPDATES=FLATPAK_UPDATES+0))
44+
else
45+
FLATPAK_UPDATES=0
46+
fi
47+
48+
# Snap
49+
if command_exists snap; then
50+
SNAP_UPDATES=$(snap refresh --list 2>/dev/null | tail -n +2 | sed '/^$/d' | wc -l)
51+
: $((SNAP_UPDATES=SNAP_UPDATES+0))
52+
else
53+
SNAP_UPDATES=0
54+
fi
55+
56+
# Firmware (fwupd)
57+
if command_exists fwupdmgr; then
58+
FWUPD_UPDATES=$(fwupdmgr get-updates 2>/dev/null | sed '/^$/d' | grep -c -E "Update|Device" || true)
59+
: $((FWUPD_UPDATES=FWUPD_UPDATES+0))
60+
else
61+
FWUPD_UPDATES=0
62+
fi
63+
64+
TOTAL_UPDATES=$((APT_UPDATES + FLATPAK_UPDATES + SNAP_UPDATES + FWUPD_UPDATES))
65+
log "Sprawdzenie zakończone: APT=$APT_UPDATES, Flatpak=$FLATPAK_UPDATES, Snap=$SNAP_UPDATES, FWUPD=$FWUPD_UPDATES, SUMA=$TOTAL_UPDATES"
66+
67+
# Jeśli brak aktualizacji -> kompletnie ciche wyjście (nic nie uruchamiamy)
68+
if [ "$TOTAL_UPDATES" -le 0 ]; then
69+
log "Brak aktualizacji. Nic nie pokazuję. KONIEC."
70+
exit 0
71+
fi
72+
73+
# ---------------------------
74+
# Przygotowanie tekstu do GUI
75+
# ---------------------------
76+
UPDATE_DETAILS="<b>Dostępne aktualizacje:</b>\n\n"
77+
UPDATE_DETAILS+="• <b>APT</b>: $APT_UPDATES aktualizacji\n"
78+
UPDATE_DETAILS+="• <b>Flatpak</b>: $FLATPAK_UPDATES aktualizacji\n"
79+
UPDATE_DETAILS+="• <b>Snap</b>: $SNAP_UPDATES aktualizacji\n"
80+
UPDATE_DETAILS+="• <b>Firmware</b>: $FWUPD_UPDATES aktualizacji\n\n"
81+
UPDATE_DETAILS+="<b>Łącznie</b>: $TOTAL_UPDATES aktualizacji\n\n"
82+
UPDATE_DETAILS+="Wybierz akcję:"
83+
84+
# ---------------------------
85+
# Funkcje akcji
86+
# ---------------------------
87+
action_close() {
88+
log "Akcja: Zamknij"
89+
exit 0
90+
}
91+
92+
action_run_update_script_as_user() {
93+
local target_user="$1"
94+
local uid="$2"
95+
96+
log "Akcja: Zaktualizuj teraz (uruchamiam update script w kontekście $target_user UID=$uid)"
97+
98+
if [ ! -f "$UPDATE_SCRIPT" ]; then
99+
log "BŁĄD: Skrypt aktualizacji nie znaleziony: $UPDATE_SCRIPT"
100+
return 1
101+
fi
102+
103+
# Uruchom skrypt jako ten użytkownik z sudo (jeżeli wymagane) w tle, aby nie blokować GUI.
104+
# Najpierw spróbuj uruchomić z prawami użytkownika (jeśli update_script nie wymaga sudo)
105+
# Jeśli potrzebujesz sudo, skrypt będzie uruchamiany z sudo przez użytkownika.
106+
# Używamy runuser aby zachować środowisko użytkownika (bez tworzenia okien przed checkiem).
107+
if command_exists runuser; then
108+
# Uruchom z przekazanymi zmiennymi środowiskowymi (DISPLAY i DBUS)
109+
local envfile="/tmp/hackeros_update_env_${uid}.sh"
110+
# Utwórz envfile z potrzebnymi zmiennymi (jeżeli istnieją)
111+
echo "export DISPLAY='${DISPLAY_OVERRIDE:-:0}'" > "$envfile"
112+
if [ -n "$DBUS_OVERRIDE" ]; then
113+
echo "export DBUS_SESSION_BUS_ADDRESS='$DBUS_OVERRIDE'" >> "$envfile"
114+
fi
115+
chmod 600 "$envfile" 2>/dev/null || true
116+
117+
# Uruchom skrypt przez runuser w tle
118+
runuser -u "$target_user" -- bash -lc "source '$envfile' >/dev/null 2>&1; nohup sudo '$UPDATE_SCRIPT' >/dev/null 2>&1 & disown" >/dev/null 2>&1 || true
119+
rm -f "$envfile" 2>/dev/null || true
120+
log "Skrypt update uruchomiony (nohup) przez $target_user."
121+
else
122+
# Fallback: spróbuj zwykłego sudo w tle
123+
nohup sudo "$UPDATE_SCRIPT" >/dev/null 2>&1 & disown
124+
log "Skrypt update uruchomiony (nohup sudo fallback)."
125+
fi
126+
return 0
127+
}
128+
129+
action_disable_notifications() {
130+
log "Akcja: Nie pokazuj więcej -> usuwam: $AUTOSTART_FILE"
131+
if [ -f "$AUTOSTART_FILE" ]; then
132+
if sudo rm -f "$AUTOSTART_FILE" >/dev/null 2>&1; then
133+
log "Usunięto plik autostartu: $AUTOSTART_FILE"
134+
else
135+
log "Nie udało się usunąć autostartu (brak uprawnień?): $AUTOSTART_FILE"
136+
fi
137+
else
138+
log "Plik autostartu nie istniał: $AUTOSTART_FILE"
139+
fi
140+
exit 0
141+
}
142+
143+
# ---------------------------
144+
# Uruchomienie Zenity w kontekście sesji graficznej użytkownika
145+
# ---------------------------
146+
# Cel: wywołać Zenity tylko teraz (po wykryciu aktualizacji) w sesji graficznej zalogowanego użytkownika,
147+
# by okno należało do tej sesji i nie tworzyło "niewidzialnego" wpisu innego procesu na pasku zadań.
148+
149+
# Znajdź aktywną sesję użytkownika (preferuj aktywną sesję local)
150+
find_graphical_session() {
151+
# Preferuj loginctl (systemd) — zwraca USER:UID i SESSION
152+
if command_exists loginctl; then
153+
while IFS= read -r line; do
154+
# line: SESSION UID USER SEAT TTY
155+
session_id=$(echo "$line" | awk '{print $1}')
156+
# sprawdź czy sesja aktywna i ma Display
157+
active=$(loginctl show-session "$session_id" -p Active --value 2>/dev/null || echo "no")
158+
state=$(loginctl show-session "$session_id" -p State --value 2>/dev/null || echo "")
159+
user=$(loginctl show-session "$session_id" -p Name --value 2>/dev/null || echo "")
160+
uid=$(loginctl show-session "$session_id" -p Remote --value 2>/dev/null || true)
161+
# choose active local session
162+
if [ "$active" = "yes" ] || [ "$state" = "active" ]; then
163+
# Resolve user and uid
164+
USERNAME="$user"
165+
USERID=$(id -u "$USERNAME" 2>/dev/null || true)
166+
echo "$USERNAME:$USERID:$session_id"
167+
return 0
168+
fi
169+
done < <(loginctl list-sessions --no-legend 2>/dev/null | awk '{print $1}')
170+
fi
171+
172+
# Fallback: wybierz pierwszy użytkownika z procesem typu gnome-session/plasma-session/Xorg/Xwayland
173+
for p in gnome-session plasma-session startplasma-x11 Xorg Xwayland; do
174+
pid=$(pgrep -u "$(logname 2>/dev/null || echo $USER)" -x "$p" | head -n1)
175+
if [ -n "$pid" ]; then
176+
USERNAME=$(ps -o user= -p "$pid" | awk '{print $1}')
177+
USERID=$(id -u "$USERNAME" 2>/dev/null || true)
178+
echo "$USERNAME:$USERID:na"
179+
return 0
180+
fi
181+
done
182+
183+
# Ostatecznie zwróć bieżącego użytkownika procesu wykonującego (jeśli to nie root)
184+
if [ -n "$SUDO_USER" ]; then
185+
USERNAME="$SUDO_USER"
186+
else
187+
USERNAME="$(logname 2>/dev/null || echo $USER)"
188+
fi
189+
USERID=$(id -u "$USERNAME" 2>/dev/null || true)
190+
echo "$USERNAME:$USERID:na"
191+
return 0
192+
}
193+
194+
session_info=$(find_graphical_session)
195+
USERNAME="$(echo "$session_info" | cut -d: -f1)"
196+
USERID="$(echo "$session_info" | cut -d: -f2)"
197+
198+
log "Wybrana sesja użytkownika: USER=$USERNAME UID=$USERID"
199+
200+
# Przygotuj zmienne środowiskowe dla sesji użytkownika (DISPLAY i DBUS)
201+
# Najczęściej DISPLAY=:0 i DBUS pod /run/user/$UID/bus
202+
DISPLAY_OVERRIDE=""
203+
DBUS_OVERRIDE=""
204+
205+
# Jeśli XDISPLAY jest ustawiony w środowisku aktualnego użytkownika (próba odczytu), użyj go
206+
# Spróbuj odczytać DISPLAY i DBUS z plików w /proc dla procesu sesji (jeśli możliwe)
207+
if [ -n "$USERID" ] && [ "$USERID" != "0" ]; then
208+
# Najpierw ustaw domyślnie DISPLAY=:0
209+
DISPLAY_OVERRIDE=":0"
210+
# DBUS session bus
211+
if [ -e "/run/user/${USERID}/bus" ]; then
212+
DBUS_OVERRIDE="unix:path=/run/user/${USERID}/bus"
213+
fi
214+
fi
215+
216+
# Jeśli mamy DBUS_OVERRIDE i DISPLAY_OVERRIDE to spróbuj uruchomić zenity jako ten user
217+
if command_exists zenity && [ -n "$DISPLAY_OVERRIDE" ]; then
218+
# Zbuduj polecenie zenity (radiolist)
219+
ZEN_CMD="zenity --list --radiolist --title='Aktualizacje systemu' --text='$UPDATE_DETAILS' --column='' --column='Akcja' TRUE 'Zamknij' FALSE 'Zaktualizuj teraz' FALSE 'Nie pokazuj więcej' --width=520 --height=300"
220+
221+
# Uruchom w kontekście użytkownika, przekazując potrzebne env
222+
# Najpierw sprawdź czy runuser istnieje i możemy go użyć
223+
if command_exists runuser; then
224+
# Eksportujemy DISPLAY i DBUS w linii poleceń, aby zenity należał do sesji tego użytkownika
225+
if [ -n "$DBUS_OVERRIDE" ]; then
226+
# Zapisz je w zmiennej i uruchom
227+
log "Uruchamiam Zenity jako $USERNAME z DISPLAY=$DISPLAY_OVERRIDE i DBUS=$DBUS_OVERRIDE"
228+
runuser -u "$USERNAME" -- bash -lc "export DISPLAY='$DISPLAY_OVERRIDE'; export DBUS_SESSION_BUS_ADDRESS='$DBUS_OVERRIDE'; $ZEN_CMD" >/tmp/hackeros_zenity_out.$$ 2>/tmp/hackeros_zenity_err.$$ || true
229+
CHOICE=$(cat /tmp/hackeros_zenity_out.$$ 2>/dev/null || true)
230+
rm -f /tmp/hackeros_zenity_out.$$ /tmp/hackeros_zenity_err.$$ 2>/dev/null || true
231+
else
232+
# Brak DBUS, uruchom jedynie z DISPLAY
233+
log "Uruchamiam Zenity jako $USERNAME z DISPLAY=$DISPLAY_OVERRIDE (brak DBUS)"
234+
runuser -u "$USERNAME" -- bash -lc "export DISPLAY='$DISPLAY_OVERRIDE'; $ZEN_CMD" >/tmp/hackeros_zenity_out.$$ 2>/tmp/hackeros_zenity_err.$$ || true
235+
CHOICE=$(cat /tmp/hackeros_zenity_out.$$ 2>/dev/null || true)
236+
rm -f /tmp/hackeros_zenity_out.$$ /tmp/hackeros_zenity_err.$$ 2>/dev/null || true
237+
fi
238+
else
239+
# fallback: uruchom bez runuser ale z env (może pojawić się w kontekście tego procesu)
240+
log "Brak runuser — uruchamiam Zenity w bieżącym kontekście (fallback)"
241+
export DISPLAY="$DISPLAY_OVERRIDE"
242+
[ -n "$DBUS_OVERRIDE" ] && export DBUS_SESSION_BUS_ADDRESS="$DBUS_OVERRIDE"
243+
CHOICE=$(bash -c "$ZEN_CMD" 2>/dev/null) || true
244+
fi
245+
else
246+
# Brak zenity lub brak DISPLAY info -> fallback tekstowy w terminalu (jeśli ktoś uruchamia ręcznie)
247+
log "Zenity niedostępny lub brak informacji o DISPLAY/DBUS -> fallback terminal"
248+
echo -e "$UPDATE_DETAILS"
249+
echo "1) Zamknij"
250+
echo "2) Zaktualizuj teraz"
251+
echo "3) Nie pokazuj więcej"
252+
read -rp "Wybór: " choice
253+
case $choice in
254+
1) action_close ;;
255+
2) action_run_update_script_as_user "$USERNAME" "$USERID"; exit 0 ;;
256+
3) action_disable_notifications ;;
257+
*) action_close ;;
258+
esac
259+
fi
260+
261+
# Jeżeli CHOICE jest puste oznacza że użytkownik zamknął okno -> nic do zrobienia
262+
if [ -z "${CHOICE:-}" ]; then
263+
log "Brak wyboru (okno zamknięte lub anulowane). Kończę."
264+
exit 0
265+
fi
266+
267+
# Znormalizuj możliwe wyniki (Zenity może zwracać etykietę)
268+
case "$CHOICE" in
269+
"Zamknij"|"Zamknij\n"|"Zamknij\r")
270+
action_close
271+
;;
272+
"Zaktualizuj teraz"|"Zaktualizuj teraz\n")
273+
# Uruchom update script w kontekście użytkownika, by okno postępu (jeśli będą) pojawiło się w sesji
274+
# Przekaż username i uid
275+
action_run_update_script_as_user "$USERNAME" "$USERID"
276+
;;
277+
"Nie pokazuj więcej"|"Nie pokazuj więcej\n")
278+
action_disable_notifications
279+
;;
280+
*)
281+
# W niektórych środowiskach zenity może zwracać wynik w innym formacie - porównaj fragmenty
282+
if echo "$CHOICE" | grep -qi "Zaktualizuj"; then
283+
action_run_update_script_as_user "$USERNAME" "$USERID"
284+
elif echo "$CHOICE" | grep -qi "Nie pokazuj"; then
285+
action_disable_notifications
286+
else
287+
action_close
288+
fi
289+
;;
290+
esac
291+
292+
# Koniec
293+
log "Koniec działania skryptu."
294+
exit 0

0 commit comments

Comments
 (0)