软件包升级后无法将文件系统重新安装回只读状态


10

在我的Debian系统上,我/在单独的分区上并已挂载read-only。只有/home//var/并且/tmp/是可写的。我还创建了Pre-InvokePost-Invoke apt hook,以便apt可以在安装或升级软件包时自动重新挂载系统以进行写入,并read-only在完成后将其重新挂载回:

DPkg::Pre-Invoke  {"mount -o remount,rw / ;};
DPkg::Post-Invoke {"mount -o remount    / ;};

整个设置工作良好,但有一个例外。有时,在安装/升级过程中,某些服务需要重新启动,或者在/挂载my时在短窗口中打开新文件read-write,这些文件会获得write许可打开。安装/升级完成后,我的Post-Invoke挂钩返回错误,因为它无法重新安装/read-only

有什么办法可以解决这个问题?这很烦人,因为在这种情况下,我通常必须重新启动服务器,这是不切实际的。

编辑

以下是我最新软件包升级的日志,该日志导致了所描述的错误:

root@alpha# apt-get upgrade 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages will be upgraded:
  base-files curl libc-bin libc6 libcurl3 libcurl3-gnutls libmysqlclient18 libssl1.0.0 locales multiarch-support mysql-client mysql-client-5.5 mysql-common
  nscd openssl tzdata wget whois
18 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.
Need to get 18.7 MB of archives.
After this operation, 264 kB of additional disk space will be used.
Do you want to continue [Y/n]? 
Fetched 18.7 MB in 0s (33.2 MB/s) 
Preconfiguring packages ...
(Reading database ... 20532 files and directories currently installed.)
Preparing to replace base-files 7.1wheezy3 (using .../base-files_7.1wheezy4_amd64.deb) ...
Unpacking replacement base-files ...
Processing triggers for man-db ...
Processing triggers for install-info ...
Setting up base-files (7.1wheezy4) ...
Installing new version of config file /etc/debian_version ...
(Reading database ... 20532 files and directories currently installed.)
Preparing to replace libc-bin 2.13-38 (using .../libc-bin_2.13-38+deb7u1_amd64.deb) ...
Unpacking replacement libc-bin ...
Processing triggers for man-db ...
Setting up libc-bin (2.13-38+deb7u1) ...
(Reading database ... 20532 files and directories currently installed.)
Preparing to replace libc6:amd64 2.13-38 (using .../libc6_2.13-38+deb7u1_amd64.deb) ...
Unpacking replacement libc6:amd64 ...
Setting up libc6:amd64 (2.13-38+deb7u1) ...
(Reading database ... 20532 files and directories currently installed.)
Preparing to replace libssl1.0.0:amd64 1.0.1e-2+deb7u1 (using .../libssl1.0.0_1.0.1e-2+deb7u4_amd64.deb) ...
Unpacking replacement libssl1.0.0:amd64 ...
Preparing to replace curl 7.26.0-1+wheezy7 (using .../curl_7.26.0-1+wheezy8_amd64.deb) ...
Unpacking replacement curl ...
Preparing to replace libcurl3:amd64 7.26.0-1+wheezy7 (using .../libcurl3_7.26.0-1+wheezy8_amd64.deb) ...
Unpacking replacement libcurl3:amd64 ...
Preparing to replace libcurl3-gnutls:amd64 7.26.0-1+wheezy7 (using .../libcurl3-gnutls_7.26.0-1+wheezy8_amd64.deb) ...
Unpacking replacement libcurl3-gnutls:amd64 ...
Preparing to replace mysql-common 5.5.33+dfsg-0+wheezy1 (using .../mysql-common_5.5.35+dfsg-0+wheezy1_all.deb) ...
Unpacking replacement mysql-common ...
Preparing to replace libmysqlclient18:amd64 5.5.33+dfsg-0+wheezy1 (using .../libmysqlclient18_5.5.35+dfsg-0+wheezy1_amd64.deb) ...
Unpacking replacement libmysqlclient18:amd64 ...
Preparing to replace multiarch-support 2.13-38 (using .../multiarch-support_2.13-38+deb7u1_amd64.deb) ...
Unpacking replacement multiarch-support ...
Processing triggers for man-db ...
Setting up multiarch-support (2.13-38+deb7u1) ...
(Reading database ... 20532 files and directories currently installed.)
Preparing to replace tzdata 2013h-0wheezy1 (using .../tzdata_2013i-0wheezy1_all.deb) ...
Unpacking replacement tzdata ...
Setting up tzdata (2013i-0wheezy1) ...

Current default time zone: 'Europe/London'
Local time is now:      Sat Feb 15 11:35:41 CET 2014.
Universal Time is now:  Sat Feb 15 11:35:41 UTC 2014.
Run 'dpkg-reconfigure tzdata' if you wish to change it.

(Reading database ... 20511 files and directories currently installed.)
Preparing to replace wget 1.13.4-3 (using .../wget_1.13.4-3+deb7u1_amd64.deb) ...
Unpacking replacement wget ...
Preparing to replace locales 2.13-38 (using .../locales_2.13-38+deb7u1_all.deb) ...
Unpacking replacement locales ...
Preparing to replace whois 5.0.23 (using .../whois_5.1.1~deb7u1_amd64.deb) ...
Unpacking replacement whois ...
Preparing to replace mysql-client 5.5.33+dfsg-0+wheezy1 (using .../mysql-client_5.5.35+dfsg-0+wheezy1_all.deb) ...
Unpacking replacement mysql-client ...
Preparing to replace mysql-client-5.5 5.5.33+dfsg-0+wheezy1 (using .../mysql-client-5.5_5.5.35+dfsg-0+wheezy1_amd64.deb) ...
Unpacking replacement mysql-client-5.5 ...
Preparing to replace nscd 2.13-38 (using .../nscd_2.13-38+deb7u1_amd64.deb) ...
[ ok ] Stopping Name Service Cache Daemon: nscd.
Unpacking replacement nscd ...
Preparing to replace openssl 1.0.1e-2+deb7u1 (using .../openssl_1.0.1e-2+deb7u4_amd64.deb) ...
Unpacking replacement openssl ...
Processing triggers for install-info ...
Processing triggers for man-db ...
Setting up libssl1.0.0:amd64 (1.0.1e-2+deb7u4) ...
Setting up libcurl3:amd64 (7.26.0-1+wheezy8) ...
Setting up curl (7.26.0-1+wheezy8) ...
Setting up libcurl3-gnutls:amd64 (7.26.0-1+wheezy8) ...
Setting up mysql-common (5.5.35+dfsg-0+wheezy1) ...
Setting up libmysqlclient18:amd64 (5.5.35+dfsg-0+wheezy1) ...
Setting up wget (1.13.4-3+deb7u1) ...
Setting up locales (2.13-38+deb7u1) ...
Generating locales (this might take a while)...
  en_DK.UTF-8... done
  en_US.UTF-8... done
Generation complete.
Setting up whois (5.1.1~deb7u1) ...
Setting up mysql-client-5.5 (5.5.35+dfsg-0+wheezy1) ...
Setting up mysql-client (5.5.35+dfsg-0+wheezy1) ...
Setting up nscd (2.13-38+deb7u1) ...
[ ok ] Starting Name Service Cache Daemon: nscd.
Setting up openssl (1.0.1e-2+deb7u4) ...
mount: / is busy

最后一行(mount: / is busy)是apt尝试重新挂载/回时返回的错误read-only

更新:

建议的命令Graeme不显示任何文件:

# lsof / | awk 'NR==1 || $4~/[0-9][uw]/'
COMMAND     PID       USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME

您是否正在寻找一种方法来防止文件被打开read-write,或者必须重新启动服务器才能重新挂载ro或查找和更改阻止程序包?还是可以接受作为解决方案?
Anthon 2014年

理想情况下,我想防止文件rw首先被打开。但是任何可以使我ro无需重新启动即可重新安装的解决方案也都不错。
Martin Vegter 2014年

停止有问题的服务,重新安装,然后重新启动?
弗罗斯特沙茨2014年

@martin您是否已对违规服务进行了概述?我喜欢您介绍的设置,并会在VM中进行尝试,但是很高兴知道您没有在系统上运行非默认设置,这会使我的实验仅部分相关。
Anthon

@Anthon我不知道哪些是冒犯性的服务。但是请参阅上面的EDIT进行澄清。我的服务器也是VM。这是最小安装,仅运行少量服务。
Martin Vegter 2014年

Answers:


2

我的猜测是,这不仅是服务,还在于您在根文件系统中安装了其他文件系统,例如/ home和/ var。除此之外,这里概述了我能找到的最佳解决方案:

https://sites.google.com/site/linuxpendrive/rorootfs

查找标题为“ 如何在只读文件系统上安装/卸载软件包”的部分。简而言之,它涉及到重新挂载目标文件系统,然后在使用包管理器之前将其挂载到新的挂载中。

该建议是在其他答案之一中概述的,它假设将根文件系统重新装入rw以进行软件包更新时会发生什么,因此,如果Debian表现出的行为与假定的行为不同,则该解决方案可能实际上不适用于Debian。但是,我认为值得一试...


1

为了更确切地说,我们需要查看导致mount: / is busy错误的文件。您可以执行以下操作:

lsof / | awk 'NR==1 || $4~/[0-9][uw]/'

请参见我对OP另一个问题的回答-lsof:显示文件以读写方式打开 -有关此方面的警告。可能需要将其放入单独的脚本中,并将脚本放入apt挂钩中才能看到内容。

我怀疑/etc一旦服务启动,下的文件仍保持打开状态。某些程序/守护程序会动态更新其配置。NetworkManagercupsd是两个例子。更新cups造成cupsd扫描新的打印机(而不是一个dpkg配置脚本)可能是什么原因造成您的问题。我建议您/etc使用可写文件系统,即使它不是问题的根源。

另一种可能性是,当您尝试进行重新挂载时,文件系统缓冲区仍处于刷新到磁盘的过程中。我不确定mount这里的行为是什么,是在IO完成之前阻塞还是失败并报告磁盘繁忙。第一个似乎更可能,但我sync在输出中看不到任何调用strace(尽管可能是mount系统调用执行了此操作)。无论如何,sync如果lsof上面没有显示任何内容,则可能需要在重新安装之前执行,例如:

DPkg::Post-Invoke { "sync; mount -o remount /"; };

这很奇怪。您的lsof命令没有列出任何文件
马丁Vegter

1
有趣的是,另一件事是内存映射文件可以是写时复制的。我不知道这对安装有何影响,而且我不确定lsof,甚至不能证明这一点。您是否尝试过lsof用钩子跑步?那sync东西呢?
Graeme 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.