0

I have an nfsroot created from 14.04 that I am rebuilding using 16.04. My nfsroot is shared by three systems named pc1,pc2 and pc3. There are 3 matching user accounts named pc1, pc2, and pc3 as well.

When these systems boot up they automatically log in and subsequently run a bash login script.

In 14.04 I replaced mingetty in my upstart tty1.conf file as follows:

# tty1 - getty
#
# This service maintains a getty on tty1 from the point the system is
# started until it is shut down again.

start on stopped rc RUNLEVEL=[2345] and (
        not-container or
        container CONTAINER=lxc or
        container CONTAINER=lxc-libvirt)

stop on runlevel [!2345]

respawn
#exec /sbin/getty -8 38400 tty1
script
    exec /sbin/mingetty --autologin `cat /proc/sys/kernel/hostname` --noclear tty1
end script

This worked just fine in 14.04 for my purposes. It gleans the hostname from /proc and then uses that as the login name.

What I am trying to do is replicate the same behaviour in 16.04, but now using systemd.To do so I modified /etc/systemd/system/getty.target.wants. Specifically I changed the ExecStart:

ExecStart=-/sbin/agetty -a $HOSTNAME --noclear %I $TERM

However from reading the systemd docs and using some google-fu I have leared that I cannot use backticks or environment variable substitution in the ExecStart line. I have tested hard coding a user account instead and it works correctly, but I can't figure out how to do the same thing I was doing previously with upstart in systemd.

I've also tried using a small script for this purpose as well by changing the ExecStart line to:

ExecStart=/bin/sh -c "/usr/bin/autogetty.sh"

The autogetty.sh script is simple script which cats to get the hostname and feeds it to mingetty. It however doesn't appear to work. I think the issue may be that for the service, the type is idle and from my researching online it needs to be fork. I have yet to try modifying the service type yet.

I would like to know the "right way" to do this. So far I'm just trying things to make it work, and even if I make it work I won't be sure if its the best way of doing it.

Thanks.

1 Answers1

0

Wrong ideas and errors

I have leared that I cannot use backticks or environment variable substitution in the ExecStart line.

You have learned a falsehood. The doco does not in fact say this. You can use environment variable substitution (with a syntax that is subtly different to most Unix shells'). It is simply the case that there is no HOSTNAME environment variable to substitute. Service processes are not spawned with such an environment variable set up.

Unit files are parameterizable, and the %H parameter expands to the (dynamic) host name as it was at the point in the past that the unit was loaded from file.

ExecStart=/bin/sh -c "/usr/bin/autogetty.sh"
[…] I have yet to try modifying the service type yet.

Good. Do not. That's the wrong thing to do. Only change the readiness notification protocol to forking if your service actually implements that protocol. Don't do it as a kludge because you have erroneously made a program that forks for no good reason.

Because that's exactly what you have done. The unnecessary /bin/sh is forking a child to run autogetty.sh, which ends up being a second shell process running that shell script. The second shell process is then forking to run mingetty as a grandchild. This does not match the forking readiness protocol anyway, as that relies upon fork followed by exit in the parent.

Take a lesson from the world of daemontools: Services are run, not spawned. The program that you run as ExecStart should be the service process, not something that spawns the service process.

The right way

The right way to set things up is this:

  • Override a specific instance of the template, for the specific terminal device, not the whole template.
  • Use %H to obtain the host name in ExecStart. Or use %m and the machine ID as your user account names.
  • Invoke things properly:
    • Just run agetty directly, for best results. You don't actually need any scripting for the task as described at all.
    • If you do nonetheless choose to insert a superfluous wrapper script:
      • Don't use /bin/sh -c scriptfile. Just make scriptfile executable, with a properly specified script interpreter, and run it directly.
      • Make sure that your script uses exec to become the dæmon getty process.

Further reading

JdeBP
  • 3,959