32

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
  • 2,472
  • 6
  • 44
  • 64

1 Answers1

42

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

grawity
  • 501,077