7

I've found this question, but it talks about a version of Ubuntu with a GUI. I'm referring to Ubuntu Server, so no GUI. I've also found this question, but it doesn't look like it will display the output of a command, but instead only static text.

The Ubuntu Server login screen looks something like this:

Ubuntu 22.04 LTS mycomputer tty1
mycomputer login:

However, I'd like it to run a command (either as root or under my account - you can pick), and then I'd like it to print the output of the command before giving the login prompt.

For example, if my command was echo Hello world!, I'd like it to look like this:

Hello world!
Ubuntu 22.04 LTS mycomputer tty1
mycomputer login:

Or this would be fine too:

Ubuntu 22.04 LTS mycomputer tty1
Hello world!
mycomputer login:

While it was in my example, the output of my command can change - it isn't gaurenteed to be the same each time, so I can't hardcode the output of the command into a file (in my case, the command is hostname -i, which prints the IP address).

I often need to check the IP of a machine, and it would be easier if I didn't have to sign in to check it. For the sake of the question, assume this is a personal server on a home network, and so leaking the IP address isn't a concern.

How can I display the output of a command in the command-line login screen?

cocomac
  • 3,824

3 Answers3

9

As you already discovered, the appearance of the server login screen is controlled by a getty program - by default, that's agetty on Ubuntu. The agetty program reads from a file named /etc/issue - and since agetty version 2.35, optionally from files in /etc/issue.d. From man agetty:

ISSUE FILES

   The default issue file is /etc/issue. If the file exists, then agetty
   also checks for /etc/issue.d directory. The directory is optional
   extension to the default issue file and content of the directory is
   printed after /etc/issue content. If the /etc/issue does not exist,
   then the directory is ignored. All files with .issue extension from the
   directory are printed in version-sort order. The directory can be used
   to maintain 3rd-party messages independently on the primary system
   /etc/issue file.

So the procedure is:

  1. create the /etc/issue.d/ directory if it does not already exist

  2. create a script to run your command and write its output to a .issue file in that directory

  3. modify the template getty@.service to execute the script via its ExecStartPre

Proof of concept (tested on a 22.04 desktop VM):

sudo mkdir -p /etc/issue.d

sudo nano /usr/local/sbin/issue

with content

    #!/bin/sh
/bin/date +'Hello world @ %c' > /etc/issue.d/50hello.issue

(the date command so we can confirm the content is generated dynamically).

sudo chmod +x /usr/local/sbin/issue

Now make a local copy of the agetty@ service file:

sudo cp --no-clobber /lib/systemd/system/getty@.service /etc/systemd/system

Edit the copy with your favorite text editor and add the ExecStartPre instruction:

[Service]
# the VT is cleared by TTYVTDisallocate
# The '-o' option value tells agetty to replace 'login' arguments with an
# option to preserve environment (-p), followed by '--' for safety, and then
# the entered username.

ExecStartPre=-/usr/local/sbin/issue ExecStart=-/sbin/agetty -o '-p -- \u' --noclear %I $TERM . . etc.

The leading "-" stops the whole unit from failing if your ExecStartPre command fails from some reason.

It should work right away if you switch to a new TTY - to see the effect in an existing TTY you may need to restart the instance service ex. sudo systemctl restart getty@tty2.service

tty2

steeldriver
  • 142,475
2

After login motd (not exactly what is needed):

# cat /etc/update-motd.d/00-update
#!/bin/bash
echo
echo "Server IP: $(hostname -i)"

Don't forget

chmod +x /etc/update-motd.d/00-update

Doc:

man update-motd
1

Pre-login the banner is provided by /etc/issue.

This file by default for me on Kubuntu 22.10 contains a single line:

Ubuntu 22.10 \n \l

The \char look like escape codes but they're not what you expect, the man issue output has your back here:

The issue files may contain certain escape codes to display the system name, date, time et cetera. All escape codes consist of a backslash (\)
       immediately followed by one of the characters listed below.
   **4 or 4{interface}**
       Insert the IPv4 address of the specified network interface (for example: \4{eth0}). If the interface argument is not specified, then select
       the first fully configured (UP, non-LOCALBACK, RUNNING) interface. If no configured interface is found, fall back to the IP address of the
       machine’s hostname.

   **6 or 6{interface}**
       The same as \4 but for IPv6.

So, adding "\4" (without quotes) to /etc/issue will print the IP address. Neat. Note that it only works on TTY that you haven't yet entered [since the last reboot?]; you can logout of a TTY and it resets the issue banner. Also \n is not a carriage return, whitespace is preserved, but instead is the "nodename" which for me is the same as the output from host.

This is only for TTY's, if you want a banner for remote login then you'll need to look at the program that provides the remote shell, such as SSH (see sshd_config file).

===

Edit: I also had a file called issue.net, but that seems to be vestigial (old and unworking). /etc/issue is from the base-files package. I did not have an /etc/issue.d directory but making one, adding a file with extension ".issue" works. I didn't test extensively; apt-file search "/issue.d" returns only the package freedombox (which I've never heard of).

pbhj
  • 3,364