diff options
authorDenys Vlasenko <>2010-06-27 00:30:42 (GMT)
committerDenys Vlasenko <>2010-06-27 00:30:42 (GMT)
commit7407ef75fe4bdb878225f16a8ec6e76bd1830b02 (patch)
parentdb0065bf54ede6c2fd905bc230103bc89e29d79f (diff)
FAQ: expand "sh: can't access tty; job control turned off" section
Signed-off-by: Denys Vlasenko <>
1 files changed, 40 insertions, 2 deletions
diff --git a/FAQ.html b/FAQ.html
index 8448505..7c5f2c2 100644
--- a/FAQ.html
+++ b/FAQ.html
@@ -583,11 +583,49 @@ int main(int argc, char *argv)
terminal. This typically happens when you run your shell on /dev/console.
The kernel will not provide a controlling terminal on the /dev/console
device. Your should run your shell on a normal tty such as tty1 or ttyS0
- and everything will work perfectly. If you <em>REALLY</em> want your shell
+ and everything will work.
+ Example: you booted into your machine with init=/bin/sh
+ and got "sh: can't access tty" error because sh has its stdio
+ opened to /dev/console. You want to reopen stdio to, say, /dev/tty1
+ and thus acquire a controlling tty.
+ # Let's try this:
+ exec &lt;/dev/tty1 &gt;/dev/tty1 2&gt;&amp;1
+ # No, doesn't work: even if opening /dev/tty1 gave sh the ctty,
+ # sh wouldn't know it - it checks for ctty just once at startup.
+ # Let's try re-execing sh:
+ exec &lt;/dev/tty1 &gt;/dev/tty1 2&gt;&amp;1
+ exec sh
+ # Got "sh: can't access tty" again. Why?
+ # The reason is somewhat obscure: kernel starts process with PID=1
+ # (in this case, shell) with SID=0 and PGID=0, not with SID=1 and PGID=1
+ # as you'd expect. IOW: our sh is not a session leader, and therefore
+ # cannot acquire ctty by opening /dev/tty1 (or any other tty).
+ # Let's try making us a session leader:
+ exec setsid sh
+ exec &lt;/dev/tty1 &gt;/dev/tty1 2&gt;&amp;1
+ exec sh
+ # Yes, this worked!
+ # This can be combined into one command,
+ # but need to be careful and perform these operations
+ # in the correct order:
+ # 1. make ourself session leader,
+ # 2. open /dev/tty1 and thus acquire a ctty,
+ # 3. re-execute the shell, allowing it to notice that it has ctty:
+ exec setsid sh -c 'exec sh &lt;/dev/tty1 &gt;/dev/tty1 2&gt;&amp;1'
+ If you <em>REALLY</em> want your shell
to run on /dev/console, then you can hack your kernel (if you are into that
sortof thing) by changing drivers/char/tty_io.c to change the lines where
it sets "noctty = 1;" to instead set it to "0". I recommend you instead
- run your shell on a real console...
+ run your shell on a real console.
<hr />