1

I'm making an update protocol for an embedded linux system, but I want to give users the option to roll back the update if it messes with their system, especially for alpha/beta releases. So I discovered the cp command option to make automatic backups of overwritten files.

This works great! But there has to be an easy way to roll back these changes with the automatic backup files right? I don't want to force users to go and find the backups of all the changed files themself.

Thanks in advance for the help!

7
  • Have you considered revision control tools: git, hg, svn, etc. Commented May 18, 2022 at 9:20
  • @ctrl-alt-delor Is that usable in this situation? I'm trying to deploy this update to multiple people across the world using this system. I thought these systems were more of a personal way of managing this kind of stuff?
    – owndampu
    Commented May 18, 2022 at 9:26
  • It could be done at many different levels: files, filesystem, block device (using LVM's snapshot features for example). etc etc. See also this implementation for (now Fedora) CoreOS: docs.fedoraproject.org/en-US/fedora-coreos/auto-updates -> ostreedev.github.io/ostree/introduction . I'm keeping "embedded" in mind.
    – A.B
    Commented May 18, 2022 at 9:36
  • I see no reason why not. You can give public access for read, or read to any one that has a key. Or you can use local repositories. Or both. Commented May 18, 2022 at 9:37
  • Can't your script just keep track of every file it copies, and then copy them all back?
    – terdon
    Commented May 18, 2022 at 9:37

1 Answer 1

0

If you have space to have two parallel filesystem trees, you could possibly have something like /bin and /bin.old. Repeat for all top-level directories.

Installation would be a case of creating /bin.new, copying from the live system, overlaying the new files, and then switching /bin to /bin.old and /bin.new to /bin`, etc. Rollback would be a switch back.

# Prepare a new filesystem tree
#
rm -rf /*.new /*.old
for item in /*
do
    cp -al "$item" "$item.new"     # Links avoid using too much disk space
done

# Overlay. Because we linked in the previous step, we must remove
# (or rename) each file that we're going to change. Do not change
# or replace any file in situ
#
# If you have space for two full filesystem trees you could just copy
# instead of linking, which could simplify this update code section.
#
echo installation code goes here

# Switch over
#
OPATH="$PATH" PATH="/bin.old:/bin:/bin.new:$PATH"

for item in /*.new
do
    live="${item%.new}"

    mv -f "$live" "$live.old"
    mv -f "$item" "$live"
done

# Post-installation steps (rebuild kernel links, etc.)
#
echo post-installation code goes here

You might want to have vital system binaries in a place that could not get updated, so that the rollback didn't get burned by a poor shell. However, that's a bit of a chicken and egg situation, where you then by definition cannot update this code. Tricky.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .