[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Read-only /usr



So, apt has some support for doing updates on servers that mount /usr
read-only, in particular you can do:

	DPkg {
		// Auto re-mounting of a readonly /usr
		Pre-Invoke {"mount -o remount,rw /usr";};
		Post-Invoke {"mount -o remount,ro /usr";};
	}

However this doesn't work quite frequently, since the umount fails
if there's any file in /usr that's been deleted (ie, was in a package
which has been updated), but is still being used (a /usr/lib/lib* that's
referenced by a long running program, or a /usr/bin/* program that's still
running, like apt-get or dselect). This is because the filesystem will
be modified when the file is closed, because the inode will be freed,
so it's obviously not read-only.

That's the theory AIUI, anyway.

To avoid this, we want to ensure that files aren't ever deleted after the
apt-get has finished. One way to do this is to keep a filename pointing
at all the inodes that can't be deleted. Unfortunately dpkg doesn't have
any hooks to do this. Fortunately, dpkg does. Two scripts are attached
which do this.

Basically, one script is called after apt finishes downloading which
makes hard links for *all* files under /usr that'll be replaced over the
upcoming upgrade (keeping a note of all of them), and the other script
is called after every dpkg run, and, theoretically on reboot or similar,
which goes through that list and unlinks any files that it reasonably can.

You can probably add something like this to your /etc/apt/apt.conf:

	DPkg {
		// Auto re-mounting of a readonly /usr
		Pre-Install-Pkgs {"/home/aj/aptdpkgro.sh";};
		Pre-Invoke {"mount -o remount,rw /usr";};
		Post-Invoke {"/home/aj/aptdpkgclean.sh; mount -o remount,ro /usr";};
	}

It's a long way from ideal, but it should probably work. It's not
particularly well tested.

Cheers,
aj

-- 
Anthony Towns <aj@humbug.org.au> <http://azure.humbug.org.au/~aj/>
I don't speak for anyone save myself. GPG signed mail preferred.

 "Security here. Yes, maam. Yes. Groucho glasses. Yes, we're on it.
   C'mon, guys. Somebody gave an aardvark a nose-cut: somebody who
    can't deal with deconstructionist humor. Code Blue."
		-- Mike Hoye,
		      see http://azure.humbug.org.au/~aj/armadillos.txt
#!/bin/sh

pathmatch="^/usr"

while read debname; do
	pkg=$(dpkg --info $debname | sed -n 's/^ Package: *//p' | head -1)
	(dpkg -L "$pkg" 2>/dev/null || true) | grep "$pathmatch" |
	  while read file; do
		[ -f "$file" -a ! -L "$file" ] || continue
		dir=`dirname "$file"`;
		base=`basename "$file"`;
		inode=`find "$file" -printf "%i\n"`
		(cd "$dir" && ln "$base" ".${base}.dpkg-ro-used.$inode")
		echo "$dir/.${base}.dpkg-ro-used.$inode"
	  done >>/var/lib/my_ro_hack.todel
done
#!/bin/sh

pathmatch="^/usr"

cat /var/lib/my_ro_hack.todel | while read file; do
	[ -f "$file" ] || continue
	N1=`find "$file" -printf "%i\n"`

	b=`basename $file`; d=`dirname $file`
	XF="${b#.}"; XF="$d/${XF%.dpkg-ro-used.*}"
	N2=`find "$XF" -printf "%i\n"`

	if [ "$N1" != "$N2" ] && ! fuser -s "$file"; then
		rm -f "$file"
	else
		echo "$file"
	fi
done >/var/lib/my_ro_hack.todel.new
mv /var/lib/my_ro_hack.todel.new /var/lib/my_ro_hack.todel

Attachment: pgpAU9I8s9Pp7.pgp
Description: PGP signature


Reply to: