Systemd unit configuration with shell expansion - linux

I'm finally trying to convert my old init.d management script to systemd, and have run into a snag that I hope someone else has found a solution to.
My application expects an argument for the name of the file it saves logging information to, and my init script generates that name at startup with this line:
LOGFILE=`/bin/date "+$MUDDIR/lib/log/runlog.%y%m%d-%H%M%S"`
How would I go about having such a construct get run so the value is available for use in ExecStart?
Can I do something as simple as
ExecStartPre=LOGFILE=`/bin/date "+${MUDDIR}/lib/log/runlog.%y%m%d-%H%M%S"`
or would it throw a fit at trying to spawn a shell there? If it runs the command as a subshell, the value would be thrown away.
Also, if I specify multiple ExecStartPre lines, will they be executed in order?
Thanks for any hints. The documentation is a bit light on details in some places, and I'm just trying to preserve my original functionality without being cheesy and just having it call my old script.

I recommend letting systemd manage logging via its journal. Don't create a log file at all. Just have the application write to stdout/stderr. That way the logs will get stored alongside all the other applications' logs, they'll be searchable via journalctl, they'll show up in systemctl status <app>, they'll be rotated automatically, etc.
If the application absolutely requires a $LOGFILE environment variable you could use:
Environment=LOGFILE=/dev/stdout

I agree with OP's answer about letting journalctl handle logging. Rather than calling /dev/stdout in Environment attribute, use the following:
[Service]
...
...
StandardOutput=syslog
StandardError=syslog
This will put your logs into the system log, such as /var/log/messages and in journalctl. You can access the log using the service name:
journalctl -u myawesomeservice.service
As it seems, on newer (>238) systemd, you can set path to the log file.
StandardOutput=file:/path/to/logfile.log
StandardError=file:/path/to/logfile.err
Here is another SO question that provides much more info.

Related

Init.d script to systemd problem with parameters

I am trying to upgrade my init.d script called "myService" to systemd .The init.d script has 1 parameter which decides what to do, with the following switch case:
case "$choice" in
"start")
# starts service logic here
"stop")
# stops service logic here
"filter")
# runs some .sh file from our PC
esac
In order to upgrade to systemd I create myService.service file in systemd and set in the properties of the file on ExecuteStart and ExecuteStop to execute the init.d file with parameter start or stop,now I can do : systemctl start myService.service ,however if I want to invoke the filter option I am not allowed to do systemctl filter myService.service since "filter" is not valid option for systemctl .Any suggestions how can I overcome this?
This scheme does not fit within systemd responsibilities as a service manager, such as (but not limited to):
running services (e.g. starting, stopping, etc.)
the configuration of the above (e.g. which system level to run in)
providing information on the status of a service
declaring the dependencies and the handling between the various services
Although you did not provide information on the implementation of the service, it seems that the filter mode is an application/server specific action. Moreover, it's not clearly described what happens when the service is stopped and filter is issued.
So, keeping in mind the separation of concerns, I'd suggest using systemd to control the start and stop of your service, but use whatever IPC (D-Bus, sockets, signals, etc.) that service is using to trigger the filter operation.

How to run application on linux in the background but leave possibility to interact with it?

