我想知道其他人对前向符号链接有何看法:它们安全吗?好的做法吗?依靠? [编辑] - 我没有定义前向符号链接,因为我离问题空间太近,看不到该术语可能没有被很好地理解。
由于合并 root 和 /usr 的尝试大多失败(我不知道有任何发行版(除了 cygwin,如果你将其算作发行版)已经摆脱了 bin、lib 和 lib64 两个单独的目录),发行版我主要使用的是OpenSUSE。他们实施合并的做法是将二进制文件安装在 /usr 中。由于许多 prog 都有许多程序的硬编码路径(/bin/ 可能是最常见的),因此安装包会放置一个来自 /bin/prog -> /usr/bin/prog 的符号链接。仅此一点并不是前向链接(尽管该术语可以定义为从上层目录到下层树的主管,但这在许多环境中显然不是问题。
在涉及安全性和可靠性的环境中,不同的树放置在不同的设备上,以 1) 优化备份和恢复时间以及备份空间。 2) 遏制擦除或损坏分区的问题 & 3) 禁止某些可能允许在攻击中使用硬链接文件和其他机制的安全攻击。与原因 1 相关,某些目录和子目录经常进行许多小更改 (/var)。有些不经常更改(/etc、/bin、/sbin)。有些可能会每天发生变化(/home)。将类似使用的目录分组到 1 个分区上可能会减少不经常更改的分区的备份,而经常更改的目录可能适合放置在 RAM 磁盘或 SSD 上。
然而,不同分区的原因与前向链接的实践是否安全或“最佳实践”(或不是)无关。更明确地说——在 /bin、/sbin 和 /lib64 中放置符号链接指向 /usr/{{s,}bin,lib64} 下的目录,如果“/usr”是一个单独的分区,那么我断言 /{{s,}bin,lib64/ 中的链接是“不安全的”,并且实际上是糟糕的管理实践,因为无论保存 /usr 的磁盘多么可靠,如果由于某种原因无法安装它们 - 那么您的二进制文件根目录 /{bin,sbin,lib64} 中的库链接是毫无价值的并会阻止系统启动。
我个人经历过三种情况 - “mount”的二进制文件位于 /usr/bin/mount 上,符号链接位于 /bin/mount 中,较新的安装程序已被重组为多个库,以及 /lib64 中的库的符号链接指向尚未安装的 /usr/lib64 以及最近的故障模式:将库版本号放入二进制文件和库中,以防止程序加载错误编号的 lib 版本。
通常,这样的搭配会奏效。主要问题是,在未安装配对目录之前,您不知道它们已嵌入版本号。在正常操作期间,根目录上的文件可以与 /usr/lib64 中的文件动态链接。如果 /usr 未挂载,它可能会尝试链接位于 /lib64 中的相同命名库,然后失败。最后一种情况是尝试通过将 /usr/lib64 中的同名库复制到 /lib64 来撤消根分区中到 /usr 的符号链接的副作用。不幸的是,当使用同一软件包的新版本进行更新时,新版本不会复制到根目录。如果 /usr/lib64 副本上的时间/日期戳比 /lib64 中的时间/日期戳更旧,则没有简单的方法可以捕获它。
链接器 util 'ldd' 显示具有基于文件名的版本的所需库,但不会立即了解嵌入式版本。所有这些额外的工作都是由于将挂载和引导其他文件系统所需的资源放置在尚未挂载的文件系统上而引起的。
我强烈认为,没有人指出这是不好的做法的一个原因是,要么没有人相信有人会实现如此容易失败的东西,要么只是相信新创建的原因,即它不是一个“错误”——将分区分开(最初由早期版本的 SuSE 安装程序设置)不再支持,就像不再支持直接从硬盘快速启动一样(尽管 systemd 开发人员建议加快启动时间)。
不幸的是,新的桌面开发人员无视以前的管理实践,同时没有将 /usr/bin 文件更安全地合并到 /bin,有些人给出的原因是 root 上可能没有足够的空间!
我无法找到任何不像 cygwin 那样合并它们的理由(它们只是挂载 /bin @ /usr/bin ——不涉及符号链接)。相反,我被告知停止争论并接受它,这似乎很像“接受”其他有问题的行为/事件的有点虐待狂的建议。
上一个结尾句子:“我是否过于保守,或者前向链接现在被认为属于关键文件的‘良好实践’领域?”
鉴于出现了新的失败方式,我不再考虑在这个问题上过于保守的可能性。我看不出有什么方法可以将其视为行政“最佳实践”。
答案1
争论的焦点是,弄清楚给定的二进制文件应该在哪里( / 或 /usr )是不必要的复杂化,没有任何意义。系统已经有一段时间无法在没有 /usr 的情况下启动,因此不再有理由保留两个目录。
看http://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge更多细节。
答案2
广泛(谨慎)使用符号链接的更好理由......
符号链接对于文件系统(一种分层数据库)的作用就像外键对于关系数据库的作用一样。
通过明智地使用“向前”和“向后”符号链接(尽管我以前没有听说过它们以这种方式提及),可以设计一个发行版,其中 /etc、/bin、/lib 和 /sbin 中的大多数内容都在到 /usr/etc、/usr/bin、/usr/lib 和 /usr/sbin 的符号链接。然后可能会在某个地方安装 /usr 目录的多个版本,例如 /initrd(初始化 ramdisk)下。然后,文件系统可以通过仔细创建和删除符号链接来管理在任何给定时间每个文件使用的版本。
小狗Linux和其他一些发行版使用联盟和奥夫斯文件系统来实现这个概念的变体。
分布式的原始操作系统作为“底层”在永久存储中保持静态(不变)。当编辑并保存其中一个文件(例如 /etc/hosts)时,文件系统不会更改原始文件,而是在 ramdisk 上最顶层的“工作层”中创建一个新副本。然后,文件系统向用户呈现此副本(而不是原始副本)。
ramdisk 副本会在后台定期(根用户可配置)刷新到第三层,该层也位于永久存储上。经过更改,ramdisk 副本有效地覆盖其保存的版本,而保存的版本又覆盖静态原始版本。只有最上面的副本是可见的(对于未更改的文件,这将是原始文件),因此文件系统对于用户和其他软件来说看起来完全典型。
该技术提高了系统速度和可靠性......
- 用户启动的文件读取和写入速度非常快,因为它们始终使用 ramdisk。
- 由于 ramdisk 层仅包含最近更改的文件,因此它保持很小并且功能与其他层类似缓存。
- 刷新到较慢的永久存储将推迟到后台处理。
- 可以定期制作“保存文件”第三层的副本,从而在配置或安装出错或检测到恶意程序时提供“撤消”功能。
符号链接使这一切成为可能。
问题的答案...
您的设置有多“高速”?
您可以为其提供的内存越多,虚拟磁盘中可以保存的程序就越多,因此响应速度就越快。从 ramdisk 启动程序比从闪存(闪存驱动器、SD 等)启动程序要快一些,并且只需要从硬盘驱动器启动相同程序所需时间的一小部分。
在我的 300MHz 1999 Toshiba 4030CDT 笔记本电脑上,配备 64MB RAM,Puppy Linux 5.2.2 Wary,主要基于 Slackware,没有足够的空间容纳太多 ramdisk,因此程序从硬盘驱动器加载。尽管如此,2D-GUI 的响应速度还是相当快的。我将它用作通过 Synergy 连接到所有其他主机的“控制台”。
而另一方面,我现在使用的是(通过笔记本电脑)... Compaq S6010V,运行 2.6GHz Celeron 处理器和 1.3GB RAM。ramdisk“PuppySpace”分配了 512MB,其中目前使用量不到 200MB。加载了 Zim(一款 Python 笔记应用程序)、Geany 编辑器/IDE、一个打开了 5 个会话的终端客户端和 2 个 Chromium 副本,总共有 12 个活动网页选项卡,包括 Gmail。
它通常会保持多长时间?
由于我不断开发和更改配置,因此计划重新启动很常见。康柏的正常运行时间输出目前...
16:21:10 up 4 days, 7:28, load average: 0.06, 0.24, 0.30
用户可以轻松地从 kernel.org 编译自己的内核并用它启动吗?
我无法解决这个问题,因为我从未这样做过。尽管 Puppy Linux 社区充满了编译自己的内核作为早餐的人。
这是你运行服务器的东西吗?
我的所有系统都运行 JWM 或 Openbox 窗口管理器(基于 GTK+),但已经完成了一些工作,将 Puppy 设置为服务器LEMP和简化的音乐服务器点唱机 (mpdPup)。
奥夫斯? ……它有什么用呢? (通过 xfs/ext.
Aufs 是 unionfs 的完全重写。他们都实现了联合安装其中多个文件系统(如 xfs、ext3/4 等)安装到同一安装点,以便它们相互覆盖。
答案3
现在最好不要/usr
再创建单独的分区。这样就根本不需要符号链接了。
至少,这是我在我的发行版中出现二进制文件移动问题后做出的决定。将所有二进制文件和库放在同一分区上实际上对我来说很有意义。那么哪些在 中/bin
、哪些在 中并不重要/usr/bin
,并且它们可以随意移动。
/usr
我最初有一个单独的唯一原因是我只是为所有东西做了一个分区;有了LVM,就很容易做到。但除此之外,没有任何实际原因。为了分离而分离。
如果您对所有内容都有一个分区,那么您的根/
分区将几乎完全是空的。就我而言,它不到 200MB。所以我将它与/usr
分区合并,并释放了根分区之前无用地浪费的空间。到目前为止我还没有发现任何缺点。
救援系统的合并过程:(使用风险自负 - 可能会破坏您的系统)
mkdir /mnt/root /mnt/usr
mount /dev/lvm/root /mnt/root
mount /dev/lvm/usr /mnt/usr
# /usr will be mounted as /, so move everything into a new usr/ subdirectory
mkdir /mnt/usr/usr
mv /mnt/usr/* /mnt/usr/usr/
# copy the root files, preserving hard links just in case
rsync -aH /mnt/root/. /mnt/usr/.
# update fstab: comment /usr, change UUID of / to the one of /usr
nano /mnt/usr/etc/fstab
umount /mnt/root
umount /mnt/usr
lvrename lvm/root lvm/oldroot
lvrename lvm/usr lvm/root
# chroot to see if it works and update grub UUID
mount /dev/lvm/root /mnt/root
mount -o bind /dev /mnt/root/dev
mount -o bind /proc /mnt/root/proc
mount -o bind /sys /mnt/root/sys
chroot /mnt/root /bin/bash
update-grub # may depend on distro/bootloader