I'm facing trouble with a system which I'm maintaining via SSH. When I test commands which require a TTY they work, probably because of the SSH session. Under some unclear circumstances there's no TTY available and commands like sudo fail due to

(sudo: sorry, you must have a tty to run sudo)

They succeed in the SSH shell which makes issues hard to track before they occur. Since this is a recurring issue, I'm looking for a way to test changes to scripts in a shell which doesn't provide a TTY.

I'm using Ubuntu 19.04, CentOS 6 and Debian 9 with bash and ksh.


1 Answer 1


The tty isn't provided by a shell (the relationship is the opposite). The tty is provided by a terminal emulator. Programs can "detach" themselves from the terminal in two parts (it depends on what the tested program actually checks for)

  1. Close stdin/stdout/stderr (which normally point to the terminal); for example, you could redirect input from /dev/null, and send output to a file or through a pipe:

    true | myapp 2>&1 | cat
    myapp </dev/null |& cat
  2. Call setsid() to detach from the controlling terminal (which otherwise would remain accessible through /dev/tty and would make the program subject to the shell's job control). From a shell you could use the tool of the same name:

    setsid myapp

So combining these two, I think you could run your test script like this:

true | (setsid ./testscript.sh) 2>&1 | cat
(setsid ./testscript.sh) </dev/null |& cat

(Yes, the parentheses are intentional – they prevent the setsid tool from having to fork and unexpectedly go "into background".)

  • 1
    Thank you. Note: The check needs to be performed as non-root user. Apr 29, 2019 at 10:17
  • 1
    Each non-rightmost component of a shell pipeline is already executed in its own subshell, the parentheses are redundant for that, and don't accomplish the goal of preventing setsid from forking in the case that setsid is the leftmost (or only) command in a pipeline in a shell with job control enabled. Nov 11, 2021 at 1:47
  • 1
    Nice, thanks! This helped be test a fix of a cronjob, running a command in docker, that would return "the input device is not a TTY" - of course, the t in 'docker exec -it ... bash -c "..." had t be removed.
    – Alex
    Aug 29, 2022 at 4:11

You must log in to answer this question.

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