I have a systemd template, load#.service defined as:
[Unit]
Description=load script
Wants=network-online.target
After=network-online.target
PartOf=load.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 load -d %i
User=root
[Install]
WantedBy=default.target
I need to run four different instances of this script with different parameters for -d, so I have set up a load.target defined as:
[Unit]
Description=dataloader.load workers
Wants=load#1.service load#2.service load#3.service load#4.service
[Install]
WantedBy=multi-user.target
I want each of the four instances to run every 10 minutes.
How can I set up a systemd timer to invoke the .target at an interval?
You can create a timer unit load#.timer defined as:
[Unit]
Description=Run load#.service every 10 minutes
[Timer]
OnCalendar=*:0/10
AccuracySec=1us
And modify load.target to invoke the .timer units instead of the .service units:
[Unit]
Description=dataloader.load workers
Wants=load#1.timer load#2.timer load#3.timer load#4.timer
[Install]
WantedBy=multi-user.target
Related
Goodday guys,
I am trying to build and run program in linux (raspberry) as a service.
It is a sample application that uses the Cerence SDK C API that implements a wake-up-word (WUW) plus command utterance recognition.
I can execute it by ./name.exe or using the Makefile commands.
The problem is that when I execute the program by console it works fine, without any problem.
When I try to execute it as a service (using both systemd or crontab and also rc.local), an error occours.
This is the function that gives me error:
printf("Selecting audio configuration %s\n", audioScenarioName);
rc = nuance_audio_IAudioManager_activateScenario(audioMgr, audioScenarioName);
if (NUANCE_COMMON_OK != rc) {
printf("Audio scenario activation failed: %d\n", rc); <-- returns 1 (error, impossible to activate scenario)
return rc;
}
ActivateScenario it's a function that simply selects the correct mic (audioScenarioName) following a JSON file and the audio manager (audioMgr).
Unfortunately this function returns 1 if something goes wrong, closes the program and nothing else.
This is the JSON:
"type": "AudioInput",
"name": "mic_input",
"adapter_type": "CUSTOM_AUDIO",
"adapter_params": {
"device_name": "default"
},
"audio_format": { "uses": "16khz_1ch" }
The service should be running as root permissions (default).
I also tried by setting the whole folder as chmod -R 777 as a test, but same problem.
This is my service:
[Unit]
Description=My Service
[Service]
Type=simple
ExecStart=+/home/pi/.../nameexec
Restart=on-failure
RestartSec=5
KillMode=process
[Install]
WantedBy=multi-user.target
I've also set the absolute path of its lib directory that it needs into the ld.so.conf file.
The only libraries I put in it are the .so ones, but not .h.
I am now trying to understand what might be different about starting the same executable but in different ways.
Could it be a permissions issue? Or is it not detecting the microphone? Any library out of place?
I really don't know why it works with the classic command and not as a service.
Can someone please help me with this?
Thank you in advance!
I succeeded!
The problem was the microphone being used.
Using Raspbian ver. Desktop, I set the mic from the bottom right part of the taskbar and changed the defaults in/out.
But these settings seem to be not system-wide and not used by the services in background (even though the "User=" is set to "pi").
So I had to change alsa.conf file:
sudo nano /usr/share/alsa/alsa.conf
Then find and edit these lines:
defaults.ctl.card cardnumber
defaults.pcm.card cardnumber
You can find the card number by running arecord -l.
I am writing a systemd service to update the firmware on the machine, if it is not the same as present in the executable.
[Unit]
Description=Firmware Update Service
[Service]
ExecStart=/path/to/fwupdate
[Install]
WantedBy=multi-user.target
In the code, I just call a function which will verify if the firmware needs to be updated or not and updates if necessary.
Below is the pseudo code:
int main()
{
FwuRunFirmwareUpdater();
return 0;
}
Should I still add the code to handle SIGTERM, am I missing anything as I am writing systemd service/daemon for the first time
I have a program in C that runs well when running it directly from the comand line but fails when running it with systemd:
Core was generated by `/usr/local/bin/midnite-modbusd'.
Program terminated with signal SIGFPE, Arithmetic exception.
#0 0x0000000000401308 in main (argc=1, argv=0x7ffeae390268) at src/midnite-modbusd.c:139
139 slen= interval - (millis % interval);
The code in question:
//wait for start of each sample interval
gettimeofday(&tv,NULL);
millis= (long long unsigned)tv.tv_sec*1000 + (tv.tv_usec/1000);
slen= interval - (millis % interval);
i= (millis+slen) % 1000;
usleep (slen*1000);
The full code is available on github.
The systyemd unit:
[Unit]
Description=Midnite Classic modbus data polling
After=network.target
[Service]
Type=simple
User=midnite-modbusd
ExecStart=/usr/local/bin/midnite-modbusd
Restart=on-failure
[Install]
WantedBy=multi-user.target
What can be so different when a program runs with systemd ?
Edit 1
It seems that my program has major issues that only happen when running with systemd:
it won't read my configuration file, which should throw an error message and exit(1) because of invalid values
journactl doesn't get filled in real time. Using journactl -f I have to wait a couple of minutes before seeing a bunch of logs that appear suddenly
As a side note for my tests using the command line I run: sudo -H -u midnite-modbusd /usr/local/bin/midnite-modbusd
A defined value of sample_interval from configuration file will initialize the interval, please check if the file is correct and sample_interval is present. An uninitialized value of interval might cause the divide by zero exception
I found the issue in this code:
if (getppid()==1) {
sprintf(str, "Daemon aready running");
log_message(log_file_path,(char*)str);
return;
}
This code is here for when the program was intended to fork itself to run as an "old style" daemon.
I didn't realize that, as systemd is forking it, then the program have a parent process (thus getppid() returning 1 when running with systemd but not from the command line)
Anyway it is badly written: this test should stop the script.
I would like to fail my builds if ANY particular unit test execution time (not the summary tests run time) exceeds certain reasonable limit, say two seconds. I am using MSTest.
Thanks!
Use the timeout block to create a timeout failure. Here is an example from the Jenkins CI Jenkinsfile:
// We're wrapping this in a timeout - if it takes more than 180 minutes, kill it.
timeout(time: 180, unit: 'MINUTES') {
// See below for what this method does - we're passing an arbitrary environment
// variable to it so that JAVA_OPTS and MAVEN_OPTS are set correctly.
withMavenEnv(["JAVA_OPTS=-Xmx1536m -Xms512m -XX:MaxPermSize=1024m",
"MAVEN_OPTS=-Xmx1536m -Xms512m -XX:MaxPermSize=1024m"]) {
// Actually run Maven!
// The -Dmaven.repo.local=${pwd()}/.repository means that Maven will create a
// .repository directory at the root of the build (which it gets from the
// pwd() Workflow call) and use that for the local Maven repository.
sh "mvn -Pdebug -U clean install ${runTests ? '-Dmaven.test.failure.ignore=true -Dconcurrency=1' : '-DskipTests'} -V -B -Dmaven.repo.local=${pwd()}/.repository"
}
}
I'm trying to run a simple C code when the pi boots, so I followed the steps on the documentation (https://www.raspberrypi.org/documentation/linux/usage/rc-local.md), but when I start it, it shows this error:
Failed to start etc/rc.local compatibility.
See 'systemctl status rc-local.service' for details.
I do as it says and I receive this:
rc-local.service - /etc/rc.local Compatibility
Loaded: loaded (/lib/systemd/system/rc-local.service; static)
Drop-In: /etc/systemd/system/rc-local.service.d
ttyoutput.conf
Active: failed (Result: exit-code) since Tue 2015-12-08 10:44:23 UTC; 2min 18s ago
Process: 451 ExecStart=/etc/rc.local start (code=exit, status=203/EXEC)
My rc.local file looks like this:
./home/pi/server-starter &
exit 0
Can anyone show me what I'm doing wrong?
You have to refer to your script using an absolute path.
/home/pi/server-starter &
Notice the absence of the . in comparison to your solution.
Also, you may have to add a reference to the shell right at the beginning of your rc.local.
#!/bin/sh -e
/home/pi/server-starter &
exit 0
to run a script shell "in a script shell" use this :
sh -c /absolute/path/to/script;
to run this script in background use this :
sh -c /absolute/path/to/script &;
Don't forget exit 0 at the end of the file