/* check_dircount.c check age of a file or directory, or all files in a directory for monitoring if logs are being updated by Doke Scott, doke at udel.edu, 5 Nov 2003 */ #define version "1.0" #include #include #include #include #include #include #include #define STATE_OK 0 #define STATE_WARNING 1 #define STATE_CRITICAL 2 #define STATE_UNKNOWN -1 char *crit_range = "900"; char *warn_range = "300"; int dir_mode = 0; int verbose = 0; char *program_name; time_t now; unsigned int best_age; char *best_pathname; void usage( int rc ) { fprintf( stderr, "Usage: %s [-vd] [-c range] [-w range] \n" " -c range critical if outside range, default 20000\n" " -w range critical if outside range, default 10000\n" " -d check best file in dir, for timestamped logs\n" " -v verbose\n" " range is 1000, 200:1000, 200:, :1000, inclusive\n" " version %s, by Doke Scott, doke at udel dot edu\n", program_name, version ); exit( rc ); } int in_range( int count, char *range ) { int l = 0, h = 0; if ( strchr( range, ':' ) ) { if ( sscanf( range, "%u:%u", &l, &h ) == 2 ) { //printf( "count %d, l %d, h %d\n", count, l, h ); if ( count < l || h < count ) return 0; return 1; } else if ( sscanf( range, ":%u", &h ) == 1 ) { //printf( "count %d, l %d, h %d\n", count, l, h ); if ( h < count ) return 0; return 1; } else if ( sscanf( range, "%u:", &l ) == 1 ) { //printf( "count %d, l %d, h %d\n", count, l, h ); if ( count < l ) return 0; return 1; } } else if ( sscanf( range, "%u", &h ) == 1 ) { //printf( "count %d, l %d, h %d\n", count, l, h ); if ( h < count ) return 0; return 1; } fprintf( stderr, "cannot parse range '%s'\n", range ); usage( -1 ); } // check age of one pathname check_age( char *pathname ) { struct stat statbuf; unsigned int age; if ( stat( pathname, &statbuf ) ) { fprintf( stderr, "can't stat pathname %s: %s\n", pathname, strerror( errno ) ); return STATE_UNKNOWN; } age = now - statbuf.st_mtime; if ( age < best_age ) { best_age = age; if ( pathname != best_pathname ) best_pathname = strdup( pathname ); // memory leak } if ( ! in_range( age, crit_range ) ) return STATE_CRITICAL; else if ( ! in_range( age, warn_range ) ) return STATE_WARNING; else return STATE_OK; } // Assume the directory contains multiple log files, possibly with the // time or date as part of the filename. We want to know if any of // them are being updated. So check each file and return the best // result we find. check_dir( char *dirname ) { DIR *dirp; struct dirent *de; char buf[1024]; int r; int warn = 0; int crit = 0; dirp = opendir( dirname ); if ( ! dirp ) { fprintf( stderr, "can't open directory %s: %s\n", dirname, strerror( errno ) ); return STATE_UNKNOWN; } while ( de = readdir( dirp ) ) { if ( ! strcmp( ".", de->d_name ) || ! strcmp( "..", de->d_name ) ) continue; sprintf( buf, "%s/%s", dirname, de->d_name ); r = check_age( buf ); if ( r == STATE_OK ) return STATE_OK; else if ( r == STATE_WARNING ) warn++; else if ( r == STATE_CRITICAL ) crit++; } closedir( dirp ); if ( warn ) return STATE_WARNING; else if ( crit ) return STATE_CRITICAL; else return STATE_UNKNOWN; // no files? } int main( int argc, char **argv ) { char *pathname; int c, rc; program_name = argv[0]; while ( ( c = getopt( argc, argv, "c:w:dvh" ) ) >= 0 ) { switch ( c ) { case 'c': crit_range = optarg; break; case 'w': warn_range = optarg; break; case 'd': dir_mode = 1; break; case 'v': verbose++; break; case 'h': usage( 0 ); break; default: usage( -1 ); break; } } if ( optind >= argc ) usage( -1 ); pathname = argv[ optind ]; time( &now ); best_age = now; best_pathname = pathname; if ( dir_mode ) rc = check_dir( pathname ); else rc = check_age( pathname ); if ( rc != STATE_UNKNOWN ) printf( "%s - %s %d s old\n", ( rc == STATE_OK ) ? "OK" : ( rc == STATE_WARNING ) ? "Warning" : "CRITICAL", best_pathname, best_age ); else printf( "UNKNOWN - can't get age of %s\n", best_pathname ); return rc; }