Problem creating a service to start at boot

Hello everyone,
I need to insert some kernel modules and then run a few programs in user space that use these kernel modules. All this has to happen at boot time. The way I have done it in the past in opensuse Linux has been to create a service script placed in file called /etc/init.d/myService – this script was created by modifying the “skeleton” example file found in that */etc/init.d/ *directory. I added the pathname to the kernel modules to be inserted to a file called /etc/ld.so.conf.d/myService.conf and ran command: ldconfig to ensure the pathnames were picked up.
The service was enabled using command: chkconfig myService on
All environment variables needed were added to /etc/profile.local to ensure they were available early during the boot process.
The problem is that none of the above now works in Tumbleweed. In Yast I can see my service is present and enabled but fails to run and the log says: “myService.service: Failed to execute command: No such file or directory” even though all programs and .ko modules to run are at the correct specified location so I don’t know what the problem is.
I don’t mind separating the insertion of kernel modules from running the programs needed – but they have to happen during boot. I have done a lot of searching on the internet and found many different ways of boot time insertion of modules and running programs but none of them have worked.
I would be grateful for and advise or help.

Hi and welcome to the Forum :slight_smile:
You can add your kernel modules to load in /etc/modules-load.d/ with a format of the kernel module name and then in the file the kernel module name, eg;


cat /etc/modules-load.d/it87.conf

it87

Environment variables can be exported in your ~/.profile

You need to look at converting your deprecated sysvinit script to a systemd service, perhaps if you post the script and systemd service can be run instead

Hello Malcolm, thanks for your reply. I have to insert 16 kernel modules. I previously used a shell script with 16 lines of insmod commands. This script was called from myService service script. Does it mean I now need 16 files in the /etc/modules-load.d directory? One of the modules need an argument, I have used following command to insert it:
*insmod /usr/realtime/modules/rtai_netrpc.ko ThisNode=“127.0.0.1” *
What would be the filename for this module and how would the argument be passed?
If I don’t need to specify the full pathname in these files how would the system know the modules are in */usr/realtime/modules/ directory?
*BTW for your information my [FONT=“Calibri”]Tumbleweed is 32-bit but I am sure it is irrelevant.[/FONT]
Many thanks again for your help!

Hi
No, you can leave your script to run, just need to create a systemd service to run it, though if the hardware is present it should just load if the modules are installed in the correct place…?

Then one that needs options could be done via /etc/modprobe.d (look at existing ones for an example);

<some_kmp> <some option>

Add a simple systemd file called say /etc/systemd/system/mymoduleload.service


# /etc/systemd/system/mymoduleload.service
#

[Unit]
Description=Load my modules

[Service]
Type=simple
ExecStart=/bin/bash -c '/path to your script/script_name'

[Install]
WantedBy=multi-user.target

Test;


systemctl status mymoduleload.service
systemctl start mymoduleload.service
systemctl status mymoduleload.service

if all ok (as in success), you might need to change to oneshot or forking for the 'type'.

systemctl enable mymoduleload.service

Reboot and see it all works…

Hi,
You mentioned “…though if the hardware is present it should just load if…”.
Just in case your suggestions may be affected by what I am trying to do I think I should clarify; these modules are RTAI modules required to create a real-time pre-emptive Linux environment, so they are not related to any particular hardware. As mentioned I have already done this with an old OpenSUSE Linux quite successfully.
So in brief I need to convert my service script to a system one and can still call the old shell script to insert the modules I need with full pathnames specified for each?

Hi
Yes, if built as KMP’s (kernel module packages), they would be built and installed in /lib/modules/<kernel>/updates, so even out of tree become part of the kernel, if manually put there, AFAIK running a depmod would add them.

Here’s an example (see the spec file);

Yes, your correct, just need a service file and carry on with your script :slight_smile:

Hi Malcolm and many thanks for your help. I now have to try out these suggestions and see what happens!
But one important thing I never mentioned is that; I started this thread by asking “why my service didn’t work” but my problem is something else and quite simple, I am just complicating the matters because I only want to insert a few RTAI kernel modules followed by running an RTAI application that needs them at boot time.

In the old days the only way I could do this or found how to do this was doing it as a Linux service. If I could do the above differently then I wouldn’t need the service script and wouldn’t have to convert it to systemd format and get involved how services work, etc., etc.

So the REAL question is; in openSUSE Tumbleweed or indeed Leap, how do I insert a few kernel modules and run a program during boot before login appears?
Many thanks again for your time.

Hi
Well, I’m assuming your building these modules against the current kernel? If so, then consider building and installing as kernel modules and then you could just have a file in /etc/modules-load.d to insert them at boot time. You could try adding the full path to them and see how it goes?

Then the service file can run your script…

There is also dracut to use so they get automatically built on a kernel upgrade.

Many things have changed with the deprecation of sysvinit, unfortunately (just like cron jobs and moving to systemd timers) it’s time to get up to speed with current practices as the transition time has passed and old stuff is getting dropped…

So you have the sources for these kernel modules, are they open source?

Hi, for RTAI I have configured and used vanilla kernel version 4.9.80 - Tumbleweed is running on this cut-down version without any problem and the modules are built against this kernel.
The kernel modules specified in a .conf file placed in /etc/module-laod.d/ are expected to be in the standard lib directory whereas my modules are in /usr/realtime/modules/ - therefore the question simply boils down to this; how to run a shell script containing the following commands at boot time, bearing in mind that the order of insertion is important:

