Check Whether Standard Input Is a Terminal with tty
A cron job behaves oddly because there is no terminal on its standard input, and tty is the command that tells you so. It either prints the terminal device or, in quiet mode, returns a status a shell can test. This guide uses GNU tty from coreutils 9.4, installed here as package version 9.4-3ubuntu6.3.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes. You need a shell and the coreutils package. No elevated privileges are needed, and this guide changes no files, services or terminal settings.
1. Confirm the installed command
Check the binary and its version before relying on a script or a copied example. These are ordinary read-only commands:
$ command -v tty
/usr/bin/tty
$ tty --version
tty (GNU coreutils) 9.4
...
$ dpkg-query -W -f='\${Package} \${Version}\n' coreutils
coreutils 9.4-3ubuntu6.3
The local manual describes tty as printing the file name of the terminal connected to standard input. It is not a general test of whether a graphical terminal application is open, and it does not inspect standard output.
Checkpoint
The command you are about to run is GNU coreutils tty, not a shell alias or a different utility earlier in your PATH.
2. Print the terminal device
Run tty at a normal interactive shell prompt:
$ tty
/dev/pts/1
Your number will probably differ. A path such as /dev/pts/1 identifies the pseudo-terminal attached to the shell. A hardware console may produce a path such as /dev/tty1. Treat the output as host-specific rather than something to hard-code.
This is useful when a script needs to show where its input is coming from, or when you are working out why an interactive program behaves differently from a scheduled or redirected invocation. tty only prints a line when standard input is a terminal, and its exit status matters just as much, so do not parse the device path when a plain yes-or-no test will do.
3. Test terminal input without printing
Use -s, also available as --silent and --quiet, when the caller needs only a status:
$ if tty --silent; then
> echo 'standard input is a terminal'
> else
> echo 'standard input is not a terminal'
> fi
standard input is a terminal
In this mode tty prints nothing. Exit status 0 means standard input is connected to a terminal; non-zero means it is not. Above, the shell's if consumes that status and prints its own message.
For a compact guard, use the same test before an interactive action:
if ! tty -s; then
printf '%s\n' 'This command needs an interactive terminal.' >&2
exit 1
fi
printf '%s\n' 'Interactive input is available.'
This test does not grant access to a terminal and does not convert redirected input into interactive input. It only reports the state of standard input at the moment it runs.
Checkpoint
Use tty -s in conditions. Use plain tty only when you actually need the device name.
4. See the difference when input is redirected
A pipe gives the next command the pipe as standard input, so tty should report that there is no terminal:
$ printf '%s\n' 'input from a pipe' | tty
not a tty
$ printf 'tty exit status: %s\n' "\${PIPESTATUS[1]}"
tty exit status: 1
The wording not a tty is diagnostic output from GNU tty. The non-zero status is the stable result a shell condition should use. PIPESTATUS is a Bash array, so do not copy that status check unchanged into a shell that does not provide it.
For a portable, direct check in a script, keep the command outside a pipeline:
if tty -s </path/to/input.txt; then
echo 'unexpected terminal input'
else
echo 'input is redirected or otherwise not a terminal'
fi
Replace /path/to/input.txt with a real readable file. This changes no data, it just demonstrates that shell redirection decides what tty sees as standard input.
5. Avoid the common script traps
- Do not test by checking whether tty printed a path. That breaks when output is redirected and needlessly mixes presentation with control flow. Prefer
tty -sand its exit status. - Do not assume a terminal is attached because output is visible. A command can read from a file while still writing messages to a terminal, or have both input and output redirected. This guide concerns standard input only.
- Do not add sudo. Asking about the current process's input is unprivileged, and elevated privileges will never turn a pipe, file or closed descriptor into a terminal.
- Do not treat a missing terminal in automation as an error. A job launched by cron, a service manager or a pipeline normally has no terminal on standard input. That is expected. If an interactive prompt is genuinely required, arrange the input and terminal allocation in the system that launches the job, then test that launcher separately.
6. Understand the available options
The installed command has a deliberately small interface:
-s,--silent,--quietsuppress the device-name output and leave the result in the exit status.--helpprints the usage summary and exits.--versionprints version information and exits.
There is no option to select a different file descriptor, configure a terminal, or force success. If a program needs to test another descriptor, use the shell's redirection or the programming interface appropriate to that program. Do not invent a tty option for the job.
Done means
ttyreports the terminal device connected to standard input when run interactively.tty -sproduces no output and returns success only when standard input is a terminal.- You tested the redirected-input case and understand its non-zero status.
- Your script checks the exit status instead of parsing host-specific device names or messages.
- No elevated privilege or persistent configuration change was needed.