- FSEvents: Разбираемся с мониториногом событий файловой системы в macOS
- Подписываемся на события программно
- Подписываемся на поток событий файловой системы
- Обрабатываем полученные события
- Останавливаем получение событий
- Использование класса
- Фильтрация событий
- Заключение
- Программа должна говорить Hello world, но выдаёт ошибку?
- System Events: What Is It?
- Mikuro
FSEvents: Разбираемся с мониториногом событий файловой системы в macOS
File System Events (далее FSEvents) — механизм, доступный в macOS начиная с версии 10.5, который позволяет подписываться на уведомления об изменениях в структуре папок, а также их содержимого. Он используется многими системными утилитами, например Time Machine. Стоит отметить, что мониторинг происходит на уровне директории: иными словами придет уведомление, что в директории изменился некий файл, но конкретной информации об изменениях в нём содержаться не будет. Для более детального мониторинга придётся спускаться на уровень ниже и использовать kqueues, либо писать собственный kext. Поэтому для написания собственного антивируса такой механизм не подойдет, а вот для своего аналога Dropbox, или чего-то подобного — вполне.
Механизм FSEvents состоит из трёх базовых частей:
- Код ядра транслирует события в пространство пользователя;
- Демон fseventsd обрабатывает эти события и рассылает уведомления;
- База данных, где хранятся записанные логи.
Изначально информация о событиях хранится в памяти. Когда происходит событие, ему назначается 64-битный идентификатор. Может получиться так что событие пришло с уже назначенным идентификатором, в этом случае, просто обновятся флаги. После того, как буфер памяти заполнится события записываются на диск.
Если выполнить в терминале ls -la / , можно увидеть в корне раздела директорию .fseventsd , куда упомянутый демон пишет логи. Посмотреть содержимое файлов так просто не получится, для этой цели можно воспользоваться скриптом FSEventsParser, он поможет экспортировать их в текстовом формате, либо как базу данных SQLite. Второй вариант обычно предпочтительнее, так как он позволит использовать SQL-запросы для фильтрации событий (которых обычно больше миллиона).
В целях безопасности, уведомления о событиях возвращаются только для тех папок, к которым есть доступ у пользователя, под которым запущена программа, подписанная на эти события. Существует возможность и полностью запретить логирование событий файловой системы на уровне раздела: для этого в корне нужно создать директорию .fseventsd , куда положить пустой файл с названием no_log .
Может показаться, что исторические данные из FSEvents — не самая полезная информация, однако косвенно они могут помочь, например при исследовании атакованной системы. Так как малварь обычно чистит за собой следы, то записи о создании подозрительных plist’ов, например в /Library/LaunchDaemons , теоретически могут помочь идентифицировать поработавшего зловреда, что станет весомым артефактом в дальнейшем расследовании. Также по записям можно увидеть активность в домашней директории пользователя, файлы перемещенные в корзину, активность в интернете и многое другое. На iOS тоже можно получить данные из FSEvents, но для этого понадобится джейлбрейк.
Подписываемся на события программно
Если тебя больше интересует возможность подписаться на события и слушать их программно, то предлагаю реализовать для этого несложный класс, который будет подписываться на уведомления в заданной директории и возвращать информацию об изменениях (путь к файлу и флаги изменений) в колбек.
Подписываемся на поток событий файловой системы
Откроем Xcode и создадим новый проект, это будет Cocoa App (на вкладке macOS), язык выберем Swift. Создадим новый класс (File > New > File > macOS > Swift file) под названием FSEventsService и напишем следующий код:
Здесь мы просто объявили класс и создали несколько переменных. Теперь нам нужно запустить мониторинг событий, для этого определим следующий метод:
API FSEvents — это C API, мы можем его использовать из Swift, но нам потребуется учесть несколько особенностей. Разберем код метода по частям. Сначала мы создаем контекст и в него записываем указатель на наш экземпляр класса. Это нужно для того, чтобы иметь возможность потом к нему обратиться из C-функции, которую мы передаём в качестве коллбека, куда будут приходить события.
Далее определяем 2 флага: kFSEventStreamCreateFlagUseCFTypes — говорит нашему потоку данных, чтобы он возвращал значения в типах Core Foundation, вместо чистых C-типов и kFSEventStreamCreateFlagFileEvents — просит передавать события на уровне файлов, а не на уровне директории (иначе будут приходить только уведомления об изменениях в директории, но не будет информации, что за файл изменился).
Теперь осталось создать поток событий и передать в него необходимую информацию, а именно:
- Алокатор, используется для выделения памяти для потока. Используем значение по-умолчанию;
- Колбек, функция которая будет вызвана, когда произойдет событие, её реализуем ниже;
- Контекст, структура, которую мы создали ранее для того, чтобы передать указатель на экземпляр нашего класса;
- Пути к директориям, в которых нужно мониторить события;
- Идентификатор события, начиная с которого запрашивать события, выставляем с текущего момента;
- Задержка с которой нужно запрашивать у ядра события, здесь для простоты выставим 0, но вообще лучше поиграть с этим значением, для лучшей производительности;
- Флаги для изменения поведения потока, которые мы определили выше.
После этого остаётся только добавить поток событий в RunLoop (часть инфраструктуры отвечающая за обработку асинхронных событий, приходящих в поток) и запустить мониторинг.
Обрабатываем полученные события
Реализация колбэка будет выглядеть так:
Здесь мы получаем экземпляр нашего класса из контекста и записываем его в переменную mySelf. Из нее извлекаем колбек, который мы передали при инициализации нашего класса, пробегаем в цикле по пришедшим событиям, в нём создаем структуру, которая содержит информацию о событии (идентификатор события, путь и флаги) и передаем ее в этот коллбек.
Структура с информацией о событии выглядит следующим образом:
Останавливаем получение событий
Здесь все достаточно просто: нужно вызвать несколько методов для остановки потока событий:
Вызов этого метода можно добавить, например, в deinit :
Использование класса
На этом написание простейшей обёртки закончено, мы теперь легко можем получить события от файловой системы, например:
После запуска в логе приложения можно будет увидеть строки с измененными файлами. Перед запуском нужно не забыть отключить Sandbox (выбрать проект в инспекторе слева, перейти на вкладку Capabilities, отключить App Sandox), иначе у приложения будет доступ к файловой системе только внутри песочницы.
Фильтрация событий
В результате работы нашего класса, мы получили флаг события, который представляет собой битовую маску. Apple заранее определила определила для нас костанты с флагами, соотвествующими опредлённому типу события. Например, если мы захотим отфильтровать только события с созданием файла, это будет выглядеть следующим образом:
Подбирая комбинации флагов, можно гибко настроить получаемый поток событий под собственные нужды. Полный список флагов можно найти в документации.
Заключение
Сегодня мы рассмотрели реализацию собственной обертки над API FSEvents, если не считать взаимодействие с API на C, то использовать из Swift его довольно просто и не должно вызвать затруднений. На GitHub можно найти большое количество библиотек, схожих с тем, что мы реализовали сегодня. Пользоваться ими или нет, нужно решать исходя из конкретных задач: с одной стороны зачем писать лишний boilerplate, когда кто-то его уже написал за тебя, а с другой стороны в сложных решениях, всё равно приходится разбираться с внутренним устройством библиотек и докручивать их под специфичные нужды заказчика, так что может быть имеет смысл написать такой класс с нуля.
Источник
Программа должна говорить Hello world, но выдаёт ошибку?
Дело не в коде программы. os.system выполняет команду. Выполняемый файл say в системе есть и он может вызываться из директории, откуда питон вызывает команды ?
‘say’ is not recognized as an internal or external command, operable program or batch file.
import speech_recognition
import os
import sys
import webbrowser
words = «Hello world»
def talk(words):
______print(words)
______os.system(«say » + words)
talk(words)
Тимур Покровский, чтобы заработало нужно скачать PyAudio, но выдаёт ошибку
Collecting PyAudio
Using cached PyAudio-0.2.11.tar.gz (37 kB)
Building wheels for collected packages: PyAudio
Building wheel for PyAudio (setup.py) . error
ERROR: Command errored out with exit status 1:
command: ‘c:\users\temp\appdata\local\programs\python\python37-32\python.exe’ -u -c ‘import sys, setuptools, tokenize; sys.argv[0] = ‘»‘»‘C:\\Users\\TEMP\\AppData
\\Local\\Temp\\pip-install-cgkci2ic\\PyAudio\\setup.py'»‘»‘; __file__='»‘»‘C:\\Users\\TEMP\\AppData\\Local\\Temp\\pip-install-cgkci2ic\\PyAudio\\setup.py'»‘»‘;f=geta
ttr(tokenize, ‘»‘»‘open'»‘»‘, open)(__file__);code=f.read().replace(‘»‘»‘\r\n'»‘»‘, ‘»‘»‘\n'»‘»‘);f.close();exec(compile(code, __file__, ‘»‘»‘exec'»‘»‘))’ bdist_whee
l -d ‘C:\Users\TEMP\AppData\Local\Temp\pip-wheel-kcbryp_8’
cwd: C:\Users\TEMP\AppData\Local\Temp\pip-install-cgkci2ic\PyAudio\
Complete output (9 lines):
running bdist_wheel
running build
running build_py
creating build
creating build\lib.win32-3.7
copying src\pyaudio.py -> build\lib.win32-3.7
running build_ext
building ‘_portaudio’ extension
error: Microsoft Visual C++ 14.0 is required. Get it with «Build Tools for Visual Studio»: https://visualstudio.microsoft.com/downloads/
—————————————-
ERROR: Failed building wheel for PyAudio
Running setup.py clean for PyAudio
Failed to build PyAudio
Installing collected packages: PyAudio
Running setup.py install for PyAudio . error
ERROR: Command errored out with exit status 1:
command: ‘c:\users\temp\appdata\local\programs\python\python37-32\python.exe’ -u -c ‘import sys, setuptools, tokenize; sys.argv[0] = ‘»‘»‘C:\\Users\\TEMP\\AppDa
ta\\Local\\Temp\\pip-install-cgkci2ic\\PyAudio\\setup.py'»‘»‘; __file__='»‘»‘C:\\Users\\TEMP\\AppData\\Local\\Temp\\pip-install-cgkci2ic\\PyAudio\\setup.py'»‘»‘;f=ge
tattr(tokenize, ‘»‘»‘open'»‘»‘, open)(__file__);code=f.read().replace(‘»‘»‘\r\n'»‘»‘, ‘»‘»‘\n'»‘»‘);f.close();exec(compile(code, __file__, ‘»‘»‘exec'»‘»‘))’ install
—record ‘C:\Users\TEMP\AppData\Local\Temp\pip-record-ch8nh0_h\install-record.txt’ —single-version-externally-managed —compile —install-headers ‘c:\users\temp\app
data\local\programs\python\python37-32\Include\PyAudio’
cwd: C:\Users\TEMP\AppData\Local\Temp\pip-install-cgkci2ic\PyAudio\
Complete output (9 lines):
running install
running build
running build_py
creating build
creating build\lib.win32-3.7
copying src\pyaudio.py -> build\lib.win32-3.7
running build_ext
building ‘_portaudio’ extension
error: Microsoft Visual C++ 14.0 is required. Get it with «Build Tools for Visual Studio»: https://visualstudio.microsoft.com/downloads/
—————————————-
ERROR: Command errored out with exit status 1: ‘c:\users\temp\appdata\local\programs\python\python37-32\python.exe’ -u -c ‘import sys, setuptools, tokenize; sys.argv
[0] = ‘»‘»‘C:\\Users\\TEMP\\AppData\\Local\\Temp\\pip-install-cgkci2ic\\PyAudio\\setup.py'»‘»‘; __file__='»‘»‘C:\\Users\\TEMP\\AppData\\Local\\Temp\\pip-install-cgkc
i2ic\\PyAudio\\setup.py'»‘»‘;f=getattr(tokenize, ‘»‘»‘open'»‘»‘, open)(__file__);code=f.read().replace(‘»‘»‘\r\n'»‘»‘, ‘»‘»‘\n'»‘»‘);f.close();exec(compile(code, __f
ile__, ‘»‘»‘exec'»‘»‘))’ install —record ‘C:\Users\TEMP\AppData\Local\Temp\pip-record-ch8nh0_h\install-record.txt’ —single-version-externally-managed —compile —i
nstall-headers ‘c:\users\temp\appdata\local\programs\python\python37-32\Include\PyAudio’ Check the logs for full command output.
WARNING: You are using pip version 20.1.1; however, version 20.2.2 is available.
You should consider upgrading via the ‘c:\users\temp\appdata\local\programs\python\python37-32\python.exe -m pip install —upgrade pip’ command.
я так сделал, всё правильно или я что-то напутал, ведь не работает
import speech_recognition
import os
import sys
import webbrowser
Источник
System Events: What Is It?
Mac Convert for Life
I noticed System Events listed as one of my start-up items in System Preferences Accounts. It’s located in HD/system/library/core services and it says it’s an application. When I click on it, nothing happens except that my cursor reverts back to the previous state (I use Mighty Mouse). Can someone tell me what this System Events is and what it does . and why it’s listed as a start-up item? I didn’t put it there.
Mikuro
Crotchety UI Nitpicker
System Events controls Folder Actions (which are AppleScripts you can attach to folders so that they’ll run whenever the folder is opened or an item is added/removed from it, etc.).
It can also be used by AppleScript developers to do some very basic and useful things like managing files, getting information on running applications, and controlling interface elements by simulating keyboard/mouse actions. It’s a scripter’s best friend.
Mac Convert for Life
System Events controls Folder Actions (which are AppleScripts you can attach to folders so that they’ll run whenever the folder is opened or an item is added/removed from it, etc.).
It can also be used by AppleScript developers to do some very basic and useful things like managing files, getting information on running applications, and controlling interface elements by simulating keyboard/mouse actions. It’s a scripter’s best friend.
Thanks, Mikuro, for your reply. But now I have a couple more questions:
1. How did it get there (in my start-up items) if I didn’t put it there? I’m the only one who uses my iBook.
2. Should I delete it or uncheck it from launching/running upon startup or just leave it as is?
I never saw this before and now, suddenly, it’s there. It’s unsettling.
Источник