Linux 系统管理

作者:Mark Komarinski

最近在 Usenet 新闻组上有一些关于 Linux 是否需要(或缺少)undelete 命令的讨论。如果您错误地输入了 rm * tmp 而不是 rm *tmp,并且有这样一个命令可用,您可以快速恢复您的文件。

从文件系统的角度来看,这个想法的主要问题在于 DOS 处理文件系统的方式与 Linux 处理文件系统的方式之间的差异。

让我们看看 DOS 如何处理其文件系统。当 DOS 将文件写入硬盘驱动器(或软盘驱动器)时,它首先在文件分配表 (FAT) 中找到第一个标记为“空闲”的块。数据被写入该块,然后搜索并写入下一个空闲块,依此类推,直到文件完全写入。这种方法的问题在于文件可能分散在驱动器的各个块中。这种分散被称为 碎片,会严重降低文件系统的性能,因为现在硬盘驱动器必须在各处查找文件碎片。当文件被删除时,空间在 FAT 中被标记为“空闲”,这些块可以被另一个文件使用。

这样做的好处是,如果您删除的文件位于驱动器末端附近,则这些块中的数据可能几个月都不会被覆盖。在这种情况下,您很可能在之后相当长一段时间内能够恢复您的数据。

Linux(实际上,几乎普遍用于 Linux 的第二代扩展文件系统)在处理碎片方面稍微智能一些。它使用多种技术来减少碎片,包括将文件系统分段为独立管理的组,临时保留大块连续空间用于文件,以及从文件的当前末尾而不是从文件系统的开头开始搜索要添加到文件的新块。这大大减少了碎片,并使文件访问速度更快。唯一会发生严重碎片的情况是将大型文件写入几乎已满的文件系统时,因为文件系统可能剩下许多太小的空闲空间,无法很好地容纳文件。

由于这种查找文件空块的策略,当文件被删除时,它占用的(可能很大的)连续空间就成为写入新文件的可能位置。此外,由于 Linux 是一个多用户、多任务操作系统,文件创建活动通常比 DOS 下更多,这意味着那些曾经存放文件的空空间更可能被用于新文件。“可恢复性”已被权衡以换取一个非常快速的文件系统,该文件系统通常 永远 不需要碎片整理。

解决这个问题最简单的方法是在文件系统中添加一些内容来表明文件刚刚被删除,但是这种方法有四个问题

  1. 您需要编写一个新的文件系统或修改当前的文件系统(即,破解内核)。

  2. 文件应该被标记为“已删除”多久?

  3. 当硬盘驱动器被“已删除”的文件填满时会发生什么?

  4. 当文件必须在“已删除”空间周围写入时,会发生什么样的性能损失和碎片?

这些问题都可以回答并解决。如果您想这样做,请继续尝试——ext2 文件系统已预留空间来帮助您。但我有一些解决方案,不需要编写一行 C 源代码。

我有两个类似的解决方案,而您作为系统管理员的任务是确定哪种方法最适合您。第一种方法是用户级别的,不需要 root 权限的方法,另一种是由 root 实现的系统级方法,适用于所有(或几乎所有)用户。

用户级别的方法可以由任何具有 shell 访问权限的人完成,并且不需要 root 权限,只需要对您的 .profile.login.bashrc 文件进行一些更改,并占用少量驱动器空间。其思想是将 rm 命令别名为将文件移动到另一个目录。然后,当您下次登录时,这些移动的文件将使用真正的 /bin/rm 命令从文件系统中清除。由于文件实际上没有被用户删除,因此它们在下次登录之前仍然可以访问。如果您使用的是 bash shell,请将以下内容添加到您的 .bashrc 文件中

alias waste='/bin/rm'
alias rm='mv $1 ~/.rm'

并在您的

.profile:
if [ -x ~/.rm ];
 then
   /bin/rm -r ~/.rm
   mkdir ~/.rm
   chmod og-r ~/.rm
 else
   mkdir ~/.rm
   chmod og-r ~/.rm
 fi

优点

  • 可以由任何用户完成

  • 仅占用用户空间

  • /bin/rm 仍然可用作 waste 命令

  • 每次登录时自动删除旧文件。

缺点

  • 占用文件系统空间(如果您有配额,则不好)

  • 不易于一次为许多用户实施

  • 文件在每次登录时都会被删除(如果您同时登录两次,则不好)

系统级

第二种方法与用户级别的方法类似,但所有操作都在 /etc/profile 和 cron 条目中完成。/etc/profile 条目执行与上述几乎相同的工作,而 cron 条目每天晚上删除所有旧文件。另一个大的变化是,删除的文件在删除之前存储在 /tmp 中,因此这不会给对其主目录有配额的用户带来问题。

