Skip to content
Snippets Groups Projects
Commit 43704634 authored by ballen4705's avatar ballen4705
Browse files

Added feature to send email warnings when errors detected by smartd. But this...

Added feature to send email warnings when errors detected by smartd.  But this is NOT YET TESTED!  Be cautious in using this for now.


git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@246 4ea69e1a-61f1-4043-bf83-b5c94c648137
parent fbf5b747
Branches
No related tags found
No related merge requests found
CHANGELOG for smartmontools
$Id: CHANGELOG,v 1.43 2002/11/11 10:55:42 ballen4705 Exp $
$Id: CHANGELOG,v 1.44 2002/11/12 21:16:25 ballen4705 Exp $
Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
......@@ -25,7 +25,11 @@ NOTES FOR FUTURE RELEASES: see TODO file.
CURRENT RELEASE (see VERSION file in this directory):
smartmontools-5.0.37
Added a new smartd configuration file Directive: -M ADDRESS.
This sends a single warning email to ADDRESS for failures or
errors detected with the -c, -L, -l, or -f Directives.
smartmontools-5.0.38
Modified perror() statements in atacmds.c so that printout for SMART
commands errors is properly suppressed or queued depending upon users
......
38
39
\# Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
\#
\# $Id: smartd.8,v 1.25 2002/11/11 12:43:53 ballen4705 Exp $
\# $Id: smartd.8,v 1.26 2002/11/12 21:16:25 ballen4705 Exp $
\#
\# This program is free software; you can redistribute it and/or modify it
\# under the terms of the GNU General Public License as published by the Free
......@@ -16,7 +16,7 @@
\# Research Center), Jack Baskin School of Engineering, University of
\# California, Santa Cruz. http://ssrc.soe.ucsc.edu/
\#
.TH SMARTD 8 "$Date: 2002/11/11 12:43:53 $" "smartmontools-5.0"
.TH SMARTD 8 "$Date: 2002/11/12 21:16:25 $" "smartmontools-5.0"
.SH NAME
smartd \- S.M.A.R.T. Daemon
.SH SYNOPSIS
......@@ -250,9 +250,7 @@ name on any line of the
configuration file. Note that
.B these are NOT command-line options for
.B smartd.
The command-line options for
.B smartd
are listed above. The Directives below may appear in any order,
The Directives below may appear in any order,
following the device name. For the moment, apart from the '\-S'
Directive, these Directives only apply to ATA disks.
.B For ATA disks, if
......@@ -332,6 +330,30 @@ life period."
.B smartctl \-v
command-line option.]
.TP
.B \-M <ADD>
Mail: Send a warning email to the email address <ADD> if the '\-c', '\-l', '\-L', or '\-f'
Directives detect a failure or a new error. This Directive only
works in conjunction with these other Directives (or with the equivalent '\-a'
Directive). To prevent your email in-box from getting filled up
with warning messages, only a single warning will be sent for each of
the enabled test types, '\-c', '\-l', '\-L', or '\-f', even if more
than one failure or error is detected.
The email is sent using the system
.B mail
command. In order that
.B smartd
find the mail command (normally /bin/mail) the
.B mail
command must be in the path of the
shell or environment from which
.B smartd
was started.
If you want to send email to more than one user, you can use the form
.B user1@add1,user2@add2,...,userN@addN
with no spaces for <ADD>.
.TP
.B \-p
Prefail: Report anytime that a Prefail Attribute has changed
its value since the last check, 30 minutes ago. [Please see the
......@@ -518,4 +540,4 @@ Please let us know if there is an on\-line source for this document.
.SH
CVS ID OF THIS PAGE:
$Id: smartd.8,v 1.25 2002/11/11 12:43:53 ballen4705 Exp $
$Id: smartd.8,v 1.26 2002/11/12 21:16:25 ballen4705 Exp $
......@@ -45,7 +45,7 @@
// CVS ID strings
extern const char *CVSid1, *CVSid2;
const char *CVSid6="$Id: smartd.c,v 1.55 2002/11/11 10:50:08 ballen4705 Exp $"
const char *CVSid6="$Id: smartd.c,v 1.56 2002/11/12 21:16:25 ballen4705 Exp $"
CVSID1 CVSID2 CVSID3 CVSID4 CVSID7;
// global variable used for control of printing, passing arguments, etc.
......@@ -87,8 +87,9 @@ void printout(int priority,char *fmt, ...){
return;
}
void printandmail(mailinfo *mail, int priority, char *fmt, ...){
// If address is null, this just prints a warning message. But if
// address is non-null then send and log a warning email.
void printandmail(char *address, mailinfo *mail, int priority, char *fmt, ...){
int pid;
va_list ap;
......@@ -99,7 +100,7 @@ void printandmail(mailinfo *mail, int priority, char *fmt, ...){
va_end(ap);
// See if user wants us to send mail
if (mail==NULL)
if (!address)
return;
// Have we already sent a message about this?
......@@ -127,7 +128,11 @@ void printandmail(mailinfo *mail, int priority, char *fmt, ...){
}
else {
// We are the child process, send email
char command[1024], message[256];
char command[1024], message[256], hostname[256];
if (gethostname(hostname, 256)){
sprintf(hostname,"hostname: unknown");
}
// print warning string into message
va_start(ap, fmt);
......@@ -135,7 +140,8 @@ void printandmail(mailinfo *mail, int priority, char *fmt, ...){
va_end(ap);
// now construct a command to send this as EMAIL, and issue it.
snprintf(command,1024, "echo '%s' | mail -s 'smartd warning: S.M.A.R.T. errors' %s > /dev/null 2> /dev/null", message, mail->address);
snprintf(command,1024, "echo '%s' | mail -s '%s: smartd detected SMART errors' %s > /dev/null 2> /dev/null",
message, hostname, address);
exit(system(command));
}
}
......@@ -235,6 +241,7 @@ void Directives() {
printout(LOG_INFO," -l Monitor SMART Error Log, report new errors\n");
printout(LOG_INFO," -L Monitor SMART Self-Test Log, report new errors\n");
printout(LOG_INFO," -f Monitor 'Usage' Attributes, report failures\n");
printout(LOG_INFO," -M ADD Send email warning to address ADD\n");
printout(LOG_INFO," -p Report changes in 'Prefailure' Attributes\n");
printout(LOG_INFO," -u Report changes in 'Usage' Attributes\n");
printout(LOG_INFO," -t Equivalent to -p and -u Directives\n");
......@@ -594,7 +601,7 @@ int ataCheckDevice(atadevices_t *drive){
if (status==-1)
printout(LOG_INFO,"Device: %s, not capable of SMART self-check\n",name);
else if (status==1)
printout(LOG_CRIT,"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!\n",name);
printandmail(cfg->address, cfg->maildata , LOG_CRIT, "Device: %s, FAILED SMART self-check. BACK UP DATA NOW!\n", name);
}
// Check everything that depends upon SMART Data (eg, Attribute values)
......@@ -625,7 +632,7 @@ int ataCheckDevice(atadevices_t *drive){
while (*loc && *loc==' ') loc++;
// warning message
printout(LOG_CRIT,"Device: %s, Failed SMART usage Attribute: %s.\n", name, loc);
printandmail(cfg->address, cfg->maildata+1, LOG_CRIT, "Device: %s, Failed SMART usage Attribute: %s.\n", name, loc);
}
}
......@@ -673,7 +680,7 @@ int ataCheckDevice(atadevices_t *drive){
unsigned char old=cfg->selflogcount;
int new=selftesterrorcount(fd, name);
if (new>old){
printout(LOG_CRIT,"Device: %s, Self-Test Log error count increased from %d to %d\n",
printandmail(cfg->address, cfg->maildata+2, LOG_CRIT, "Device: %s, Self-Test Log error count increased from %d to %d\n",
name, (int)old, new);
}
if (new>=0)
......@@ -687,7 +694,7 @@ int ataCheckDevice(atadevices_t *drive){
int old=cfg->ataerrorcount;
int new=ataerrorcount(fd, name);
if (new>old){
printout(LOG_CRIT,"Device: %s, ATA error count increased from %d to %d\n",
printandmail(cfg->address, cfg->maildata+3, LOG_CRIT, "Device: %s, ATA error count increased from %d to %d\n",
name, old, new);
}
// this last line is probably not needed, count always increases
......@@ -841,6 +848,22 @@ int parsetoken(char *token,cfgfile *cfg){
cfg->selftest=1;
cfg->errorlog=1;
break;
case 'M':
// send email to address that follows
arg=strtok(NULL,delim);
if (!arg) {
printout(LOG_CRIT,"Drive %s Directive: %s at line %d of file %s needs email address.\n",
name,token,lineno,CONFIGFILE);
Directives();
exit(1);
}
if (!(cfg->address=strdup(arg))){
printout(LOG_CRIT,"Drive %s Directive: %s at line %d of file %s: no free memory for address %s.\n",
name,token,lineno,CONFIGFILE,arg);
Directives();
exit(1);
}
break;
case 'i': // ignore
case 'I': // ignore
case 'C': // period (time interval) for checking
......
\# Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
\#
\# $Id: smartd.conf.5,v 1.3 2002/11/11 12:43:53 ballen4705 Exp $
\# $Id: smartd.conf.5,v 1.4 2002/11/12 21:16:25 ballen4705 Exp $
\#
\# This program is free software; you can redistribute it and/or modify it
\# under the terms of the GNU General Public License as published by the Free
......@@ -16,7 +16,7 @@
\# Research Center), Jack Baskin School of Engineering, University of
\# California, Santa Cruz. http://ssrc.soe.ucsc.edu/
\#
.TH SMARTD.CONF 5 "$Date: 2002/11/11 12:43:53 $" "smartmontools-5.0"
.TH SMARTD.CONF 5 "$Date: 2002/11/12 21:16:25 $" "smartmontools-5.0"
.SH NAME
/etc/smartd.conf \- S.M.A.R.T. Monitoring Daemon Configuration File
......@@ -147,9 +147,7 @@ name on any line of the
configuration file. Note that
.B these are NOT command-line options for
.B smartd.
The command-line options for
.B smartd
are listed above. The Directives below may appear in any order,
The Directives below may appear in any order,
following the device name. For the moment, apart from the '\-S'
Directive, these Directives only apply to ATA disks.
.B For ATA disks, if
......@@ -229,6 +227,30 @@ life period."
.B smartctl \-v
command-line option.]
.TP
.B \-M <ADD>
Mail: Send a warning email to the email address <ADD> if the '\-c', '\-l', '\-L', or '\-f'
Directives detect a failure or a new error. This Directive only
works in conjunction with these other Directives (or with the equivalent '\-a'
Directive). To prevent your email in-box from getting filled up
with warning messages, only a single warning will be sent for each of
the enabled test types, '\-c', '\-l', '\-L', or '\-f', even if more
than one failure or error is detected.
The email is sent using the system
.B mail
command. In order that
.B smartd
find the mail command (normally /bin/mail) the
.B mail
command must be in the path of the
shell or environment from which
.B smartd
was started.
If you want to send email to more than one user, you can use the form
.B user1@add1,user2@add2,...,userN@addN
with no spaces for <ADD>.
.TP
.B \-p
Prefail: Report anytime that a Prefail Attribute has changed
its value since the last check, 30 minutes ago. [Please see the
......@@ -345,4 +367,4 @@ SEE ALSO:
.SH
CVS ID OF THIS PAGE:
$Id: smartd.conf.5,v 1.3 2002/11/11 12:43:53 ballen4705 Exp $
$Id: smartd.conf.5,v 1.4 2002/11/12 21:16:25 ballen4705 Exp $
......@@ -45,7 +45,7 @@
// CVS ID strings
extern const char *CVSid1, *CVSid2;
const char *CVSid6="$Id: smartd.cpp,v 1.55 2002/11/11 10:50:08 ballen4705 Exp $"
const char *CVSid6="$Id: smartd.cpp,v 1.56 2002/11/12 21:16:25 ballen4705 Exp $"
CVSID1 CVSID2 CVSID3 CVSID4 CVSID7;
// global variable used for control of printing, passing arguments, etc.
......@@ -87,8 +87,9 @@ void printout(int priority,char *fmt, ...){
return;
}
void printandmail(mailinfo *mail, int priority, char *fmt, ...){
// If address is null, this just prints a warning message. But if
// address is non-null then send and log a warning email.
void printandmail(char *address, mailinfo *mail, int priority, char *fmt, ...){
int pid;
va_list ap;
......@@ -99,7 +100,7 @@ void printandmail(mailinfo *mail, int priority, char *fmt, ...){
va_end(ap);
// See if user wants us to send mail
if (mail==NULL)
if (!address)
return;
// Have we already sent a message about this?
......@@ -127,7 +128,11 @@ void printandmail(mailinfo *mail, int priority, char *fmt, ...){
}
else {
// We are the child process, send email
char command[1024], message[256];
char command[1024], message[256], hostname[256];
if (gethostname(hostname, 256)){
sprintf(hostname,"hostname: unknown");
}
// print warning string into message
va_start(ap, fmt);
......@@ -135,7 +140,8 @@ void printandmail(mailinfo *mail, int priority, char *fmt, ...){
va_end(ap);
// now construct a command to send this as EMAIL, and issue it.
snprintf(command,1024, "echo '%s' | mail -s 'smartd warning: S.M.A.R.T. errors' %s > /dev/null 2> /dev/null", message, mail->address);
snprintf(command,1024, "echo '%s' | mail -s '%s: smartd detected SMART errors' %s > /dev/null 2> /dev/null",
message, hostname, address);
exit(system(command));
}
}
......@@ -235,6 +241,7 @@ void Directives() {
printout(LOG_INFO," -l Monitor SMART Error Log, report new errors\n");
printout(LOG_INFO," -L Monitor SMART Self-Test Log, report new errors\n");
printout(LOG_INFO," -f Monitor 'Usage' Attributes, report failures\n");
printout(LOG_INFO," -M ADD Send email warning to address ADD\n");
printout(LOG_INFO," -p Report changes in 'Prefailure' Attributes\n");
printout(LOG_INFO," -u Report changes in 'Usage' Attributes\n");
printout(LOG_INFO," -t Equivalent to -p and -u Directives\n");
......@@ -594,7 +601,7 @@ int ataCheckDevice(atadevices_t *drive){
if (status==-1)
printout(LOG_INFO,"Device: %s, not capable of SMART self-check\n",name);
else if (status==1)
printout(LOG_CRIT,"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!\n",name);
printandmail(cfg->address, cfg->maildata , LOG_CRIT, "Device: %s, FAILED SMART self-check. BACK UP DATA NOW!\n", name);
}
// Check everything that depends upon SMART Data (eg, Attribute values)
......@@ -625,7 +632,7 @@ int ataCheckDevice(atadevices_t *drive){
while (*loc && *loc==' ') loc++;
// warning message
printout(LOG_CRIT,"Device: %s, Failed SMART usage Attribute: %s.\n", name, loc);
printandmail(cfg->address, cfg->maildata+1, LOG_CRIT, "Device: %s, Failed SMART usage Attribute: %s.\n", name, loc);
}
}
......@@ -673,7 +680,7 @@ int ataCheckDevice(atadevices_t *drive){
unsigned char old=cfg->selflogcount;
int new=selftesterrorcount(fd, name);
if (new>old){
printout(LOG_CRIT,"Device: %s, Self-Test Log error count increased from %d to %d\n",
printandmail(cfg->address, cfg->maildata+2, LOG_CRIT, "Device: %s, Self-Test Log error count increased from %d to %d\n",
name, (int)old, new);
}
if (new>=0)
......@@ -687,7 +694,7 @@ int ataCheckDevice(atadevices_t *drive){
int old=cfg->ataerrorcount;
int new=ataerrorcount(fd, name);
if (new>old){
printout(LOG_CRIT,"Device: %s, ATA error count increased from %d to %d\n",
printandmail(cfg->address, cfg->maildata+3, LOG_CRIT, "Device: %s, ATA error count increased from %d to %d\n",
name, old, new);
}
// this last line is probably not needed, count always increases
......@@ -841,6 +848,22 @@ int parsetoken(char *token,cfgfile *cfg){
cfg->selftest=1;
cfg->errorlog=1;
break;
case 'M':
// send email to address that follows
arg=strtok(NULL,delim);
if (!arg) {
printout(LOG_CRIT,"Drive %s Directive: %s at line %d of file %s needs email address.\n",
name,token,lineno,CONFIGFILE);
Directives();
exit(1);
}
if (!(cfg->address=strdup(arg))){
printout(LOG_CRIT,"Drive %s Directive: %s at line %d of file %s: no free memory for address %s.\n",
name,token,lineno,CONFIGFILE,arg);
Directives();
exit(1);
}
break;
case 'i': // ignore
case 'I': // ignore
case 'C': // period (time interval) for checking
......
......@@ -23,7 +23,7 @@
*/
#ifndef CVSID7
#define CVSID7 "$Id: smartd.h,v 1.19 2002/11/10 21:54:19 ballen4705 Exp $\n"
#define CVSID7 "$Id: smartd.h,v 1.20 2002/11/12 21:16:25 ballen4705 Exp $\n"
#endif
// Configuration file
......@@ -75,8 +75,6 @@ typedef struct mailinfo {
int logged;
// time last email was sent, as defined by man 2 time
time_t lastsent;
// address to send email to
char *address;
} mailinfo;
// Used to store a list of devices and options that were in the
......@@ -97,7 +95,9 @@ typedef struct configfile_s {
// Should we ignore missing capabilities/SMART errors
char permissive;
// mailing information for each of the previous error types
mailinfo *mailinfop[6];
mailinfo maildata[4];
// address to send email to
char *address;
// counts of ata and self-test errors. Perhaps ought to be in the
// atadevices_t structure.
unsigned char selflogcount;
......@@ -120,9 +120,8 @@ typedef struct atadevices_s {
} atadevices_t;
// Declare our own printing function...
void printout(int priority,char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
// Declare our own printing functions...
void printout(int priority,char *fmt, ...) __attribute__ ((format(printf, 2, 3)));
void printandmail(char *address, mailinfo *mail, int priority, char *fmt, ...) __attribute__ ((format(printf, 4, 5)));
int ataCheckDevice(atadevices_t *drive);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment