The at command has a strange behaviour, and I can't find why.

Story - In 3 days, I'll need to send emails at specific times to make a surprise to someone. I won't be able to monitor if everything is running correctly, because I'll be in a plane for ~20 hours. Everything shall run perfectly. :-)

Script - I am using the at command to queue jobs for later execution. I created a bunch of files (one per mail), with the following format:

Content of mail1.txt (example)

This is a subject
This is a message...
... on several lines

This is my script:


function sendit {
        FROM_MAIL="[email protected]"
        RCPT_MAIL="[email protected]"

        SUBJECT=$(head -n  1 $1)
        MESSAGE=$(tail -n +2 $1)

        echo -e "$MESSAGE" |mail -s "$SUBJECT" -r $FROM_MAIL $RCPT_MAIL

# Note, time is EDT, it correspond to the date of my server
sendit mail1.txt|at 02:37 May 03
sendit mail2.txt|at 02:38 May 03
sendit mail3.txt|at 03:13 May 03

I then run my script:

$ bash script.sh
warning: commands will be executed using /bin/sh
job 35 at Tue May  3 02:37:00 2016
warning: commands will be executed using /bin/sh
job 36 at Tue May  3 02:38:00 2016
warning: commands will be executed using /bin/sh
job 37 at Tue May  3 03:13:00 2016

Everything seems perfect, however, when I check my mails a few minutes after, I saw that some of the mails have been sent... (it seems random)

Any idea?

  • If you write your mail1.txt so that it has a header block and a body block separated by a blank line, you can use mail's -t option to get Subject:, From:, To:, etc from the headers in the message, and you wouldn't have to use head or tail to extract the subject and the body from the file. See man mail and search for -t.
    – cas
    May 3, 2016 at 23:18

2 Answers 2


The | sends the stdout of the left process to the right command. Your sendit function actually sends the mail, but doesn't produce much output on stdout (I actually don't remember what the output of mail is), so the input to at isn't a command to send the mail.

Consider that as a user, you would typically have used at like this:

at 02:37 May 03        # This will read commands from stdin until Ctrl/D
sendit mail1.txt

You could have also piped the sendit command to at programmatically:

echo 'sendit mail1.txt' | at 02:37 May 03
  • Running atq will show (or would have shown) that the jobs are still queued. May 3, 2016 at 7:44
  • Thank you, could you give me the commands that I should have written?
    – DontMessIt
    May 3, 2016 at 7:50

I think you mean echo sendit mail1.txt|at 02:37 May 03.

  • Yes, the user probably did intend that. Can you explain why? May 3, 2016 at 9:21
  • I can't upvote your question as I don't have enough rep, but I would. The accepted answer is a bit more detailed, this is the reason I accepted it.
    – DontMessIt
    May 3, 2016 at 10:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .