I am using the following /etc/inittab file (systemv):

# /etc/inittab: init(8) configuration.
# $Id: inittab,v 1.91 2002/01/25 13:35:21 miquels Exp $

# The default runlevel.

# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.


# What to do in single-user mode.

# /etc/init.d executes the S and K scripts upon change
# of runlevel.
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user.
# Runlevel 6 is reboot.

l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
S0:12345:respawn:/sbin/getty -L 115200 ttyS0

In order to understand how things really work I'll appreciate if your answers to 1-3 you'll distinguish between two situations:

  1. I'm connected to my system using a serial port.
  2. I have a "regular" desktop pc.


  1. If I'll add another getty line, once linux startup I will see two separate terminals?

  2. If I open several getty lines, how I assigned which getty will run my si::sysinit:/etc/init.d/rcS command and which getty will run the other script's commands? (the ones who run scripts according to the system run level)

    in other words: in the /etc/inittab file - can i assign different commands to different gettys? (i mean to the terminals which will open by these gettys)

  3. the last script in /etc/init.d/rc5 folder run the following command:

    su nobody -c /bin/sh

    and the output is:

    sh: cannot set terminal process group (1618): Inappropriate ioctl for device
    sh: no job control in this shell
    sh-4.3$ whoami

    So I verified that i am nobody but why it writes the first two lines? also why the prompt is sh-4.3$ and not nobody@...

  4. I'm using serial connection. Can I change the /etc/inittab file and the last script that will run by init in order to:

    1. run a program before login as low privileged user (init process will wait for termination)
    2. once the program exits get the regular login prompt to my system
    3. what is the best way to create a low privileged user and let him run this program during init process (if I don't want to use the nobody user)

3 Answers 3


Question 1:

Yes, by adding more getty lines you can get more terminals in parallel. Only one getty can be associated with one terminal device at a time, so only one getty per serial port is possible. On a regular desktop PC, the Linux kernel defines a number of virtual consoles, accessible using the Control+Alt+FX key combinations and corresponding to /dev/ttyX devices (X = a number). The exact setup may vary between distributions, but usually on mainstream distributions, the first 6 or so /dev/ttyX devices have gettys configured for them when the system is running normally. You can use openvt and deallocvt commands to add or remove virtual consoles and start processes (which can be any processes, not necessarily gettys) on them.

/dev/tty0 is special: it refers to whichever virtual console is the currently selected one. /dev/console is a similar special device, pointing to whatever TTY device is defined as the primary kernel-level system console. On desktop systems, it is effectively an alias to /dev/tty0 by default, but by using the console= boot option you could switch it to a serial port. On e.g. some embedded architectures it might be a serial port by default. Utilities like xconsole can also act as an additional output for /dev/console.

Back when computers were big multi-cabinet things in dedicated computer rooms, sending a message to /dev/console would have been a way to reach the on-duty system operator physically near the computer, which might have been useful for requests to e.g. change tapes or disk packs. On modern systems, messages sent specifically to /dev/console are usually boot/shutdown messages, or possibly a last-resort channel for urgent alarms about failure conditions that might impact network or storage access, or even involve a kernel crash: "a person in charge of the physical hardware needs to see this and the usual log files are unusable for some reason."

Question 2:

I'm afraid you have a misconception here. The sysinit line and other /etc/inittab lines are not associated with getty processes at all. Each command executed from inittab, unless otherwise specified, has its standard input, output and error streams associated with /dev/console.

The getty lines actually specify the TTY device they will be using, and the getty process has code built in that will assign that TTY device for themselves and all their child processes unless/until the user runs a shell and chooses to redirect those streams some other way. That and initializing the settings of the TTY device are the biggest part of getty's purpose: displaying /etc/issue and the login prompt, accepting the username, setting the TERM environment variable and starting the next step of the TTY login process (usually /bin/login but customizable) are effectively just minor parts.

Note that there is a convention that for the TTY devices, the two-character ID field in the first column of the inittab line should match the name of the TTY device in question after the /dev/tty prefix, so /dev/ttyS0 will get an inittab line ID of S0, and so on. For stuff that is not necessarily associated with any TTY at all (or just outputs emergency stuff to /dev/console if needed), the ID can be anything that does not conflict with the TTY device line IDs.

(Back in the day when serial-attached terminals were the norm, getting the settings of the TTY device right for the terminal at the other end of the line, and resetting that terminal to a known state for login were non-trivial tasks, since there were many competing terminal type standards.)

If you configure an inittab line to run a script, you could, for example, see if a particular /dev/ttyX virtual console device exists. If it does not, you can use openvt -c X <command> to create the virtual console and start a command on it; if the virtual console device already exists, you can simply start whatever command you want with standard input, output and error redirected to it. For example, you could specify an inittab line like this:


and then /usr/local/sbin/myscript with something like this (disclaimer: not tested, I don't have a system with SysVinit at hand right now, feel free to edit if you can improve this):

if [ -c /dev/tty6 ]; then
    exec <some command> </dev/tty6 >/dev/tty6 2>&1
    exec openvt -c 6 -w <some command>

respawn in the inittab line makes sure the process will automatically be restarted if it dies for any reason. 345 is the list of SysVinit runlevels this process should run on. If you need it to run on all regular runlevels, enter 12345.

Note, this works as intended only if the inittab line is placed after the sysinit line, so the initialization of udev can be assumed to be complete. If you want to do this early in the init process, you may have to take care of creating the actual device nodes for devices that have drivers already loaded first; once udev is running, it should create device nodes automatically as device drivers are initialized.

If using a serial port, the openvt command will not apply.

So yes, you definitely can attach different commands to different TTY devices. It helps if the commands have built-in facilities for that like gettys do, but you can do it with scripting too.

(If you set up something more complicated than a simple tail -f to permanently view some log in an otherwise-unused virtual console, you should read man setsid and see if it is applicable to what you're planning.)

Question 3:

There is more to initializing a TTY session for a particular non-root user than just starting a shell with su.

The error messages

sh: cannot set terminal process group (1618): Inappropriate ioctl for device
sh: no job control in this shell

are probably caused by the shell being associated by the /dev/console device rather than a specific TTY device. Since /dev/console is just an alias to whatever is the current system console, it won't have the full set of TTY control ioctl functions available to it.

If there is no login script to assign a more useful value to the PS1 environment variable, the default prompt for /bin/sh can be simply sh-<version>$.

Question 4:

Yes, you can. You should specify the "last script" as a wait-type line in inittab, and place it before the getty line corresponding to your serial line.

Without knowing a lot more details about your environment, it will be very difficult to say which would be the best way to create a low-privilege user for such purposes.

  • thanks! small q plz: when init process invokes other processes according to the suitable runlevel scripts , I can see that! if I'll run program from one of these scripts I'll see it executing. From my understanding - if I can see it (inside the terminal) there must be a getty who opened this first terminal for me. I guess the ttys0 getty is the one opened this first stty for me. What's the connection of /dev/console to that? and if I write 4 scripts, same runlevel, but I want each will run in different getty (but the init process is the one that runs these scripts) how can i do that?
    – hutcruchi
    Commented Nov 5, 2019 at 14:01
  • getty is a process; what you are talking about is a TTY device. The kernel opened the first one for you and for the init scripts; /dev/console is an alias to "the first TTY device that was opened and used by the kernel". If your user account has the permissions for read+write access to a TTY device, you can just start using it (no getty needed), but it might be a good idea to set the TERM variable correctly: TERM=linux top </dev/tty8 >/dev/tty8 2>&1 & or TERM=vt100 top </dev/ttyS1 >/dev/ttyS1 2>&1 & will start the top command on the 8th virtual console or the 2nd serial port.
    – telcoM
    Commented Nov 5, 2019 at 16:33
  • If you attempt to run a process on a TTY device that already has a getty process on it, it will make a mess of the input&output, as the two processes will fight for the input and their outputs will get mixed up together. The getty processes are started only after the /etc/init.d/rc 5 and any scripts started by it have finished.
    – telcoM
    Commented Nov 5, 2019 at 16:35
  • thanks for your reply
    – hutcruchi
    Commented Nov 7, 2019 at 11:31
  1. Yes, assuming the line is given a unique identifier and the configured terminal line is available:

    S1:12345:respawn:/sbin/getty -L 115200 ttyS1

    will open a terminal on the serial port attached to ttyS1.

  2. Lines in inittab aren’t sequential, or related to a login. Each line describes an action to be taken in a given set of runlevels. Thus si::sysinit:/etc/init.d/rcS specifies that init should run /etc/init.d/rcS when it handles system initialisation; this happens before logins are possible. (See the inittab(5) manpage for details).

    To assign different commands to different gettys on specific terminals, you’d configure the getty invocation itself, for example by changing the login program it starts (the -l option in most getty implementations):

    S0:12345:respawn:/sbin/getty -L 115200 -l /bin/my-t0-login ttyS0
    S1:12345:respawn:/sbin/getty -L 115200 -l /bin/my-t1-login ttyS1
  3. /etc/init.d/rc 5 runs before logins are possible, and the programs it runs aren’t connected to a terminal (“properly”, which is what getty does – it opens the terminal for you and connects the programs it starts to it), so when su nobody -c /bin/sh is invoked, the shell doesn’t find the terminal setup it expects, and disables job control as a result. The sh-4.3$ prompt is Bash 4.3’s default prompt when run as /bin/sh.

  4. If your program is only supposed to run once a user starts logging in, then you can hook it into the login sequence used by getty; but such a program would run as root. Depending on what you’re after exactly, you’d probably be better off using an initscript rather than /etc/inittab customisation, or sudo and the shell’s startup scripts.

  • thanks for your replay. Can I ask for a smail clarification regards sec.2? how can I edit the login command for each different getty?
    – hutcruchi
    Commented Nov 5, 2019 at 8:58
  • Done, see the update. Commented Nov 5, 2019 at 9:03
  • thank you! just to check if I understood correctly: by default the getty process will run the /bin/login command which executes the process responsible for system login. Now the getty will run a different command , every command that I'll choose , and will not call to the system login process as before... am i right?
    – hutcruchi
    Commented Nov 5, 2019 at 13:07
  • Yes, that’s right. The key is getting getty to open the TTY for you; its normal behaviour is to wait for a login name, then run login, connected to the TTY; login waits for the password, checks it and starts the shell, also connected to the TTY. If you replace the login part, you’ll need to make sure your replacement program behaves like login. Commented Nov 5, 2019 at 13:25
  • For example if I want to skip the login phase - to be able to open my system with root user without entering any user name or password. I can use: S0:12345:respawn:/sbin/getty -L 115200 -l -/bin/sh ttyS0 or to use: S0:12345:respawn:/sbin/getty -L 115200 -l [my_script_path] ttyS0 and inside the script i'll run the -/bin/sh command and others?
    – hutcruchi
    Commented Nov 5, 2019 at 13:34

Just now a second (long!) answer has been posted. I must say the first one explains quite well. At the moment I want to comment on point three: It is less a question of timing, but of processes controlling a "real virtual" tty, and not just a "console dummy".

Before you can start a shell "with job control", you have to set up i.e. open a ttyN. The "generic" command is getty. From that tty-something you get you can start a shell, not just after that.

It is like trying to first start a window manager, and then xorg, instead of "booting" them together with xinit. I think. "session leader".

Because of


and, contrarily:


...you get a N:M relation (you also get a mess if you abuse -- many RLs each with many different progs). You can go far with that, but since ever different kinds of RC-"standards" have taken over. "Runcoms". With them, inittab looks simple, but all the complexity is in these scripts.

But your inittab looks simple and correct - only the last comment, and the "z6" entry...

Maybe your "su nobody" just needs a "getty ... ttyN" before / around. su instead of login, and no respawn. Should at least give another error message than "inappropriate".

Conclusion (after reading 2nd answer): You don't need a complicated init.d system, the raw inittab is flexible enough. Just have to get the concept and the details right.

You could set up three runlevels: one with ttyNs, one with ttySN, and one RL that starts both. It is a boot parameter you can add with the boot loader. Runlevel "5" in your case is only default. You choose a kernel, a root=, and a runlevel to init into.

The "respawn" action is what sysvinit was/is actually needed for. Much more it does not do, and less would have been possible to implement in a script. But if you exit (or crash) the "last" shell level, you need a safety net.

sysvinit can even detect a misconfig by erroring "spawning too fast -- ignoring for 5 minutes...".

You must log in to answer this question.

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