What is meant to happen with uci-defaults after a sysupgrade?

Ah I think I get it now. I'm in a different situation, I'm building for one specific device. I have my fork of OpenWrt, with out-of-tree kernel patches and some other little tweaks, and I'm already using Git branches for features, bugfixes, etc. I'm not sure how scripts/env would interact with that but I'll check it out.

This is getting O/T (only a bit, it does relate somewhat) BUT... I initially started off putting some of these customisations into files, but hit a number of problems:

  • Some customisations depend on packages. If I use a seed config (scripts/diffconfig), it just holds all direct and indirect packages and options rather than just the direct dependencies. Say my tweak depends on umdns — now I have to remember why every dependency of umdns is in my config. After a certain point it becomes easier to write a Makefile that just has +umdns in it and create a package.
  • Some customisations need special permissions or ownership. For example, say I want to follow the instructions to restrict SSH access. Both sudo config and SSH keys require very specific permissions on config files, which requires either a Makefile with a Package/.../install stanza or... a uci-defaults script to set them on boot.
  • More on adding an unprivileged user - this will require either manually crafting /etc/passwd files and other such things, or running the appropriate utils through uci-defaults scripts. The latter is almost always easier to me.

There were other things that tripped me up, but I can't remember them all now. Perhaps I should look into the scripts/env approach, although what exactly does it do if you're already working in Git? Does it commit a subdirectory with... it's own .git folder? Inside an existing Git repo? (Isn't that equivalent to a Git subtree?)

I wanted to use sysupgrade because if a device has accumulated config since its first clean boot, I want to preserve that. I don't get why a reboot after a sysupgrade call would be any different to a reboot after mtd -r -e firmware write image.bin firmware. Why would the former have race conditions, or a not-ready filesystem, when the latter never does? Even if I can't do much about it (and eg. have to move things into rc.local, which is fine) I would like to understand the problem.

Anyway, sorry for rambling on, my original question really was simply whether sysupgrade somehow held off on running the scripts or whether it was an issue with my images, and I'm grateful for the answer and extra tips here!

Oh, I almost forgot! The extra fun thing about a custom /etc/banner is that if you still want version information in there, you need to run $(VERSION_SED_SCRIPT) over it at some point. So if you just drop it in files/etc/banner, you'll still have the %D, %V etc. placeholders in there.

Your images, for sure. The scripts are run by /etc/init.d/boot and the internal filesystem is already mounted. I have been using this approach for a long time without a single issue ever. I use the image builder and add my scripts to files/etc/uci-defaults. I also disable the feature to preserve the config in LuCI, so my scripts always start with default config and build a functioning router, which decreases the number of permutations to support. An added benefit here for me is that anything that a user might have changed disappears and a working config is created.
You do need visibility into each script's output, though. Add these lines at the top of your script and you will get all the output into a file AND the script will stop at the first failure, which is also helpful for debugging:

set -e

exec >>/root/some_name.log 2>&1
3 Likes

I have one router with jffs2 and one with ubi: not a single issue on either, ever. Having said that, debugging without seeing the output is less than trivial, so that might be confusing the users.
Using uci-defaults is way superior to rc.local, because wifi, etc can call be configured before they start.

Not everyone wants to properly patch the sources and build their own firmware. If the image builder is used, then one will be overriting the config files and risk loosing new default params. With scripts, the new config is additive to what came in as default. This makes for more reliable setup.

1 Like

I've been using set -e but the exec trick is new to me, thanks!

My high level approach is as follows:

  1. Create multiple scripts and use ordering by name to make sure they run in a pre-determined order
  2. The first script would copy /etc/config to /root/ so that I have access to the reference config
  3. Make sure that all logs are empty after a reboot and all scripts are removed from uci-defaults

You might actually have to use $(basename $0) to get the script name only.

UPDATE: I fixed my post above with a proper command.

1 Like

Actually it seems whatever script it's in, it produces the file /root/rc.common.log. For now I've manually put a name in.

Right! Now I remember why I hardcoded it in all my scripts.

This literally made me laugh out loud, thanks for that.