3

I have several shell scripts (bash) which are started by cron. Every time a script is executed I get an email saying "stdin: is not a tty". Can someone please tell me how to fix this? All scripts run successfully but these mails are killing my email folder.

I use Debian Wheezy. "/root/.bashrc" is empty. Cron entries are like:

/bin/bash --login /root/script.sh > /dev/null

Even this script produces the error message:

#!/bin/bash
ls

Content of .profile:

# ~/.profile: executed by Bourne-compatible login shells.

if [ "$BASH" ]; then
  if [ -f ~/.bashrc ]; then
    . ~/.bashrc
  fi
fi

mesg n
5
  • It's something in your script (or in your .profile or .bash_profile since you're telling bash to read it). We can't help you unless you post the script content. If you want to diagnose what it might be, add set -x at the top of the script. Commented Jan 16, 2014 at 0:45
  • @Gilles: Thx. The scripts are quite long but even calling 'ls' produces the error. Commented Jan 16, 2014 at 1:03
  • stty and mesg are the typical culprits. You can run them with a 2>/dev/null to quiet them. Commented Jan 16, 2014 at 1:07
  • @MarkPlotnick: I have commented 'mesg n' out (whatever is does) and it works but this doesn't seems to be the right solution. If I write '2>/dev/null' instead of '>/dev/null' I don't get the "stdin:..." error message but instead the output of the ls command which I also don't want. Commented Jan 16, 2014 at 1:16
  • Sorry, I meant to say to put 2>/dev/null just on the line that does the mesg. Commented Jan 16, 2014 at 1:22

2 Answers 2

3

Something in your .bashrc is assuming that the shell is running on a terminal. That's perfectly fine: .bashrc is supposed to run only in interactive shells, and interactive shells are supposed to run only on terminals.

The problem is that you're systematically including .bashrc from .profile. That's wrong: you should only include .bashrc in interactive shells.

Change your .profile to

# Bash doesn't load its interactive initialization file if it's invoked as
# a login shell, so do it manually.
case $- in
  *i*) if [ -n "$BASH" ]; then . ~/.bashrc;; fi
esac

Move mesg n into .bashrc: it's a terminal-related command, not a session-related command.

If you have environment variable definitions in your .bashrc, move them to .profile. The .profile file is for things that are executed when your session starts, typically mainly environment variable definitions, used by any application that you'll run during the session. The .bashrc file is the configuration file for bash when running interactively, it typically contains terminal setup, alias definitions, shell options and completion settings, and other things related to the interactive use of the shell.

For background, see:

0
0

Another way to do this is to start your cron job in a detached screen:

0 0 * * * cd /path/to/my/job && screen -dmS any-job-name-you-want ./job.sh

This works because screen allocates a tty. I've had to do this before for example with expect scripts. It has the added bonus that you can screen -r any-job-name-you-want to view and even interact with a running cron job.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.