vixalien I'm inferring that for example, If I have a module called boot, that means that every service in there is isolated right?
Correct
vixalien Could I replace and disable some services in there?
Absolutely
vixalien For example, alpine has a service named networking that has provide net. But in alpine, there is also networkmanager and I can enable networkmanager and networking will hence be disabled.
Here you refer to an alias feature. This is for now something missing with 66 but planned.(see this and the roadmap)
Anyway, you can do what you want with a module.
First copy the original module service directory to the sysadmin directory. This will avoid you to loose changes when you update the service through the packager.
# cp -r /usr/share/66/service/boot /etc/66/service/
According to the (light) documentation, you will found different directories for different purpose.
Activated directory
As you said, service inside module are isolated. That means that a service inside a module cannot declare a dependency to a service outside the module. If a service inside the module need an external service, you need to declare the module itself depending on that service. This is purpose of the activated/{depends,requiredby}
directories. For instance, if i create an empty file at activated/requiredby/networknamager
, the networkmanager service will only start when all services inside the module has started successfully.
If you create an empty file named activated/depends/networmanager
, the boot@
service (and so all service inside the module) will only start if the networmanager
service started successfully. I think you get the point.
Now if you create a empty file at root of the activated directory named networmanager
, the service networmanager
will always be activated when you start the boot service. But, and this is important to understand, any service name declared at the activated root directory must have the corresponding frontend file declared at the module frontend directory.
Taking the actual boot@
service as example, you will see an empty file named local-dmesg
declared at activated directory. This means that this service will always be present into the boot@
service when you start the boot@
service. And this local-dmesg
have the corresponding frontend file declared at the frontend/local
directory.
The activated directory can also be populated with the configure/configure
script. That means that this directory can be populated on the fly depending of the choices of the user at configuration time.(see below at configure script section)
Frontend directory
This is where you define the frontend file of every service that you will need for your module. You can organize it as you want with many sub-directories that you need. As you can see with the actual boot@
service, many sub-directory exist. The name, the number and the order of the directory does not matter. But, all service that you need must exist in this directory. If it not the case the parser will crash.
The frontend file of the module itself must be at the root directory of your module service. For instance, the frontend file of the boot@
service is declared at boot/boot@
. This is the only one authorized at the root directory of the module. Again, all others frontend file must be declared at the frontend directory inside your module directory (so e.g. boot/frontend
).
Frontend file of the module itself
The frontend file of the module itself only accept the following field at [Main]
section:
- Type
- Description
- Version
- User
- Depends
- RequiredBy
- OptsDepends
- CopyFrom
It also accept the [Regex]
section and the [Environment]
section.
Regex section
This section allow you to prepare your frontend file and directories of the module. This section is applied to the module before performing the parse process of each frontend file found inside the module. This is important to understand. That means that you can rename file and directory or make a regex operation inside the frontend file of a service.
Configure keyword
This field allow you to pass any arguments to the configure script. For example you can pass the template name of the module service like this (see identifier)
Configure = "@I"
As the frontend file of the module will be parsed first before parsing all others services the identifier will be replaced by the corresponding word.
For instance, enabling the module boot@
with the following command 66 enable boot@system
, at execution time of the configure script, the script will receive as arguments system
.
You can pass any arguments that you want, e.g. :
Configure = "-p shortoption --longoptions=myvar @R".
It will be your responsability to interpret the arguments inside your configure script.
Directories keyword
This field allow you to rename the directory found at the frontend directory of your module. For instance, i have a directory named frontend/login-manager@DM
and my Directories
field declare:
Directories = ( DM=sddm )
the directory frontend/login-manager@DM
will be renamed frontend/login-manager@sddm
. You can obviously specify multiple regex like this:
Directories = (
DM=sddm
myregex=replacedby
)
Files keyword
This is exactly the same as the Directories field but applied to the name of a files instead of the name of a directory.
Infiles keyword
This will allow you to make a regex operation inside the file. The perfect example is to replace the version. Let's take an example.
I have a frontend/networking
declaring the following :
[Main]
Type = classic
Description = "networking service"
Version = %%version%%
User = ( root )
[Start]
.....
and my regex contains:
[Regex]
InFiles = (:networking:%%version%%=0.1.0)
at the end of the regex process, my frontend/networking
file will contains:
[Main]
Type = classic
Description = "networking service"
Version = 0.1.0
User = ( root )
[Start]
.....
You have two options here. You can apply a regex to all files found at the frontend directory of the module or you can specify the file to apply the regex. For intance,
[Regex]
InFiles = (
::%%version%%=0.1.0 ## this will be applied to ALL frontend file found at frontend directory
:networking:%%version%%=0.1.0 ## this will only be applied to the frontend file named networking
)
Obviously, you can use any recognized identifier:
[Regex]
InFiles = ( :create_runtime:rundirectory=@R )
In this case, the @R
will be replaced by the $XDG_RUNTIME_DIR
of the user and so, the regex become e.g. for root :create_runtime:rundirectory=/run
and only applied to the frontend file named create_runtime
.
Configure script
This script must be named configure
and must be found at configure directory and must be executable. For instance, if you module directory is called boot
, the configure script must be placed at boot/configure/configure
.
This is the heart of the module.
Here i need to explain a little bit the flow of the parse process of a module.
When you do e.g. 66 parse boot@system
, the parser will execute the things in that order:
- It parse the frontend file of the module itself replacing any identifier found inside the frontend file.
- It apply the
[Regex]
section to the entire module directory.
- It execute the
configure
script.
- It parse all frontend service file found at activated directory.
So, the configure script is applied before parsing the frontend file of the module. That means that you can activate/deactivate, declare a dependency/requiredby of the module with the configure
script.
You can place at the configure directory any files that you want. The parser will only deal with the configure script and do not touch any others files present in that directory. It also can be written with any language (python maybe) as long as your define a correct shebang.
This script is executed with some well-known environment variable, see the 66 module creation documentation, section Environment variable passed to the script configure
, that you can use to help you for the configuration of the module.
Also, the script is executed with the environment variable coming from the [Environment]
section of the frontend file of the module. For instance, if your frontend file of the module itself declare:
[Environment]
Network=networmanager
Replaces=networking
the script will have Network=networkmanager
and Replaces=networking
on its environment variable.
As the [Environment]
section can be changed by the user (66 configure mymodule@name
), you can configure your module dynamically.
For example, if the user change Network=networmanager
by Network=connmand
, at reconfiguration time of the module (66 reconfigure mymodule@name
), the script will be executed with the corresponding environment variable define by the user (so Network=connmand
).
Now, inside your configure script, you can have something like this:
#!/bin/bash
## script variable
FRONTEND_PATH="${MOD_MODULE_DIR}/frontend"
ACTIVATED_PATH="${MOD_MODULE_DIR}/activated"
enable() {
name=${1}
66-yeller %benable%n service: "${name}"
touch "${ACTIVATED_PATH}/${name}"
}
if [ $Network == "connmand" ]; then
enable "connmand"
fi
Conclusion
Hope this little explanation will help you to understand how the module works. I understand that can be a little difficult to understand at first approach, but when you get the point, you will see that feature is very powerfull and flexible.
If you don't understand something, need more explanation or need help to build your own module don't hesitate to ask.
I saw your Alpine
package contributions. Many many (should i say MANY) thanks for that.
To be honest, the actual boot@
service is a little old and out to date. This service was one of the first service provided and need to be review to incorporate the new features of 66. I didn't want to change that service before reaching the stable stage of the frontend keywords, which is the case with the 0.8.0.0
version. So, a new boot@
service will be provided in the near future (certainly called boot2@) which will allow more flexibility to add or remove services.
Please, if you decide to remake a boot service module especially for Alpine
, please consider to make a copy (or original) here. This will help a lot to 66
to be recognized as a portable service manager.
I'm also very very interested to known if 66
work well compiled with musl. So, don't hesitate to open an issue at the 66 git if you encounter something weird.