cron 守护进程(或 crond)是一个设置为在指定时间执行命令的程序。这些通常是频繁重复的任务,例如执行夜间备份或拨号到 SLIP 服务器以每半小时获取邮件。添加条目需要一些工作。这是因为用户有一个与之关联的 crontab 文件,其中列出了 crond 程序必须执行的任务。要获取 crond 已知的任务列表,请使用 crontab -l 命令,表示“列出当前 cron 任务”。要设置新的 cron 任务,您必须使用 crontab <file 命令,表示“从此文件读取 cron 分配”。如您所见,添加新 cron 任务的最佳方法是从 crontab -l 中获取列表,对其进行编辑以满足您的需求,然后使用 crontab <file 提交修改后的列表。它看起来像这样

~# crontab -l > cron.fil
~# vi cron.fil

要添加必要的 cron 条目,只需以 root 身份键入上述命令,然后转到 cron.fil 文件的末尾。添加以下行

# Automatically remove files from the
# /tmp/.rm directory that haven't been
# accessed in the last week.
0 0 * * * find /tmp/.rm -atime +7 -exec /bin/rm {} \;

然后键入

~# crontab cron.fil

当然,如果您想每天删除文件,可以将 -atime +7 更改为 -atime +1;这取决于您有多少空间以及您想给用户多少空间。

现在,在您的 /etc/profile 中(以 root 身份)

if [ -n "$BASH" == "" ] ;
then # we must be running bash
   alias waste='/bin/rm'
   alias rm='mv $1 /tmp/.rm/"$LOGIN"'
   undelete () {
     if [ -e /tmp/.rm/"$LOGIN"/$1 ] ; then
       cp /tmp/.rm/"$LOGIN"/$1 .
     else
       echo "$1 not available"
     fi
   }   if [ -n -e /tmp/.rm/"$LOGIN" ] ;
   then
     mkdir /tmp/.rm/"$LOGIN"
     chmod og-rwx /tmp/.rm/"$LOGIN"
   fi
fi

一旦您重启 cron 并且您的用户登录,您的新“undelete”功能就可以为所有运行 bash 的用户使用了。您可以为使用 csh、tcsh、ksh、zsh、pdksh 或您使用的任何其他 shell 的用户构建类似的机制。或者,如果您的所有用户都在其路径中将 /usr/bin 放在 /bin 之前,您可以创建一个名为 /usr/bin/rm 的 shell 脚本,它执行与上述别名基本相同的操作,并创建一个 undelete shell 脚本。这样做的好处是更容易进行完整的错误检查,而这里没有这样做。

优点

  • 一个更改影响所有(或大多数)用户

  • 文件保留时间比第一种方法更长

  • 不占用用户的文件空间

缺点

  • 一些用户可能不想要此功能

  • 可能会占用 /tmp 中大量空间,特别是当用户删除大量文件时

这些解决方案适用于简单使用。要求更高的用户可能需要更完整的解决方案,并且有很多方法可以实现这些解决方案。如果您实现了非常优雅的解决方案,请考虑将其打包以供通用使用,并给我发送一封电子邮件,以便我可以在这里告诉大家。

Tar 技巧

并且,作为对先前文章(特别是我在 LJ 第 5 期中关于 mtools 的文章)的最后一分钟更正/补充,一位细心的读者注意到,虽然 mtools 可以将 Unix 文件复制到 DOS 软盘,但如果 DOS 最多只能处理 11 个字符,并且不区分大小写,您如何保留原始 Unix 文件的 256 个字符的名称?这种情况是两台 Unix 机器可以使用 DOS 软盘,但无法直接通信。但是,这可以应用于您希望将文件存储在 DOS 软盘上的备份,或任何其他您希望保留长文件名的情況。有一种方法可以做到这一点。

tar 命令用于创建一个可以包含许多小文件的大文件。使用 tar 命令,您可以创建一个包含一堆 256 个字符的文件名的存档文件,而 tar 文件本身是合法的 DOS 名称。DOS(或 FAT 文件系统,无论如何)不关心文件中的内容,只要它最多有八个字符加上三个字符的扩展名。

确保在复制 tar 文件时,不要给 mtools 提供 -t(文本)选项。tar 文件必须以二进制格式复制,即使 tar 文件仅包含文本文件。

因此,要将一些长文件名复制到第一个软盘驱动器(A:/dev/fd0

tar -cvf file.tar longfilename \
reallylongfilename \ Not.In.Dos.Format.Filename.9999 /
mcopy file.tar a:

然后在远程 Unix 机器上(或恢复它)

mcopy a:file.tar file.tar
tar -xvf file.tar

mread a:file.tar | tar -xf -

并且假设远程 Unix 系统具有 mtools 并支持 256 个字符的文件名,文件的副本现在将在每个系统上。

下次请继续关注,我将找到虚拟啤酒、BogoMIPS 和 VIC-20 之间的真正关系。同时,请将您的评论或问题,甚至对未来文章的建议发送至:komarimf@ craft.camp.clarkson.edu。

Mark Komarinski (komarimf@craft.camp.clarkson.edu) 毕业于克拉克森大学(位于非常寒冷的纽约州波茨坦),获得计算机科学和技术传播学位。他现在居住在纽约州特洛伊,并在业余时间为退伍军人事务部工作,担任程序员。

加载 Disqus 评论