Somewhatunderstandable technically, as enabled state is a symlink in /etc/rc.d, and how to restore the non-existence of a link? Well, there are methods of course, but this is probably the technical explanation why this is not working.
PS: I think a simple method would be instead of deleting the rc.d symlink, upon disable we could make the symlink to /dev/null, and simply add /etc/rc.d to the list of folders that are backed up.
Maybe as a safely, always enable certain essentials like network and dropbear upon restore.
Yes this is exactly the expected behavior for services. One reason for this could be that if user is restoring configuration it's not always the case that they have those programs/services installed. This is why it's better not to backup the services' states.
Even if a user has packages/services installed and it would be perfectly fine to restore the services' states then you have the option to do it manually through /etc/sysupgrade.conf. You can edit it and save whatever you think you need to save while saving configuration. So then when you create a backup it should save all those that you put in there along with other config.
If I for example disable build-in dnsmasq, then I really feel that should be part of the saved config. Starting dnsmasq on a device that is not supposed to could really cause trouble. And yes, I could also put in a safety by ignoring all interfaces in dnsmasq config, but please do not distract from the principle, the fact I disabled a build in package is part of the config.
And to be honest, even as to the enabled state of additional packages: So I may restore a /etc/rc.d/ that point to a non-existing package. I see no problem with that. The non-existing package will not run. Until I remember to install it, when it does run, which is exactly what I want.
If you aren't afraid of CLI, you can create a script to configure the system from zero including package and service management.
In that case you basically do not need to perform configuration backup.
@cybermaus You should know that OpenWrt is not limited to just one scenario. If services' states were to be saved, for instance, it can cause problems for those who are fairly new to the project. But anyways as I said before everyone has a different scenario to work with so if you want something done for your use-case, you have to make it work yourself.
You can also create a custom firmware and bake the configuration in there so it is part of the firmware and you would not need to do anything after that. Most of the users are happy with the configuration that gets deployed with it.
After using this method since 19.07, I found it failed to work going from 21.02 to 22.03. Instead, I'm now using the method recommended in the section Disable Daemons Persistently in the Wireless Access Point / Dumb Access Point guide.
Beginners may find it difficult to relate the facts from the formal documentation on the BSD rc.d framework with the practical tasks of rc.d scripting.In this article, we consider a few typical cases of increasing complexity, show rc.d features suited for each case, and discuss how they work.Such an examination should provide reference points for further study of the design and efficient application of rc.d.
The historical BSD had a monolithic startup script, /etc/rc.It was invoked by init(8) at system boot time and performed all userland tasks required for multi-user operation: checking and mounting file systems, setting up the network, starting daemons, and so on.The precise list of tasks was not the same in every system; admins needed to customize it.With few exceptions, /etc/rc had to be modified, and true hackers liked it.
Later there was an attempt to split out some parts of /etc/rc for the sake of starting the most important subsystems separately.The notorious example was /etc/netstart to bring up networking.It did allow for accessing the network from single-user mode, but it did not integrate well into the automatic startup process because parts of its code needed to interleave with actions essentially unrelated to networking.That was why /etc/netstart mutated into /etc/rc.network.The latter was no longer an ordinary script; it comprised of large, tangled sh(1) functions called from /etc/rc at different stages of system startup.However, as the startup tasks grew diverse and sophisticated, the "quasi-modular" approach became even more of a drag than the monolithic /etc/rc had been.
Without a clean and well-designed framework, the startup scripts had to bend over backwards to satisfy the needs of rapidly developing BSD-based operating systems.It became obvious at last that more steps are necessary on the way to a fine-grained and extensible rc system.Thus BSD rc.d was born.Its acknowledged fathers were Luke Mewburn and the NetBSD community.Later it was imported into FreeBSD.Its name refers to the location of system scripts for individual services, which is in /etc/rc.d.Soon we will learn about more components of the rc.d system and see how the individual scripts are invoked.
The basic ideas behind BSD rc.d are fine modularity and code reuse.Fine modularity means that each basic "service" such as a system daemon or primitive startup task gets its own sh(1) script able to start the service, stop it, reload it, check its status.A particular action is chosen by the command-line argument to the script.The /etc/rc script still drives system startup, but now it merely invokes the smaller scripts one by one with the start argument.It is easy to perform shutdown tasks as well by running the same set of scripts with the stop argument, which is done by /etc/rc.shutdown.Note how closely this follows the Unix way of having a set of small specialized tools, each fulfilling its task as well as possible.Code reuse means that common operations are implemented as sh(1) functions and collected in /etc/rc.subr.Now a typical script can be just a few lines' worth of sh(1) code.Finally, an important part of the rc.d framework is rcorder(8), which helps /etc/rc to run the small scripts orderly with respect to dependencies between them.It can help /etc/rc.shutdown, too, because the proper order for the shutdown sequence is opposite to that of startup.
The BSD rc.d design is described in the original article by Luke Mewburn, and the rc.d components are documented in great detail in the respective manual pages.However, it might not appear obvious to an rc.d newbie how to tie the numerous bits and pieces together to create a well-styled script for a particular task.Therefore this article will try a different approach to describe
rc.d.It will show which features should be used in a number of typical cases, and why.Note that this is not a how-to document because our aim is not at giving ready-made recipes, but at showing a few easy entrances into the rc.d realm.Neither is this article a replacement for the relevant manual pages.Do not hesitate to refer to them for more formal and complete documentation while reading this article.
There are prerequisites to understanding this article.First of all, you should be familiar with the sh(1) scripting language to master
rc.d.In addition, you should know how the system performs userland startup and shutdown tasks, which is described in rc(8).
This article focuses on the FreeBSD branch of rc.d.Nevertheless, it may be useful to NetBSD developers, too, because the two branches of BSD rc.d not only share the same design but also stay similar in their aspects visible to script authors.
To be properly managed by the rc.d framework, its scripts need to be written in the sh(1) language.If you have a service or port that uses a binary control utility or a startup routine written in another language, install that element in /usr/sbin (for the system) or /usr/local/sbin (for ports) and call it from a sh(1) script in the appropriate rc.d directory.
If you would like to learn the details of why rc.d scripts must be written in the sh(1) language, see how /etc/rc invokes them by means of run_rc_script, then study the implementation of run_rc_script in /etc/rc.subr.
Now it is the right time to choose a unique name for our script once and for all.We will use it in a number of places while developing the script.The content of the name variable needs to match the script name,some parts of FreeBSD (e.g., service jails and the cpuset feature of the rc framework) depend upon this.As such the filename shall also not contain characters which may be troublesome in scripting (e.g., do not use a hyphen "-" and others).
The current style of rc.d scripting is to enclose values assigned to variables in double quotes.Keep in mind that it is just a style issue that may not always be applicable.You can safely omit quotes from around simple words without sh(1) metacharacters in them, while in certain cases you will need single quotes to prevent any interpretation of the value by sh(1).A programmer should be able to tell the language syntax from style conventions and use both of them wisely.
Now let us add some controls to our dummy script.As you may know, rc.d scripts are controlled with rc.conf(5).Fortunately, rc.subr(8) hides all the complications from us.The following script uses rc.conf(5) via rc.subr(8) to see whether it is enabled in the first place, and to fetch a message to show at boot time.These two tasks in fact are independent.On the one hand, an rc.d script can just support enabling and disabling its service.On the other hand, a mandatory rc.d script can have configuration variables.We will do both things in the same script though:
While examining rc.d scripts, keep in mind that sh(1) defers the evaluation of expressions in a function until the latter is called.Therefore it is not an error to invoke load_rc_config as late as just before run_rc_command and still access rc.conf(5) variables from the method functions exported to run_rc_command.This is because the method functions are to be called by run_rc_command, which is invoked after load_rc_config.
3a8082e126