Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I am a relative Linux novice. I am trying to learn how to use at so that I can schedule tasks to begin at a later time, without using sleep. I have been looking at this previous question for help.

My question is, in the following sample bash script that I have created, why is "Running" never -- as far as I can tell -- printed to the standard output (i.e., my bash console)?

#!/bin/bash

echo "Started"

at now + 1 minutes <<EOF
echo "Running"
EOF

echo "Finished"

The only output I see is, for example:

Started
warning: commands will be executed using /bin/sh
job 3 at Fri Jul 12 17:31:00 2013
Finished

Is the answer to my question found in the warning? If so, how does /bin/sh differ from the standard output?

share|improve this question

3 Answers 3

up vote 10 down vote accepted

Because at does not execute commands in the context of your logged in user session. The idea is that you can schedule a command to run at an arbitrary time, then log out and the system will take care of running the command at the specified time.

Note that the manual page for at(1) specifically says (my emphasis):

The user will be mailed standard error and standard output from his commands, if any. Mail will be sent using the command /usr/sbin/sendmail.

So you should be checking your local mail spool or, failing that, the local system mail logs. /var/spool/mail/$USER is probably a good place to start.

Also note that the "Started" and "Finished" originate from the outer script and in and of themselves have nothing to do with at at all. You could take out them or the at invocation and you'll get essentially the same result.

share|improve this answer

As @MichaelKjörling has explained it any output that's produced by your at job will be captured and sent to you via email. If you don't have a running MTA - Mail Transfer Agent on your box then the email may be in limbo and you'll not know that at is even attempting to do this.

A MTA, is a program such as sendmail or postfix that can "deliver" email to an appropriate destination. In this case it's going to deliver it to a mail queue (a file under the directory /var/spool/mail) on your local system. Each user on the system can have a queue in this directory.

On my Fedora system if I start up sendmail then local mail delivery can occur. I typically have it off though.

$ sudo service start sendmail

Now we can see that my mail queue for my user account saml is empty:

$ ll /var/spool/mail/|grep saml
-rw-rw----. 1 saml mail       0 Jul 12 19:33 saml

So now we run the at job:

$ at now + 1 minutes <<EOF
echo "Running"
EOF
job 96 at Fri Jul 12 19:38:00 2013

We can see that the job is waiting to run with atq:

$ atq
96  Fri Jul 12 19:38:00 2013 a saml

Running it again after a couple of minutes we can see that the at job is complete:

$ atq
$

Incidentally, with my MTA running I now get this message in my terminal:

You have new mail in /var/spool/mail/saml

So let's check:

$ ll /var/spool/mail/|grep saml
-rw-rw----. 1 saml mail     651 Jul 12 19:38 saml

Yup we've got mail, so let's check it out using mutt:

$ mutt -f /var/spool/mail/saml

We have this in our mail queue's "inbox":

     ss of mutt's inbox

Let's check out this email:

     ss of mutt's msg

And it worked.

share|improve this answer
    
+1 for Mutt! :) –  Michael Kjörling Jul 13 '13 at 10:08
    
@MichaelKjörling - mutt rulz 8-) –  slm Jul 13 '13 at 12:13

The above answers are the standard/"right" way to do it.

Another approach that's simpler from a more "end user" point of view is to have any scheduled or background task write it's output to a "log" file. The file can be anywhere on your system, but if the task is running as root (from cron, etc.), then somewhere under /var/log is a good place to put it.

I created the /var/log/maint directory and made it readable by everybody and I have a readable file under that called "backup" where I log the output from my backup scripts.

I made my own directory so my files don't get mixed in with things generated by the system.

To put stuff there (in bash):

BACKUP="/var/log/maint/backup"
echo "my message" >> "${BACKUP}"

The >> causes the messages to be appended to the file instead of overwriting it each time.

If my script has a lot of output, I use a script or function for output so everything gets done the same. Below is my current (overkill version): (the VERBOSE stuff is there for when I'm running the script from a terminal and want to see what's going on for debugging purposes.)

#!/bin/bash
## backup_logger
## backup system logging module
## Copyleft 01/20/2013 JPmicrosystems
## Usage is ${SCRIPT_NAME} [-v] [<caller> <log message text>]
## If present, -v says log to console as well as to the log file
## <caller> is the name of the calling script
## If <caller> <log message text> is not present, write a blank line to the log

## Must be placed in path, like ~/bin
## If log is owned by root or another user, then this must run as root ...
## If not, it just aborts

##source "/home/bigbird/bin/bash_trace"  ## debug
SCRIPT_NAME="$(basename $0)"
USAGE="Usage is ${SCRIPT_NAME} [-v] [<caller> <log message text>]"
SYSLOGDIR='/var/log/maint'
SYSLOGFILE="${SYSLOGDIR}/backup.log"

LOGGING=1
VERBOSE=0
if [ "${1}" == "-v" ]
then
  VERBOSE=1
  shift
fi

##LOGGING=0  ## debug
##VERBOSE=1  ## debug

## Only zero or two parameters allowed - <caller> <log message text>
RC=0
if [ "$#" -eq 1 ] || [ "$#" -gt 2 ]
then
  echo "${USAGE}"
  RC=1
else
  if [ ! -w "${SYSLOGFILE}" ]
  then
    touch "${SYSLOGFILE}"
    if [ $? -ne 0 ]
    then
      echo -e "$(date) ${1} ${2}"
      echo "${SCRIPT_NAME} Can't write to log file [${SYSLOGFILE}]"
      RC=1
      exit ${RC}
    fi
  fi

  if [ -n "${1}" ]
  then
    (( LOGGING )) && echo -e "$(date) ${1} ${2}"  >> "${SYSLOGFILE}"
    (( VERBOSE )) && echo -e "$(date) ${1} ${2}"
  else
    (( LOGGING )) && echo "" >> "${SYSLOGFILE}"
    (( VERBOSE )) && echo ""
  fi
fi

exit $RC
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.