[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Script to email details not working in cron



Manikandan M wrote:
> I have written a small script to email (using ssmpt) some details, and
> scheduled it in crontab. The script is running as per time mentioned in the
> cron but ssmtp is not sending the mail. please find the details below.

A couple of details to provide background to understanding cron
scripts.  Cron scripts like most things on the system use /bin/sh and
not /bin/bash.  The /bin/sh is a mostly standard shell.  Not being
bash means that if you use bash'isms they will not work.  In the
crontab PATH="/usr/bin:/bin" and therefore any reference to comands
from your home won't be found.  Anyout output from your crontab will
be mailed to your account on that system.  These things can all be
configured.

> user@host ~ $ cat bin/email-script
> /home/user/bin/actual-script > ~/details-file
> ssmtp username@gmail.com < ~/details-file
> echo $? > ~/email-status

What do you see in ~/email-status after the crontab runs?

Is any output emailed to your account on the local system?  Is
anything stuck in the local mail queue?  Run "mailq" to see.  Do you
have an MTA (such as postfix or exim4) installed on your system?

  mailq

What is logged to /var/log/syslog when the crontask is run?

  less /var/log/syslog

If you don't have permission for viewing syslog as yourself on your
machine then add yourself to the adm group, log out, log back in again
so that the adm group gets added to your running account processes,
and look again.  It is security protected by default but you on your
own machine should be able to access it.

  id | grep --color adm

If you are doing this for the first time and adding 'adm' then you
might as well add 'staff' too.  That way you will have access to your
/usr/local directory tree as yourself too.  Might as well do both at
the same time for you on your own system.

More suggestions follow in a moment.

> The crontab entry is as below
> 0 9 * * * /home/user/email-script

Okay.  At 9am every day run /home/user/email-script.

> When i execute the script manually i'm getting the email from ssmtp. but
> when the script is executed using cron i'm not getting the email. I checked
> the status of the ssmtp and the status is 127.

The status of ssmtp when run manually is 127?  Or when run by cron?

> Please can anyone suggest what might be wrong in my setup.

Anytime you write a script always declare the interpreter on the first
line.  This is used by the system to invoke the right interpreter.  In
this case add #!/bin/sh to the first line of your script.  That
explicitly states things.  Otherwise the behavior depends upon your
system and various details not important to discuss here.

As a general suggestion I always use $HOME instead of ~ in scripts
like this as ~ is a ksh feature, now migrated to bash, now migrated to
/bin/sh (as implemented by dash) but isn't a Bourne shell feature.  I
didn't look now to see if it is in the POSIX spec (probably is) so
this is simply the guaranteed safe thing and perhaps is overly safe
these days but then again I am not usually getting hit with bashism
problems either.  :-)

Therefore your script would be changed to:

  #!/bin/sh
  /home/user/bin/actual-script > $HOME/details-file
  ssmtp username@gmail.com < $HOME/details-file
  echo $? > $HOME/email-status

Any output from the script will be emailed to your local account by
cron.  For me that is mostly convenient.  For others perhaps not so
convenient.  For debugging it is often better to redirect everything
to a log file.  Sometimes it makes sense to truncate and start a new
file every run.  Sometimes it makes sense to keep a running log by
appending to the end all of the time.  It is your choice.  I will
append here for this example.

Sometimes it is good to simply "echo print" specific details.

  #!/bin/sh
  exec >>$HOME/foo.cron.out 2>&1
  echo Beginning script
  /home/user/bin/actual-script > $HOME/details-file
  echo Actual script finished.
  ls -ldog $HOME/details-file
  ssmtp username@gmail.com < $HOME/details-file
  echo ssmtp exit code: $?

Sometimes it is good to trace all output using -x.

  #!/bin/sh
  exec >>$HOME/foo.cron.out 2>&1
  set -x
  /home/user/bin/actual-script > $HOME/details-file
  ls -ldog $HOME/details-file
  ssmtp username@gmail.com < $HOME/details-file
  echo ssmtp exit code: $?

I like to have statements listed in -x output using the ":" true
operator.  It does nothing but is a command and therefore the command
and arguments are listed in -x tracing output.  These are run but are
invisible when not using -x.  (Especially good for observing builtins
such as case statements.)

  #!/bin/sh
  exec >>$HOME/foo.cron.out 2>&1
  set -x
  : "DEBUG: Beginning actual-script"
  /home/user/bin/actual-script > $HOME/details-file
  ls -ldog $HOME/details-file
  ssmtp username@gmail.com < $HOME/details-file
  : "DEBUG: ssmtp exit code: $?"

If PATH is the issue then you can add the standard login paths to this
script.  (Add /usr/local/games:/usr/games too if you like.)

  #!/bin/sh
  exec >>$HOME/foo.cron.out 2>&1
  set -x
  PATH="/home/usernamehere/bin:/usr/local/bin:/usr/bin:/bin"
  : "DEBUG: Beginning actual-script"
  /home/user/bin/actual-script > $HOME/details-file
  ls -ldog $HOME/details-file
  ssmtp username@gmail.com < $HOME/details-file
  : "DEBUG: ssmtp exit code: $?"

These are ways to get visibility into your crontasks so that you can
debug whatever problem you are having.  I don't know what you are
actually experiencing but with visiblity you will be able to figure it
out.

Note that inside your crontab itself you can change your PATH and
SHELL and then the commands of the crontab will be executed using your
specified PATH and SHELL.  That is a vixie-cron extension not found in
other cron daemons on classic Unix systems so you might not find too
much documentation mentioning it.

It should go without saying that when debugging cron tasks that are
meant to run once a day at 9am using "0 9 * * *" that will only happen
once a day.  To debug set those to happen more often during debugging.
I often use every minute "* * * * *" when debugging.  Or I run every
hour and just update the minute to fire on the next minute manually
every time I want to trigger it "32 * * * *" and update 32 to be 37
for the next and then 42 and so forth if it is something that takes me
more than a minute to think through for the next debug test.

HTH,
Bob

Attachment: signature.asc
Description: Digital signature


Reply to: