Killwine - zabijanie procesów wine

Skrypt do ubijania procesów Wine - jak ktoś się bawi w uruchamianie programów pod Wine to będzie wiedział o co chodzi :wink:

Znaleziony na oficjalnym forum Manjaro

#!/bin/bash

wine_cellar="${HOME}/.wine"

if (($#)); then
    if [[ -e "${wine_cellar}/$1" ]]; then
        WINEPREFIX="${wine_cellar}/$1"
        shift
    elif [[ "${1:0:1}" != "-" ]]; then
        echo "ERROR: Didn't understand argument '$1'?" >&2;
        exit 1
    fi
fi

if ((${#WINEPREFIX})); then
    pids=$(
        grep -l "WINEPREFIX=${WINEPREFIX}$" $(
            ls -l /proc/*/exe 2>/dev/null |
            grep -E 'wine(64)?-preloader|wineserver' |
            perl -pe 's;^.*/proc/(\d+)/exe.*$;/proc/$1/environ;g;'
        ) 2> /dev/null |
        perl -pe 's;^/proc/(\d+)/environ.*$;$1;g;'
    )
else
    pids=$(
        ls -l /proc/*/exe 2>/dev/null |
        grep -E 'wine(64)?-preloader|wineserver' |
        perl -pe 's;^.*/proc/(\d+)/exe.*$;$1;g;'
    )
fi

if ((${#pids})); then
    set -x
    kill $* $pids
fi
1 polubienie

Działa, choć nie kasuje wszystkiego. Zostawia jeden proces: C:\windows\system32\winedevice.exe - ok 10 MiB. Ale to drobiazg.

Hmm, wygląda na to, że dałoby się łatwo zmodyfikować skrypt tak, aby ubijał również proces winedevice.
Jak na mój gust wystarczy zmodyfikować linie: 19 oraz 27:

 grep -E 'wine(64)?-preloader|wineserver' |

na

 grep -E 'wine(64)?-preloader|wineserver|winedevice' |

Ale to tak trochę na “czuja” i nie przetestowane :slight_smile:

Dokładnie tak samo na “czuja” :slight_smile: próbowałem. Są 2 procesy o takiej nazwie i skrypt uwala tylko jeden z nich.

Edit:
Zapuściłem to teraz z konsoli i wyszło coś ciekawego.
Skrypt pokazuje procesy, które ubijał (a przynajmniej próbował) i jest wśród nich ten, który nie dał się ubić (w tym przypadku, ten “niezatapialny” to był proces 10021):

./KillWine.sh
++ kill 10003 10006 10016 10021 10034 9994 9997

Sprawdziłem teraz u siebie z pinballem - chyba z WindowsaXP… i u mnie niezmodyfikowany skrypt zabija wszystkie procesy, czyli działa dobrze i skutecznie.

Nie mam za bardzo pomysłu co może być nie tak.

Nazwa winedevice.exe sugeruje, że chodzi o urządzenie. Jeżeli hardware’owe, to może @majo masz coś podłączone, z zabiciem czego system ma problem. Jeżeli software’owe, to … może masz dwa prefix’y (dwie instancje, wersje) wine. A może masz coś uruchomione na root’cie, co blokuje.

Korzystam z wine-staging i pulpitu wirtualnego. Być może to generuje drugi proces C:\windows\system32\winedevice.exe .

Dwa procesy o takiej nazwie uruchamiane są w momencie uruchomienia wine i niezależnie od tego, ile programów działa pod wine.
Po zamknięciu wszystkich programów w wine w normalny sposób, oba te procesy znikają.
Tak to wygląda, przy uruchomionej jednej aplikacji pod wine:

co do wine to najlepszy jest:

wine-staging-nine

z łatką do 10’ki


nie testowałem ale coby ubić wine to nie wystarczy:

killall wine -9
1 polubienie

Jeśli chodzi wine, to wszystko zależy od tego, do czego jest potrzebne. Ja akurat koniecznie potrzebuję wirtualny pulpit pod wine, a na W10 mi nie zależy, więc wine-staging mi pasuje.

Natomiast eksperymentując z komendą killall, znalazłem sekwencję, która dla większości przetestowanych programów uruchomionych pod wine (z wyjątkiem jednego programu) zabija wszystkie procesy pod wine:
killall -I -w -r .exe

Nie ma szans, wine uruchamia wiele procesów i żaden z nich nie nazywa się dokładnie wine

Bardziej już stosując wyrażenie regularne…

killall -r wine*

Nie wszystkie procesy, należące do programów pracujących pod wine, mają tekst “wine” w nazwie, więc taka komenda nie zawsze zabije wszystkie procesy z wine.

Po kolejnych testach proponuję złożoną komendę (koniecznie w takiej kolejności)
killall -I -w -r .exe && killall -I -w -r wine

Jednak trzeba pamiętać, że przy ubijaniu procesów wine za pomocą killall lub skryptu KillWine, istnieje pewne niebezpieczeństwo przypadkowego ubicia jakiegoś procesu linuksowego, nie pracującego pod wine, który posiada w swojej nazwie tekst “.exe”, “wine” lub inny użyty w skrypcie KillWine.

Za pomocą kombinacji z killall istnieje prawdopodobieństwo ubicia innego procesu. Skrypt z pierwszego postu nie ubije żadnego przypadkowego procesu, ponieważ dokładnie sprawdza wg wzorca wyszukiwania:

wine(64)?-preloader|wineserver

Z moich testów - ograniczonych co prawda do kilku programów pod wine, wynika, że skrypt działa znakomicie.
Nie zdarzyło mi się jeszcze, aby pozostawił jakiś proces.

U mnie akurat, jak wcześniej pisałem, skrypt zostawia jeden proces, ale to drobnostka, którą można poprawić z poziomu menadżera zadań.
Natomiast (chyba?) skrypt KillWine będzie bezpieczniejszy i nie powinien usunąć np. działającego procesu twine, podczas gdy killall go na pewno usunie.

Skrypt nie usunie na pewno, killall w zależności co dokładnie mu się każe zrobić, np. wzorzec wine* nie pasuje do twine więc go nie usunie.

Komenda killall -r wine* usunie tylko procesy z nazwą rozpoczynającą się od tekstu “wine”.
Nie usunie natomiast procesów z tekstem “wine” w środku nazwy procesu, które pozostaną nietknięte. Przykład:


Aby skutecznie usunąć wszelkie procesy z tekstem “wine”, w dowolnym miejscu nazwy i pisane dowolną literą, należałoby zastosować komendę killall -I -w -r wine

Drążąc dalej temat, znalazłem rozwiązanie do bezpiecznego usunięcia absolutnie wszystkich procesów z “wine”, które bazuje na założeniu, że w linuksie nie ma procesów z tekstem “.exe” w nazwie, innych niż te używane przez wine (co chyba jest prawdą).

Zatem najpierw należałoby usunąć wszystko z “.exe” w nazwie za pomocą killall -I -w -r .exe , a następnie skorzystać z bezpiecznego kodu skryptu zamieszczonego w 1. poście do usunięcia pozostałych procesów wine.

Całość wyglądałaby tak:

#!/bin/bash

wine_cellar="${HOME}/.wine"

if (($#)); then
if [[ -e "${wine_cellar}/$1" ]]; then
    WINEPREFIX="${wine_cellar}/$1"
    shift
elif [[ "${1:0:1}" != "-" ]]; then
    echo "ERROR: Didn't understand argument '$1'?" >&2;
    exit 1
fi
fi

killall -I -w -r .exe

if ((${#WINEPREFIX})); then
pids=$(
    grep -l "WINEPREFIX=${WINEPREFIX}$" $(
        ls -l /proc/*/exe 2>/dev/null |
        grep -E 'wine(64)?-preloader|wineserver' |
        perl -pe 's;^.*/proc/(\d+)/exe.*$;/proc/$1/environ;g;'
    ) 2> /dev/null |
    perl -pe 's;^/proc/(\d+)/environ.*$;$1;g;'
)
else
pids=$(
    ls -l /proc/*/exe 2>/dev/null |
    grep -E 'wine(64)?-preloader|wineserver' |
    perl -pe 's;^.*/proc/(\d+)/exe.*$;$1;g;'
)
fi

if ((${#pids})); then
set -x
kill $* $pids
fi

A tak w ogóle, to w jakim celu ta operacja ma być przeprowadzana? Po, to aby wyczyścić system ze zbędnych procesów wine; zabicie wiszących procesów, aby ponownie uruchomić wine; czy coś innego?

A może zastopowanie server’a wine lub restart - czy, to nie rozwiązuje problemu?

Skrypt może być pomocny przy testowaniu programów pod wine, np. takich, które źle działają np. nie ma okna programu a proces sobie gdzieś zostaje i działa. Dawniej jak częściej próbowałem coś robić z wine, takie sytuacje u mnie się zdarzały.

Wszystko jasne i zrozumiałe, nabiera sensu.