Я не уверен, существует ли существующий код для этого. Но можно посмотреть на файл /var/lib/dpkg/status
. Вся информация об установленных пакетах хранится в этом файле.
Написать код, который проанализирует этот файл, довольно легко даже в случае, если Вы не являетесь великими в Python.
Linux обеспечивает два механизма для того, чтобы следить за развитием событий файловой системы; dnotify
и inotify
.
Более старые из этих двух, dnotify
, был представлен в версии 2.4.0 ядра. Это позволяет приложениям регистрироваться для получения уведомлений на изменениях в каталоге через fcntl()
интерфейс. Сами уведомления поставляются через сигналы. dnotify
механизм ограничен наблюдением изменений в каталоге, это не позволяет контролировать отдельных файлов. Кроме того, это требует поддержания открытого дескриптора файла к контролируемому каталогу. dnotify
механизм удерживался от использования в 2.6.13, когда inotify
был представлен.
Новые программы должны использовать inotify
механизм, который поддерживает контроль обоих каталогов и отдельных файлов. Это, однако, не на основе сигналов. inotify
экземпляр связан с дескриптором файла. Уведомления о событии могут быть прочитаны из этого дескриптора файла.
Ограничение обоих механизмов - то, что нет никакой опции смотреть каталоги рекурсивно. Это означает, что контроль должен быть установлен отдельно для каждого каталога в поддереве, за которым нужно наблюдать.
Пример (dnotify
):
#define _GNU_SOURCE
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
/* For error handling */
#include <stdlib.h>
#include <errno.h>
#include <error.h>
static volatile int event_fd;
static void handler(int sig, siginfo_t *si, void *data)
{
event_fd = si->si_fd;
}
int main(int argc, char *argv[])
{
struct sigaction sa;
int fd;
if(argc < 2)
error(EXIT_FAILURE, 0, "missing argument");
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sigaction(SIGRTMIN + 1, &sa, NULL);
if((fd = open(argv[1], O_RDONLY)) < 0)
error(EXIT_FAILURE, errno, "failed to open '%s'", argv[1]);
if(fcntl(fd, F_SETSIG, SIGRTMIN + 1) < 0)
error(EXIT_FAILURE, errno, "failed to set dnotify signal");
if(fcntl(fd, F_NOTIFY, DN_MODIFY|DN_CREATE|DN_DELETE|DN_MULTISHOT))
error(EXIT_FAILURE, errno,
"failed to register notification for '%s'", argv[1]);
while (1) {
pause();
printf("event occured for fd=%d\n", event_fd);
}
}
Объяснение:
fcntl(fd, F_SETSIG, SIGRTMIN + 1)
Устанавливает сигнал, отправленный, когда события уведомления имеют место. Значение нуля указывает на это SIGIO
(значение по умолчанию), отправляется. Любое другое значение, включая SIGIO
, интерпретируется как сигнал, который будет отправлен вместо этого. В последнем случае обработчик сигналов получает a siginfo_t
структура как ее второй аргумент, и si_fd
поле структуры будет содержать дескриптор файла, который генерировал событие.
Если сигнал в реальном времени (>= SIGRTMIN
) используется для уведомлений, несколько событий I/O могут быть поставлены в очередь с помощью того же числа сигнала (в зависимости от доступной памяти). Сигнал в реальном времени должен использоваться особенно при использовании DN_MULTISHOT
.
fcntl(fd, F_NOTIFY, DN_MODIFY|DN_CREATE|DN_DELETE|DN_MULTISHOT)
Устанавливает события, которые вызовут уведомления, когда каталог, упомянутый fd или любыми файлами, которые он содержит, будет изменен. Доступные типы событий:
DN_ACCESS
К файлу получают доступ.DN_MODIFY
Файл изменяется.DN_CREATE
Файл создается.DN_DELETE
Файл является несвязанным.DN_RENAME
Файл переименован в рамках каталога.DN_ATTRIB
Атрибуты файла изменяются.Уведомления обычно одноразовы, т.е. приложение должно повторно зарегистрироваться для получения дальнейших уведомлений. Если DN_MULTISHOT
указан, уведомления останутся в силе, пока явно не удалено.
Пример (inotify
):
#include <stdio.h>
#include <stdlib.h>
#include <sys/inotify.h>
/* For PATH_MAX */
#include <limits.h>
/* For error handling */
#include <errno.h>
#include <error.h>
int main(int argc, char *argv[]) {
int fd, wd, len, i;
char buf[sizeof(struct inotify_event) + PATH_MAX];
if (argc < 2)
error(EXIT_FAILURE, 0, "missing argument");
if ((fd = inotify_init()) < 0)
error(EXIT_FAILURE, errno, "failed to initialize inotify instance");
for (i = 1; i < argc; i++) {
if ((wd = inotify_add_watch (fd, argv[i],
IN_MODIFY | IN_CREATE | IN_DELETE)) < 0)
error(EXIT_FAILURE, errno,
"failed to add inotify watch for '%s'", argv[i]);
}
while ((len = read(fd, buf, sizeof(buf))) > 0) {
i = 0;
while (i < len) {
struct inotify_event *ie = (struct inotify_event*) &buf[i];
printf("event occured for '%s': ", argv[ie->wd]);
if (ie->mask & IN_MODIFY)
printf("%s was modified\n", ie->len ? ie->name : "file");
else if (ie->mask & IN_CREATE)
printf("%s was created\n", ie->name);
else if (ie->mask & IN_DELETE)
printf("%s was deleted\n", ie->name);
else
printf("unexpected event\n");
i += sizeof(struct inotify_event) + ie->len;
}
}
error(EXIT_FAILURE, len == 0 ? 0 : errno, "failed to read inotify event");
}
Объяснение:
fd = inotify_init()
Инициализирует новое inotify
экземпляр. Возвращаемое значение является дескриптором файла, связанным с недавно созданный inotify
очередь событий. По умолчанию дескриптор файла блокируется.
wd = inotify_add_watch (fd, argv[i], IN_MODIFY | IN_CREATE | IN_DELETE)
Новые объекты к списку часов, иначе часы добавляются с inotify_add_watch()
. Третьим аргументом является битовая маска, используемая для указания inotify
события для наблюдения за. Доступные типы событий:
IN_ACCESS
К файлу получают доступ.IN_ATTRIB
Атрибуты файла изменяются.IN_CLOSE_WRITE
Файл, открытый для записи, закрывается.IN_CLOSE_NOWRITE
Файл, открытый только для чтения, закрывается.IN_CREATE
Файл или каталог создается в рамках наблюдаемого каталога.IN_DELETE
Файл или каталог удален в рамках наблюдаемого каталога.IN_DELETE_SELF
Наблюдаемый файл или каталог удален.IN_MODIFY
Файл был изменен.IN_MOVE_SELF
Наблюдаемый файл или каталог перемещен.IN_MOVED_FROM
Файл перемещен из наблюдаемого каталога.IN_MOVED_TO
Файл перемещен в наблюдаемый каталог.IN_OPEN
Файл открыт.IN_ALL_EVENT
Все вышеупомянутое.IN_MOVE
Эквивалентный IN_MOVED_TO|IN_MOVED_FROM
IN_CLOSE
Эквивалентный IN_CLOSE_WRITE|IN_CLOSE_NOWRITE
Следующие опции могут также быть установлены в аргументе маски inotify_add_watch()
:
IN_DONT_FOLLOW
Не следуйте за символьными ссылками.IN_EXCL_UNLINK
Не генерируйте события для несвязанных файлов, которые раньше были в наблюдаемом каталоге.IN_MASK_ADD
Добавьте наблюдаемые события кумулятивно, если часы уже существуют.IN_ONESHOT
Автоматически удалите часы после одного события от него.IN_ONLYDIR
Только наблюдайте путь, если это - каталог.Значение, возвращенное inotify_add_watch()
дескриптор часов, связанный с объектом файловой системы, наблюдаемым в inotify
экземпляр, обозначенный fd
. Если за указанным объектом уже наблюдают, дескриптор для существующих часов возвращается.
while ((len = read(fd, buf, sizeof(buf))) > 0) {
i = 0;
while (i < len) {
struct inotify_event *ie = (struct inotify_event*) &buf[i];
/* ... */
i += sizeof(struct inotify_event) + ie->len;
}
}
Каждый успешный read()
от дескриптора файла, связанного с inotify
экземпляр возвращает один или несколько inotify_event
структуры со следующими полями.
int wd
Наблюдайте дескриптор инициированных часов.uint32_t mask
Маска событий, которые инициировали часы.uint32_t cookie
Уникальный cookie, связывающий связанные события.uint32_t len
Размер поля имени.char name[]
Дополнительное завершенное пустым указателем название файла, который инициировал событие в наблюдаемом каталоге.В дополнение к битам, соответствующим типам событий, передал inotify_add_watch()
, полю маски можно было установить следующие биты состояния:
IN_IGNORED
Часы были удалены (через inotify_rm_watch()
, путь, несвязанный и т.д.).IN_ISDIR
Событие инициировано каталогом.IN_Q_OVERFLOW
Очередь событий переполнена. Кроме того, wd установлен на-1.IN_UNMOUNT
Файловая система, содержащая наблюдаемый путь, была размонтирована.Длина каждого inotify_event
структура sizeof(inotify_event) + len
из-за переменной длины name
поле.
До версии 2.6.21 ядра, если буфер передал read()
является слишком маленьким, чтобы провести следующее мероприятие, читать (), возвратился бы 0. С тех пор 2.6.21, read()
сбои и errno
установлен на EINVAL
.
Я не думаю, что возможно получить сигнал на изменении файла. Однако inotify
, как показано на его странице Wikipedia, должен позволить Вам писать программу, которая получает события, когда файл изменяется.
Этот сайт имеет хорошую запись о inotify
. Это также имеет образец, который следит за развитием событий в текущем каталоге.
dnotify
интерфейс является самым близким механизмом пространства пользователя в Linux, который соответствует требованиям операции в секунду. Так как это удерживается от использования в пользуinotify
, ответ касается обоих. – Thomas Nyman 30.09.2016, 22:58