#!/bin/bash
insmod /usr/realtime/modules/rtai_hal.ko
insmod /usr/realtime/modules/rtai_sched.ko
insmod /usr/realtime/modules/rtai_fifos.ko
insmod /usr/realtime/modules/rtai_sem.ko
insmod /usr/realtime/modules/rtai_mbx.ko
insmod /usr/realtime/modules/rtai_msg.ko
insmod /usr/realtime/modules/rtai_netrpc.ko ThisNode=“127.0.0.1”
insmod /usr/realtime/modules/rtai_shm.ko

Without worrying about services etc.?

Hi
Well easiest way is the simple systemd service as indicated with the exec your script wherever it is. Else it depends on what part of the system startup, eg if some piece of equipment gets plugged in, then a udev rule, a user logs in the a ~/.profile call to the script should suffice.

Thanks Malcolm. OK so we are back to square one, i.e. I need to use the same service script I have had but convert it to systemd format – this script will show in Yast and can be started, stopped and restarted.
As this script is a proper shell script it cannot have a name with .conf extension and a one line content with the module name which is what is expected in /etc/modules-load.d/ - so where should it reside?
So there is normally an equipment already connected to the PC, up and running by the time the PC comes up – this is a control system that needs to run with or without a user logging in, it’s not the user that plugs it in. I think as long as the modules are inserted and the main control application runs automatically before anyone can log in we are good.
BTW in the old system I needed to put the environment variables in /etc/profile.local – these are required by the application that is supposed to run during boot so need to be available early during system start-up phase, they don’t belong to any user to be put in .profile in a home directory - do you agree I need to do the same?
And to be sure where should the service script with various calls to other scripts and programs to exec reside, and its name format be?

Hi Malcolm, sorry you had already answered the question i.e. location and file name format of the service script.
I just have to find some good example and rewrite it in systemd format. If any problem running it I will ask, if you know of good and simple example I would appreciate it and thanks again for your help!

This is not my text, but it might be helpful:

writing systemd unit files is pretty simple, it’s more straight forward than for the good old init. I will demonstrate it on a short example:


[Unit] 
Description=My cool daemon 
After=mysql.service  


[Service] 
User=daemon_user 
ExecStart=/usr/local/bin/daemon  


[Install] WantedBy=multi-user.target

If your daemon depends on some other processes you should add it to After section. Maybe you also want to replace daemon_user with the your spcific daemon user.

Then copy this file to /etc/systemd/system/daemon.service, reload configuration with

systemctl --system daemon-reload

and start it with

systemctl start daemon.service

that’s it.

To enable it on startup just type

systemctl enable daemon.service

. It’s really quite simple, isn’t it

Hi Henk, many thanks for your reply. I agree this looks quite simple if it works! The reason I am very cautious is last time I experimented on this I ended up having to reinstall Linux and I am not dealing with a simple installation as you have gathered from the thread it involves having to reconfigure, patch and rebuild the Linux running under Tumbleweed!
My daemon depends on a shell script called myshell.sh which simply includes 16 insmod commands to insert some kernel modules in a certain order - this script has to be called first. Then I need to call the main daemon called mYdaemon; so in your example service script where should I add these two files please?

On Sun 16 Dec 2018 12:46:03 PM CST, areft wrote:

Hi Henk, many thanks for your reply. I agree this looks quite simple if
it works! The reason I am very cautious is last time I experimented on
this I ended up having to reinstall Linux and I am not dealing with a
simple installation as you have gathered from the thread it involves
having to reconfigure, patch and rebuild the Linux running under
Tumbleweed!
My daemon depends on a shell script called -myshell.sh- which simply
includes 16 -insmod- commands to insert some kernel modules in a certain
order - this script has to be called first. Then I need to call the main
daemon called mYdaemon; so in your example service script where should
I add these two files please?

Hi
You add them in the same service, your script as ExecStartPre= and the
daemon script as ExecStart=

Ref: systemd.service


Cheers Malcolm °¿° SUSE Knowledge Partner (Linux Counter #276890)
SLES 15 | GNOME Shell 3.26.2 | 4.12.14-25.25-default
If you find this post helpful and are logged into the web interface,
please show your appreciation and click on the star below… Thanks!

Hi Henk, I tried what you suggested but it did not work. The log says:
/etc/systemd/system/myService.service:3: Unkown lvalue ‘ExecStartPre’ in section ‘Unit’
I have set the ExecStartPre equal to the full pathname to the shell script that inserts the kernel modules with #!/bin/bash as its first line and insmod commands with full pathname to the kernel modules.
Please forgive the details, just trying to make sure you are not assuming anything wrong.
Thanks

I think the first problem is that ‘ExecStartPre’ should not be in [Service] section, there are plenty of wrong examples in internet. Obviously will have to read the full system spec to get this right!

Well, it wasn’t me that suggested the ExecStartPre, it was Malcolm :wink:

In fact, after reading his post, I went to the man pages and tried to find the ExecStartPre, but could not find it. So I was already wondering.

The only thing I tried was to give you a start on making such a Unit… I did not realy study your case in depth. So the following might be a stupid remark. I do not quite understand why you want to have two scripts, one for loading the modules and one for the things that follow. Can’t that be done in one script? Then you only need the ExecSatrt= clause.

Because traditionally the shell script has only dealt with kernel modules and the daemon itself effectively is a user space program, and there are issues mixing them.
I just moved ExecStartPre to the Service section which is where it belongs and everything started to work!
Now I just have to add a ExecStartPost to complete the service.

Question: Currently I don’t have a ExecStop in my Service section but command ‘systemctl stop myService’ works perfectly. Does this mean the systemd automatically kills the process started with ExecStart?
If I add a ExecStop to run a script to rmmod the modules inserted, would this script run after the daemon has been automatically killed by systemd? If not what command do I need in the Service section to run a script to remove the kernel modules AFTER the daemon has been killed?