How to simulate a shell without tty?

8,943

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".)

Share:
8,943

Related videos on Youtube

Kalle Richter
Author by

Kalle Richter

Updated on September 18, 2022

Comments

  • Kalle Richter
    Kalle Richter over 1 year

    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.

  • Kalle Richter
    Kalle Richter about 5 years
    Thank you. Note: The check needs to be performed as non-root user.
  • renrutsirhc
    renrutsirhc over 2 years
    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.
  • Kamil Maciorowski
    Kamil Maciorowski about 2 years
    For clarity: where you gave two pipelines one under the other, they are two independent variants and I can pick one that fits my needs better; I mean I don't need to run them both. Right?
  • user1686
    user1686 about 2 years
    @Kamil: I think those were two separate examples, depending on the program's position in a pipeline.
  • Kamil Maciorowski
    Kamil Maciorowski about 2 years
    When I read it for the first time, I expected the code to continue, like it's a snippet from a script. It took me several seconds to realize it may not be the case. Consider a comment in between. Changing each empty line to # or should do.