Inotify is a Linux feature that monitors file system operations, such as reading, writing, and creating. Inotify is responsive, easy to use, and much more efficient than the busy polling of cron tasks. Learn how to integrate inotify into your application and discover a group of command line tools that can be used to further automate system management.
System Management is like daily life. Just like brushing your teeth and eating vegetables, daily maintenance can keep your machine in good shape. You must regularly clear waste, such as temporary files or useless log files, and spend time entering forms, replying to calls, downloading updates, and monitoring processes. Fortunately, automated shell scripts, monitoring using Nagios and other tools, and task scheduling using common cron can reduce this burden.
But the strange thing is that none of these tools haveResponsiveness. Of course, you can schedule a frequently-run cron task to monitor the conditions, but such a busy round robin consumes a lot of resources and is uncertain-is not ideal. For example, if you must monitor several transfer protocol (FTP) receiving boxes for input data, you may needfind
Command to scan each target directory and list new contents. However, although this operation does not seem to have any harm, each call generates a new shell andfind
Command, which requires many system calls to open the directory, then scan the directory, and so on. This may cause too frequent or a large number of polling tasks (worse, busy polling is not always good. Imagine a file system browser, such as the Mac OS X Finder, to poll for a large amount of resources and their complexity when updating ).
What should the Administrator do? Fortunately, you can turn to trusted computers again.
Learn more about inotify
InotifyIs a Linux kernel feature that monitors the file system and sends event warnings to specialized applications in a timely manner, such as delete, read, write, and uninstall operations. You can also track the source and target details of an activity.
Using inotify is simple: create a file descriptor and append one or more monitors (oneMonitorIs a path and a group of events), and then useread()
Method To obtain event information from the descriptor.read()
It does not use up the entire cycle. It is blocked before the event occurs.
Better, because inotify works through traditional file descriptors, you can use the traditionalselect()
The system calls to passively monitor monitors and many other input sources. Two Methods: Blocking file descriptors and usingselect()
-Avoid busy polling.
Now, let's take a closer look at inotify, write some C code, and then look at a group of command line tools that you can build and use to attach commands and scripts to file system events. Inotify won't lose control in the middle, but it can runcat
Andwget
And strictly enforce it when necessary.
To use inotify, you must have a Linux machine with 2.6.13 or a kernel update (earlier Linux kernel versions use a lower-level File MonitorDnotify). If you do not know the kernel version, go to shell and enteruname -a
:
% uname -aLinux ubuntu-desktop 2.6.24-19-generic #1 SMP ... i686 GNU/Linux |
If the listed kernel version is no less than 2.6.13, your system supports inotify. You can also check the/usr/include/sys/inotify. h file of the machine. If it exists, your kernel supports inotify.
Note:FreeBSD and Mac OS X provide an inotify-likeKqueue. Input on FreeBSD Machineman 2 kqueue
Obtain more information.
This article is based on Ubuntu Desktop version 8.04.1 (that isHard), Which runs on Parallels Desktop version 10.5 of Mac OS X version 3.0 leopard.
Inotify C API
Inotify provides three system calls that can be used to build a variety of file system monitors:
inotify_init()
Create an inotify sub-system instance in the kernel. If it succeeds, a file descriptor is returned. If it fails,-1 is returned. Like other system calls, ifinotify_init()
Failed. Please checkerrno
To obtain diagnostic information.
- As the name suggests,
inotify_add_watch()
Used to add a monitor. Each monitor must provide a path name and a list of related events (each event is specified by a constant, such as in_modify ). To monitor multiple events, you only need to use logical operators between events.Or-Pipeline line in C Language (|
) Operator. Ifinotify_add_watch()
If the call succeeds, a unique identifier is returned for the registered monitor. Otherwise,-1 is returned. Use this identifier to change or delete related monitors.
inotify_rm_watch()
Delete a monitor.
In additionread()
Andclose()
System Call. If the descriptor is composedinotify_init()
Generate, callread()
Wait for warning. Assuming there is a typical file descriptor, the application will block the receipt of events, which are represented as data in the stream. Theinotify_init()
Generate commonclose()
Delete all activity monitors and release all memory associated with inotify instances (a typical reference count warning is also used here. All file descriptors associated with the instance must be disabled before the memory consumed by the monitor and inotify is released ).
This powerful tool provides three application programming interfaces (APIS) for calling, and a simple and familiar example of "all content is a file ". Now let's look at the sample application.
Sample Application: event monitoring
Listing 1 is a short C program that monitors the directories of two events: File Creation and deletion.
Listing 1. A simple inotify application that monitors directories for creating, deleting, and modifying events
#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <sys/types.h>#include <sys/inotify.h>#define EVENT_SIZE ( sizeof (struct inotify_event) )#define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )int main( int argc, char **argv ) { int length, i = 0; int fd; int wd; char buffer[BUF_LEN]; fd = inotify_init(); if ( fd < 0 ) { perror( "inotify_init" ); } wd = inotify_add_watch( fd, "/home/strike", IN_MODIFY | IN_CREATE | IN_DELETE ); length = read( fd, buffer, BUF_LEN ); if ( length < 0 ) { perror( "read" ); } while ( i < length ) { struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ]; if ( event->len ) { if ( event->mask & IN_CREATE ) { if ( event->mask & IN_ISDIR ) { printf( "The directory %s was created./n", event->name ); } else { printf( "The file %s was created./n", event->name ); } } else if ( event->mask & IN_DELETE ) { if ( event->mask & IN_ISDIR ) { printf( "The directory %s was deleted./n", event->name ); } else { printf( "The file %s was deleted./n", event->name ); } } else if ( event->mask & IN_MODIFY ) { if ( event->mask & IN_ISDIR ) { printf( "The directory %s was modified./n", event->name ); } else { printf( "The file %s was modified./n", event->name ); } } } i += EVENT_SIZE + event->len; } ( void ) inotify_rm_watch( fd, wd ); ( void ) close( fd ); exit( 0 );} |
This application usesfd = inotify_init();
Create an inotify instance and add a monitor to Monitor modifications, new files, and corrupted files in/home/strike (wd = inotify_add_watch(...)
).read()
The method is blocked until one or more warnings arrive. Warning details-each file and each event-are sent in the form of a byte stream; therefore, the loop in the application replaces byte flow with a series of event structures.
In the/usr/include/sys/inotify. H. file, you can find the definition of the event structure, which is a C structure, as shown in Listing 2.
List 2. Definitions of event Structures
struct inotify_event { int wd; /* The watch descriptor */ uint32_t mask; /* Watch mask */ uint32_t cookie;/* A cookie to tie two events together */ uint32_t len;/* The length of the filename found in the name field */ char name __flexarr;/* The name of the file, padding to the end with NULs */} |
wd
A field is a monitor associated with an event. If each inotify has more than one instance, you can use this field to determine how to continue the subsequent processing.mask
A field consists of several parts, indicating what happened. Test each part separately.
You can usecookie
Bind two events together. Inotify generates two moving events-targeting the source and target respectively-only when you monitor the source and target directories.cookie
Bind them together. To monitor a mobile operation, you must specifyIN_MOVED_FROM
OrIN_MOVED_TO
, Or use a shortIN_MOVE
It can monitor two operations. UseIN_MOVED_FROM
AndIN_MOVED_TO
To test the event type.
Finally,name
Andlen
Length of the file name (but not the path) and the name of the affected file.
Build sample application code
To build the code, change the directory/home/strike to your home directory, save the code to a file, and then call the C compiler-GCC in most Linux systems. Then, run the executable file, as shown in listing 3.
Listing 3. Run the executable file
% cc -o watcher watcher.c % ./watcher |
When the monitor program is running, open the second terminal window and usetouch
,cat
Andrm
To change the content of the main directory, as shown in Listing 4. After that, restart your new application.
Listing 4. Using touch, cat, and RM
% cd $HOME% touch a b cThe file a was created.The file b was created.The file c was created.% ./watcher & % rm a b cThe file a was deleted.The file b was deleted.The file c was deleted.% ./watcher & % touch a b cThe file a was created.The file b was created.The file c was created.% ./watcher & % cat /etc/passwd >> aThe file a was modified.% ./watcher & % mkdir dThe directory d was created. |
Try other available monitoring tags. To capture changes to permissions, SetIN_ATTRIB
Add to mask.
Tips for using inotify
You can also useselect()
,pselect()
,poll()
Andepoll()
To avoid blocking. It is useful if you want to use monitoring as part of the main event processing loop of a graphic application, or as part of the daemon that monitors other input connections. Add the inotify descriptor to this set of descriptors for concurrent monitoring. Listing 5 showsselect()
.
Listing 5. Standard Form of select ()
int return_value;fd_set descriptors;struct timeval time_to_wait;FD_ZERO ( &descriptors );FD_SET( ..., &descriptors );FD_SET ( fd, &descriptors );...time_to_wait.tv_sec = 3;time.to_waittv_usec = 0;return_value = select ( fd + 1, &descriptors, NULL, NULL, &time_to_wait);if ( return_value < 0 ) {/* Error */}else if ( ! return_value ) {/* Timeout */}else if ( FD_ISSET ( fd, &descriptors ) ) {/* Process the inotify events */...}else if ... |
select()
Method intime_to_wait
Pause the program. However, if any file descriptor of this group of descriptors is active during this delay, the execution program will be resumed immediately. Otherwise, the call times out, allowing the application to execute other processes, such as responding to mouse or Keyboard Events in the graphical user interface (GUI) tool.
The following are other tips for using inotify:
- If a file or directory under monitoring is deleted, ITS Monitor is also automatically deleted (after the deletion event is triggered ).
- If you monitor files or directories on an unmounted file system, the monitor receives an unmount event before deleting all affected monitors.
- Set
IN_ONESHOT
Add the flag to the monitor tag and set a one-time warning. The warning will be deleted after it is sent.
- To modify an event, you must provide the same path name and different tags. The new monitor replaces the old monitor.
- Considering its practicality, it is impossible to exhaust the monitor of any inotify instance. However, you may exhaust the space of the event queue, depending on the frequency of processing the event. Queue overflow may cause
IN_Q_OVERFLOW
Event.
close()
Method To destroy inotify instances and all associated monitors, and clear all wait events in the queue.