zepete: (Default)
[personal profile] zepete
Коомпьютер с linux при выключении не спрашивает разрешения на выключение у приложний, так как алгоритм выключения был придуман для консольного режима работы, когда все работающие приложения были демонами (аналог резидентов в DOS), которые нежалко убивать. В настоящее время, компьютер работает с оконными приложениями, которых, в момент нажатия на кнопку завершения работы, выполняется около десятка, причем в каждом из которых могут быть результаты многочасового труда пользователя компьютера. Но команда выключения linux этого не понимает и все их закрывает не посылая им никаких сообщений и недавая пользователю возможможности передумать. В результате все введенные тексты и нарисованные картинки, схемы, чертежи будут потерены безвозвратно.

То есть процесс завершения работы linux реализован хуже, чем было сделано в windows 3.1, вероятно даже 1.0. В windows при выключении компьютера окнам посылается куча сообщений с запросом завершения работы: WM_QUERYENDSESSION (запрос разрешения выключения), WM_ENDSESSION (иформирование об выключении), WM_CLOSE (запрос разрешения закрытия окна)..... В результате самая тупая программа понимает, что надо сохраняться. Все завершается корректно.

В стабильнейшемем gdk после десятков лет работы нет аналога WM_QUERYENDSESSION, а в описании GDK_DELETE, аналоге WM_CLOSE , не сказано, что оно посылается при выключении компьютера, а только при нажии на специальную кнопку на заголовке.

the window manager has requested that the toplevel window be hidden or destroyed, usually when the user clicks on a special icon in the title bar.


Самое любопытное, пользователей linux это нисколько не волнует. Я для решения этой проблемы придумал деревянный костыль, который надо поместить в автозагрузку и запускать от root. Делается это через sudo, visudo, sudoers.


Скрипт для перезагрузки.


#/bin/sh
export DISPLAY=":0"
ProgName="SwitchOff"

ErrMsg()
{
zenity --error --text "$1" --title "$ProgName"
}

wmvar=$(wmctrl -l) ; if [ $? -ne 0 ] ; then ErrMsg "wmctrl return error" ; exit ; fi
if [ "BAD" = "$(printf "%s" "$wmvar" | sed -nE '/^0[xX][[:xdigit:]]+[[:space:]]+[^[:space:]]+[[:space:]]+.*$/bskip;s/^.*$/BAD/p;:skip')" ]
then ErrMsg "wmctrl return error" ; exit ; fi

wmvar=$(printf %s "$wmvar" | grep -Ev '[[:xdigit:]]+[[:space:]]+-1')
if [ $? -ne 0 ] ; then ErrMsg "grep return error" ; exit ; fi
ListWID=$(printf %s "$wmvar" | sed -nE '/^[[:xdigit:]]+/s/^([[:xdigit:]xX]+).*$/\1/p')
if [ $? -ne 0 ] ; then ErrMsg "sed return error" ; exit ; fi

for wid in $ListWID
do
wmctrl -i -c $wid
#echo ""
done

i=600
NumWndOld=10000
( while [ $i -ne 0 ]
do
sleep 0.1s ; if [ $? -ne 0 ] ; then ErrMsg "sleep return error" ; exit ; fi
i=$(($i-1)) ; echo $((100-$i/6))
wmvar=$(wmctrl -l 2>&1) ; if [ $? -ne 0 ] ; then continue ; fi
if [ "BAD" = "$(printf "%s" "$wmvar" | sed -nE '/^0[xX][[:xdigit:]]+[[:space:]]+[^[:space:]]+[[:space:]]+.*$/bskip;s/^.*$/BAD/p;:skip')" ]
then continue ; fi
wmvar=$(printf %s "$wmvar" | grep -Ev '[[:xdigit:]]+[[:space:]]+-1' |\
grep -Ev "[[:xdigit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[^[:space:]]+[[:space:]]+$ProgName")
if [ "$wmvar" = "" ] ; then shutdown -r now ; exit ; fi
NumWnd=$(printf %s "$wmvar" | wc -l) ; if [ $? -ne 0 ] ; then ErrMsg "wc return error" ; exit ; fi
NumWnd=$(($NumWnd+1)) ; if [ $? -ne 0 ] ; then ErrMsg "calc expr return error" ; exit ; fi
echo "# Waiting close of $NumWnd windows."
if [ $NumWnd -ne $NumWndOld ] ; then wmctrl -i -a $(printf %s "$wmvar" | sed -nE '1s/^([[:xdigit:]xX]+).*$/\1/p') ; fi
NumWndOld=$NumWnd
done
) | zenity --progress --title="$ProgName" --text="waiting..." --percentage=0 --auto-close || exit






Скрипт для выключения.


#/bin/sh
export DISPLAY=":0"
ProgName="SwitchOff"

ErrMsg()
{
zenity --error --text "$1" --title "$ProgName"
}

wmvar=$(wmctrl -l) ; if [ $? -ne 0 ] ; then ErrMsg "wmctrl return error" ; exit ; fi
if [ "BAD" = "$(printf "%s" "$wmvar" | sed -nE '/^0[xX][[:xdigit:]]+[[:space:]]+[^[:space:]]+[[:space:]]+.*$/bskip;s/^.*$/BAD/p;:skip')" ]
then ErrMsg "wmctrl return error" ; exit ; fi

wmvar=$(printf %s "$wmvar" | grep -Ev '[[:xdigit:]]+[[:space:]]+-1')
if [ $? -ne 0 ] ; then ErrMsg "grep return error" ; exit ; fi
ListWID=$(printf %s "$wmvar" | sed -nE '/^[[:xdigit:]]+/s/^([[:xdigit:]xX]+).*$/\1/p')
if [ $? -ne 0 ] ; then ErrMsg "sed return error" ; exit ; fi

for wid in $ListWID
do
wmctrl -i -c $wid
#echo ""
done

i=600
NumWndOld=10000
( while [ $i -ne 0 ]
do
sleep 0.1s ; if [ $? -ne 0 ] ; then ErrMsg "sleep return error" ; exit ; fi
i=$(($i-1)) ; echo $((100-$i/6))
wmvar=$(wmctrl -l 2>&1) ; if [ $? -ne 0 ] ; then continue ; fi
if [ "BAD" = "$(printf "%s" "$wmvar" | sed -nE '/^0[xX][[:xdigit:]]+[[:space:]]+[^[:space:]]+[[:space:]]+.*$/bskip;s/^.*$/BAD/p;:skip')" ]
then continue ; fi
wmvar=$(printf %s "$wmvar" | grep -Ev '[[:xdigit:]]+[[:space:]]+-1' |\
grep -Ev "[[:xdigit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[^[:space:]]+[[:space:]]+$ProgName")
if [ "$wmvar" = "" ] ; then shutdown -h now ; exit ; fi
NumWnd=$(printf %s "$wmvar" | wc -l) ; if [ $? -ne 0 ] ; then ErrMsg "wc return error" ; exit ; fi
NumWnd=$(($NumWnd+1)) ; if [ $? -ne 0 ] ; then ErrMsg "calc expr return error" ; exit ; fi
echo "# Waiting close of $NumWnd windows."
if [ $NumWnd -ne $NumWndOld ] ; then wmctrl -i -a $(printf %s "$wmvar" | sed -nE '1s/^([[:xdigit:]xX]+).*$/\1/p') ; fi
NumWndOld=$NumWnd
done
) | zenity --progress --title="$ProgName" --text="waiting..." --percentage=0 --auto-close || exit




Это костыль, так как проблему он до конца не решает: он не умеет посылать сообщения окнам свернутым в трей.

Date: 2017-08-01 02:54 am (UTC)
From: [identity profile] vlkamov.livejournal.com
> недавая пользователю возможности передумать
Суть вашей претензии - "почему Линукс не Виндоуз ?"
Потому что нет необходимости.

При желании же можно применить отложенный shutdown
shutdown -s -t 3600

Можно тупо сделать составную команду
sleep 300; shutdown now
- она даже лучше читается

Кстати, без now сразу не выключает, видимо по умолчанию таймаут есть.

Можно привязать ее к кнопке выключения на рабочем столе или в меню.

Можно добавить проверку условий, например запущенных пользователем программ.

Этого в Линуксе не нет, но мало востребовано, поэтому и разговоров нет.

Date: 2017-08-01 12:50 pm (UTC)
From: [identity profile] talgaton.livejournal.com
"Коомпьютер с linux при выключении не спрашивает разрешения на выключение у приложний, так как алгоритм выключения был придуман для консольного режима работы, когда все работающие приложения были демонами (аналог резидентов в DOS), которые нежалко убивать. " -
ну это уже наглость.
большинство северов в в мире работают на линукс.
них работают базы данных и веб сервера.
базы данных работают - и обысно они запущены как демоны.

Date: 2017-08-02 12:51 am (UTC)
From: [identity profile] zepete.livejournal.com
Как я понимаю с серверами ничего плохого не произойдет, так как предусмотрена корректная запись буферов на диск при выключении, а вот документ какого-нибудь LibreOffice после выключения будет потерян, что более важно.

Date: 2017-08-02 01:22 am (UTC)
From: [identity profile] talgaton.livejournal.com
вот только что проверил.
внес в документ информацию и не сохраняя ее выключил перезагрузил (через меню).
либр офис у меня ничего не просил при выключении!
однако после загрузки, открыл офис - а внесенная информацию есть.

Date: 2017-08-02 12:06 pm (UTC)
From: [identity profile] zepete.livejournal.com
Он у вас, вероятно, не выключался, а засыпал.
Я снял "скринкаст" процесса перезагрузки с открытым офисом, в котором был несохраненный текст. На нем все видно.

Date: 2017-08-02 01:25 pm (UTC)
From: [identity profile] talgaton.livejournal.com
именно перезагрузился.
с полной процедурой загрузки.

Profile

zepete: (Default)
zepete

January 2026

S M T W T F S
    1 23
4 56 78910
11121314151617
18192021222324
25262728293031

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 14th, 2026 12:18 am
Powered by Dreamwidth Studios