There is a fairly fundamental thing about dæmons that you're missing: As standard they don't have controlling terminals. They don't have open file handles for terminal devices. Anything that expects to talk to "the terminal" won't do so. There is no "the terminal".
No, $TERM
doesn't specify "the terminal". It specifies the terminal type, i.e. what escape sequences to send as output and to interpret as input. It is needed here, and you'll have to arrange for it to be set to an appropriate value. But it's not the major factor here. The major factor is that there is no "the terminal".
Yes, the output ends up in /var/log/messages
. The standard output of a service goes to the journal by default under systemd
, and you've evidently got a syslogd
of some sort running. That you saw this only after $TERM
was set simply means that your script got further along, past the part where it needed to know the terminal type in order to work out how it was going to output things.
systemd
does have the ability to attach dæmons to terminals. It has to have. It runs agetty
as a daemon to provide the login sessions on virtual terminals.
What you are looking for are the StandardInput=
, StandardOutput=
, and TTYPath=
settings, to add to that unit file in your question. Have a look in /usr/lib/systemd/system/getty@.service
to see them in use.
You don't give enough information in your question as to whether this is precisely the right approach, or whether instead you should be adding an ExecStartPre=
to a custom /etc/systemd/system/getty@.service
. It all depends from whether this is something to be run once before starting a GUI, or every time before every individual (TUI) login. Before=graphical.target
hints at the former, but this could be not what you actually wanted (given the RequiredBy=
). ☺
In systemd (and other modern init systems), service startup is strictly separated into two steps:
- User tools (e.g. systemctl) remotely ask init (pid 1) to start a particular service.
- Init reads the service's configuration, sets up environment (including switching to the desired user account), and runs the executable.
Due to this indirection, services are guaranteed to always have the same environment regardless of who and how started them. (Previously, user environment like locale, path, or SELinux contexts leaking into services used to be a common problem.)
(For init.d scripts, the distro's lsb-functions file contains the magic redirects to 'systemctl start', so they also receive the same indirection.)
This also means that you cannot start a service "as the same user" – you must configure a specific username in the relevant systemd .service file (and if there is none, you really should write one).
The 'start service' call is normally privileged, but you can write a polkit rule allowing it per-user or per-service (if the systemd version is recent enough):
/* /etc/polkit-1/rules.d/allow-whatever.rules */
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.systemd1.manage-units") {
var verb = action.lookup("verb");
var unit = action.lookup("unit");
if (subject.user == "manager"
&& unit == "app.service"
&& (verb == "start" || verb == "stop" || verb == "restart"))
{
return polkit.Result.YES;
}
}
});
Alternatively, it might be possible to opt out of indirection in the init.d script, but then you would also lose systemd's service tracking entirely – your daemon will look like a regular user process.
Best Answer
Use systemd it already includes support for user sessions, in fact you should already depend on it (unwittingly).
Create the service directory
Create edit a service file (vim, gedit, geany - whatever you want)
It should roughly look like this, if it's a permanent service.
But it sounds like you rather want to trigger it once, then be good with it, so rather use a oneshot configuration like this:
This of course assumes that your script is executable, i.e.:
Else you would need to prepend the path to the respective interpreter:
Now reload systemd (and re-login for the sake of testing)
If you need more information refer to the Arch-Wiki for example. This askubuntu thread has various ideas, including incidentally, mine.
You can extend the behaviour (if you are root) to other users by defining the service globally. In order to do this you would need to create the service file in /usr/share/systemd/user/ not in $HOME/.local/share/systemd/user.