Score:0

Multiple instances of systemd unit not writing to log files

jp flag

I'm trying to create a systemd unit file that will take an argument for a php script.

The small php script:

<?php
$val = $argv[1];

while(true) {
        echo "Argument = $val\n";
        sleep(1);
}
?>

Devs are working on the real script. All I need to do to test is take an argument, which is passed in the systemd unit file. Here it is:

[email protected]

[Unit]
Description=Systemd Params Test
Wants=network-online.target
After=network-online.target

[Service]
Environment=ARGS=%I
ExecStart=/usr/bin/php /home/myself/test_systemd.php $ARGS
StandardOutput=file:/var/log/test-multiple-systemd-$ARGS.log

[Install]
#Start after boot
WantedBy=multi-user.target

I start the multiple instances with systemctl start [email protected] and systemctl start [email protected]. When checking the services, I see:

root@servername:/lib/systemd/system# systemctl --type=service | grep test
[email protected]      loaded active running Systemd Params Test                                                          
[email protected]      loaded active running Systemd Params Test 

It is not creating the different log files. It's only creating a single one, strangely with quotes around it:

-rw-r--r-- 1 root root 285 Dec 8 08:15 'test-multiple-systemd-$ARGS.log'

And the content of the log file is mostly "Argument = bar". Only a few instances of "Argument = foo" for some reason:

cat /var/log/test-multiple-systemd-\$ARGS.log

Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = bar
Argument = foo <--- WHY???
Argument = foo
Argument = foo
Argument = foo
Argument = foo
Argument = foo

Is it possible to write to different log files for each instance of the systemd unit? I would like to see test-multiple-systemd-foo.log and test-multiple-systemd-bar.log if those are the arguments I pass. I've tried escaping the $ in the log path to no avail. I've tried removing and adding quotes to the Environment="$ARGS=%I" also to no avail. The log always shows with quotes with the literal "$ARGS" in the name.

UPDATE

It appears I cannot create the multiple log files dynamically, per this answer.

So, I created the log writing in the php script with:

echo file_put_contents("/var/log/test-multiple-systemd-$val.log", "Argument=$val", FILE_APPEND);

Will this suffice? I'm getting the multiple log files now and they are writing the argument correctly to the log file.

Gerrit avatar
cn flag
While starting a file from your script works, I would say that using the systemwide /var/log directory for a bash script could be unsafe, and you still have to contend with unexpected stderr/stdout coming from the script. Did you consider just using the journal and `systemd-cat` or `logger` in your script?
DevOpsSauce avatar
jp flag
This is not a permanent log path. I'm just testing on a dev server. :) The logs are in a subdirectory of /var/log/. They've existed for quite some time, but now they're wanting multiple instances of the same script.
Gerrit avatar
cn flag
It probably doesn't make sense to put the ARGS into the environment, if you already include this info on the ExecStart line. Just use '%i" in the ExecStart line and be done with it. Prefer %i here, because otherwise you could have an escape of the quotes and unwanted globbing and word splitting by the shell. Not an issue if you only use numbers, but higly recommended for more general usage of these methods of passing the instance variable.
Gerrit avatar
cn flag
Also look here for an idea how to package your instances into a target that can run a defined set of them: https://www.stevenrombauts.be/2019/01/run-multiple-instances-of-the-same-systemd-unit/
Score:0
sa flag

You should fix your .service file for several log files. Variables should be with braces {}. Like this:

ExecStart=/usr/bin/php /home/myself/test_systemd.php ${ARGS}
StandardOutput=file:/var/log/test-multiple-systemd-${ARGS}.log
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.