Requirements:
I want to run my application on linux in the background (at startup of course).
I want to be able to call start/stop/restart commands directly from console (it have to be simple just like for /etc/init.d - just call simple command directly from console).
I want to be able to call status - and I want that this command will somehow get the actual status of application returned by itself. I thought that I can call some method which returns String or just use stdin to send command but when I do noup .. &, or start-stop-daemon, then the stdin is detached. Is there a simple way to attach stdin back to the application (I've seen that I can create a pipe, but this is pretty complitated). Or what is the best way to communicate with application after it is started as a daemon (I can make a socket and connect through telnet for example, but I am looking for simpler solution and possibility to do it directly from console, without starting telnet first)? Ideally it will be great to get the possibility to send any command, but simple status will be sufficient (but again - it have to communicate with the application to get that status somnehow)
I have found many different answers. Some of them says to simply use nohup and &, and some others says that nohup and & is old fashion. Some answers says to use start-stop-daemon or JSvc (for java). But it seems that none of them will suffice this 3 requirements from me.
So... What are the simplest possibilities for all of 3 requirements to be met?
PS. I don't want to use screen. The application must be run as a linux daemon.
PPS. Application is written in Java but I am looking for generic soluction which is not limited to java.
You should create a command line tool for communicate with a daemon in way you need. The tool itself can use TCP/IP or named pipes.
And then use cli-tool start|stop|restart|status from console.
If you need to start a daemon at startup sequence (before user login) you have to deal with init system (init.d, systemd, OpenRC, etc...).
Dragons be here:
Be sure that init doesn't restart your daemon after manual stop via cli.
Command line tool itself runs with unprivileged user rights, so restart may be hard if first startup script use superuser rights or application-specific user and, especially in case deep init integration, you might have to use sudo cli-tool start.
To avoid this one possible solution is to make wrapper daemon, that runs forever via init and control the underlying application (start-stop) with proper rights.
Cons: Develop two additional tools for a daemon.
Pros: Wrapper daemon can operate as a circuit breaker between superuser/specific user and userspace.

Processes started with systemd are logging to /var/log/syslog and /var/log/daemon.log

I'm running a couple of python scripts on a Beaglebone Black, both started at init by systemd. I noticed yesterday that my eMMC flash was completely full, and the reason was I had 1.8 gigs of log files. It seems that the standard output of these scripts (they generate a good amount of data for debugging purposes) is being logged to both /var/log/syslog and /var/log/daemon.log. Also, /var/log/messages has a ton of entries about "rate-limiting".
Now, I assume I could fix this by disabling standard output on these scripts. However, I would much rather preserve that capability and somehow tell systemd not to log that data. However, I've been unable to find information on this.
Here is an example of my current .service file:
[Unit]
Description=Description of my process
After=network.target
[Service]
Type=simple
ExecStart=/opt/myprocess
[Install]
WantedBy=multi-user.target
I should note that I originally had syslog.target as an "After" target, just because the example I was following had it. But I have since removed it and it doesn't seem to solve the problem.
Any help or insight into this problem would be greatly appreciated.
Edit: I may have found the answer here:
http://www.kibinlabs.com/systemd-logging-tricks/
Adding StandardOutput=null and seeing if that fixes it. Looks promising.
Edit 2: It does.
SystemD does not log files in /var/log by itself, ever.
If log messages are showing up in /var/log, this suggests that your system is running a "syslog" daemon, which is receiving log messages either (a) by reading the systemd journal, or (b) by applications using syslog directly.
Simply disabling your syslog daemon would prevent files from being written in /var/log. Messages will still be written to the system journal, but there are fairly flexible controls available to you to limit the space used by these files. See the journald docs for more information.

Automating services with Linux OS starting up and shutting down

I have a script to start and stop my services. My server is based on Linux. How do I automate the process such that when OS is shutdown the stop script runs and when it is starting up, the start script runs?
You should install init script for your program. The standard way is to follow Linux Standards Base section 20 subsections 2-8
The idea is to create a script that will start your application when called with argument start, stop it when called with argument stop, restart it when called with argument restart and make it reload configuration when called with argument reload. This script should be installed in /etc/init.d and linked in various /etc/rd.* directories. The standard describes a comment to put at the beginning of the script and a uitlity to handle the installation.
Please, refer to the documentation; it is to complicated to explain everything in sufficient detail here.
Now that way should be supported by all Linux distribution. But Linux community is currently searching for better init system and there are two new, improved, systems being used:
systemd is what most of the world seems to be going to
upstart is a solution Ubuntu created and sticks to so far
They provide some better options like ability to restart your application when it fails, but your script will then be specific to the chosen system.

Howto: Using syslog for user created shell script

Information abound about syslog, but I can't find anything very concise for my interest.
I have a user-created bash script that should log various debug, info, and error messages. I'd like to use syslog. This in Ubuntu Server distribution.
I'm looking for a quick overview only.
I see many files in /etc/logrotate.d that don't get discussed in any man pages that confuse me.
Should I be logging as user? local0-7?
Do I need to do something to configure this before I use these in a logger command?
How should I define what logs get created? Or is this already done?
With those questions answered I should be able to glean the details from the man pages.
You want the logger(1) utility, available in the bsdutils package.
From the man page:
logger - a shell command interface to the syslog(3) system log module
There's nothing that's essential to configure, just pass the switches you want. E.g.
logger -p local3.info -t myprogram "What's up, doc?"
You can now inspect wherever local3.info messages go and you will see something like this:
Jul 11 12:46:35 hostname myprogram: What's up, doc?
You only need to worry about logrotate if you need something fancier than this.
As for what log facility to use, I would use daemon for daemon messages and local for most other things. You should consult syslog(3) for the purposes of the different facilities.
Don't worry about logrotate. It doesn't affect you if you're logging to the system log.
You can use any facility you like. See the syslogd configuration for what ends up where.
See the syslogd configuration for what ends up where.
See the... yeah, you get it.

Resources