10

У меня есть приложение на OSX, которое постоянно переходит в состояние «Не отвечает» и должно быть принудительно уничтожено. Я надеялся автоматизировать его, но при проверке процесса с помощью ps я не вижу ничего, что соответствовало бы состоянию Not Responding. Я посмотрел на индикатор состояния , но приложение показывает как S , отвечает ли он или нет.

состояние Состояние задается последовательностью символов, например, `` RWNA ''. Первый символ указывает состояние выполнения процесса:

  • Я отмечаю процесс, который бездействует (спит дольше, чем около 20 секунд).
  • R отмечает работоспособный процесс.
  • S Отмечает процесс, который спит менее 20 секунд.
  • T отмечает остановленный процесс.
  • U отмечает процесс в непрерывном ожидании.
  • Z отмечает мертвый процесс ("зомби").

Как определить, не отвечает ли процесс, как это делает Менеджер активности?


Я также открыт для решений AppleScript.

3 ответа3

8

Состояние Not Responding - это не состояние процесса, а процесс прекратил связь с оконным менеджером / графическим ядром. Это может быть связано в цикле, висящем на сокете, удаленном файле, чем угодно, что заставляет его возвращаться в основной цикл, который обрабатывает события. Оконный менеджер замечает, что события находятся в очереди, и поэтому помечает его как "Не отвечающий".

Вам может потребоваться написать небольшую программу X11, которая отправляет фиктивные события процессу, а затем убить ее, если она не отвечает.

4

Вот AppleScript, использующий сценарии пользовательского интерфейса, который ищет не отвечающий процесс и убивает их.

Он будет работать с монитором активности Mavericks. Но так как это сценарии пользовательского интерфейса и пользовательский интерфейс Activity Monitor изменился, он, скорее всего, не будет работать со старой OS X без каких-либо незначительных изменений.

tell application "Activity Monitor" to run  --We need to run Activity Monitor
tell application "System Events" to tell process "Activity Monitor"
    tell radio button 1 of radio group 1 of group 1 of toolbar 1 of window 1 to click --Using the CPU View 
    tell outline 1 of scroll area 1 of window 1 -- working with the list 
        set notResponding to rows whose value of first static text contains "Not Responding" -- Looking for Not responding process
        repeat with aProcess in notResponding
            set pid to value of text field 5 of aProcess  -- For each non responding process retrieve the PID 
            if pid is not "" then do shell script ("kill -9 " & pid) -- KILL the PID. 
        end repeat
    end tell
end tell
0

(Размещать это как отдельный ответ, поскольку он слишком длинный, чтобы помещаться в комментарии

Благодарим @MatthieuRiegler за оригинальный сценарий.

Это сработало 10.12.6 и является незначительной модификацией оригинального сценария (см. Комментарий @ CharlieGorichanaz после того, как я провел собственное расследование):


set textToSearchForInProcessName to "Not Responding"

--  Run Activity Monitor 
tell application "Activity Monitor" to activate

tell application "System Events" to tell process "Activity Monitor"
    --  Wait for the Activity Monitor window to open
    repeat until (exists window 1)
        delay 1
    end repeat
    --display notification "Window appeared"

    --  Wait for the Menubar to be present
    repeat until (exists menu 1 of menu bar item "View" of menu bar 1)
        delay 1
    end repeat
    --display notification "Menubar appeared"

    --  Make sure View -> My Processes is selected 
    click menu item "My Processes" of menu 1 of menu bar item "View" of menu bar 1

    --  Click the 'CPU View' button  ( **1 ) 
    click radio button 1 of radio group 1 ¬
        of group 2 of toolbar 1 ¬
        of window 1

    --  Working with the list of processes 
    tell outline 1 of scroll area 1 of window 1
        --  Looking for Not responding process  
        set notResponding to rows whose value of ¬
            first static text contains textToSearchForInProcessName

        repeat with aProcess in notResponding

            --  For each non responding process retrieve the PID 
            set pid to value of text field 1 of aProcess -- ( **2 )

            --  Kill that process using pid 
            if pid is not "" then do shell script ("kill -9 " & pid)
        end repeat
    end tell
end tell

** 1 В macOS 10.12.x панель инструментов содержит дополнительный значок, благодаря которому набор кнопок (CPU, Memory, Energy и т. д.) находится в group 2 of toolbar 1 вместо group 1 of toolbar 1 . В отсутствие этого значка (я не подтвердил в старых версиях MacOS), я думаю, что кнопки процессора и т.д. Были бы в group 1 of toolbar 1

** 2 Это применимо, если вы когда-либо перетаскивали столбец PID в столбце Activity в другую позицию. Я перетащил столбец PID в крайнее левое положение, поэтому в этой строке мне пришлось изменить индекс на 1 :

set pid to value of text field 1 of aProcess

Столбцы пронумерованы слева, начиная с 1. Так что отрегулируйте подсвеченный индекс в строке выше, если это необходимо.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .