如何在Linux上使用chroot命令
chroot命令可以将我们送入监狱,使开发或者测试环境保持隔离,或者只是提高系统的安全性。我们向我们展示最简单的使用方法。
什么是chroot?
如果尝试衡量命令的有用性,则必须考虑到该命令提供的功能及其易用性。如果对于人来说使用它太复杂或者太费力以致于他们不想尝试使用它,那么该功能可能也为零。如果没有人使用它,它将不提供任何功能。
在与Linux用户亲自讨论和在论坛上进行讨论时,似乎chroot命令是一个难于使用的命令,或者安装起来过于麻烦和乏味。看来这个实用工具并未得到应有的利用。
使用chroot
,我们可以在封装的文件系统中设置和运行程序或者交互式shell,例如Bash,以防止与常规文件系统进行交互。 chroot环境中的所有内容都被写入并包含其中。如果不升级到root特权,chroot
环境中的任何内容都无法超越它自己的特殊根目录。这使这种类型的环境赢得了" chroot"监狱的绰号。监狱一词不应与FreeBSD的" jail"命令混淆,后者创建的" chroot"环境比通常的" chroot"环境更安全。
但是实际上,有一种非常简单的方法可以使用" chroot",我们将逐步介绍。我们正在使用可在所有发行版上正常运行的常规Linux命令。一些Linux发行版具有专用的工具来设置" chroot"环境,例如Ubuntu的debootstrap,但是我们在这里与发行版无关。
什么时候应该使用chroot?
chroot环境提供的功能类似于虚拟机,但是解决方案更轻便。专属系统不需要安装和配置虚拟机监控程序,例如VirtualBox或者Virtual Machine Manager。也不需要在自备系统中安装内核。专属系统共享我们现有的内核。
从某种意义上说," chroot"环境比诸如虚拟机更靠近LXC之类的容器。它们重量轻,部署迅速,并且可以自动创建和启动。像容器一样,一种方便的配置方式是安装足够多的操作系统,以完成所需的操作。通过查看如何使用chroot环境,可以回答所需的问题。
一些常见的用途是:
软件开发和产品验证。开发人员编写软件,产品验证团队(PV)对其进行测试。有时PV发现的问题无法在开发人员的计算机上复制。开发人员在其开发计算机上安装了普通用户和PV不会拥有的各种工具和库。通常,适用于开发人员但不适用于其他开发人员的新软件原来使用的是开发人员PC上的资源,该资源未包含在该软件的测试版本中。chroot允许开发人员拥有纯原始的俘虏环境在他们的计算机上,他们可以先将软件浸入水中,然后再提供给PV。可以使用软件所需的最低限度依赖项来配置俘虏环境。
降低发展风险。开发人员可以创建一个专用的开发环境,以便其中发生的任何事情都不会破坏他的实际PC。
运行不推荐使用的软件。有时,我们只需要运行旧版本即可。如果旧软件的要求与Linux版本冲突或者不兼容,则可以为问题软件" chroot"一个环境。
恢复和文件系统升级:如果无法进行Linux安装,则可以使用chroot
将损坏的文件系统安装到Live CD上的安装点。这样,我们就可以在损坏的系统中工作,并尝试像在根目录/上正常安装一样对其进行修复。这意味着可以从根目录而不是从Live CD的挂载点正确引用损坏的系统中的预期文件路径。本文中使用了类似的技术来描述如何将Linux文件系统从ext2或者ext3迁移到分机4.
环网应用程序。在" chroot"环境中运行FTP服务器或者其他与Internet连接的设备会限制外部攻击者可能造成的损害。这是加强系统安全性的重要步骤。
创建一个chroot环境
我们需要一个目录作为chroot
环境的根目录。为了方便我们引用该目录,我们将创建一个变量并将目录名称存储其中。在这里,我们设置一个变量来存储testroot目录的路径。该目录是否存在并不重要,我们将很快创建它。如果目录确实存在,则应为空。
chr=/home/dave/testroot
如果该目录不存在,则需要创建它。我们可以使用此命令来做到这一点。 -p(parents)选项可确保同时创建所有丢失的父目录:
mkdir -p $chr
我们需要创建目录来保存我们的" chroot"环境所需的操作系统部分。我们将建立一个使用Bash作为交互式shell的极简主义Linux环境。我们还将包括" touch"," rm"和" ls"命令。这将使我们能够使用Bash的所有内置命令以及"触摸"," rm"和" ls"。我们将能够创建,列出和删除文件,并使用Bash。在这个简单的示例中就足够了。
列出我们需要在大括号扩展{{}中创建的目录。
mkdir -p $chr/{bin,lib,lib64}
现在,我们将目录更改为新的根目录。
cd $chr
让我们将极简Linux环境中所需的二进制文件从常规/ bin目录复制到我们的chroot
/ bin目录中。 -v(verbose)选项使cp在执行每个复制动作时告诉我们它在做什么。
cp -v /bin/{bash,touch,ls,rm} $chr/bin
这些文件将为我们复制:
这些二进制文件将具有依赖性。我们需要发现它们是什么并将这些文件也复制到我们的环境中,否则bash
,touch
,rm
和ls
将无法运行。我们需要依次为每个选择的命令执行此操作。我们将首先进行Bash。 ldd命令将为我们列出依赖项。
ldd /bin/bash
在终端窗口中标识并列出了依赖性:
我们需要将这些文件复制到我们的新环境中。从列表中挑选细节并一次复制一次将非常耗时且容易出错。
值得庆幸的是,我们可以将其半自动化,我们将再次列出依赖项,这次我们将形成一个列表。然后,我们将遍历复制文件的列表。
在这里,我们使用ldd列出依赖项,并将结果通过管道输入到egrep中。使用egrep
与使用带有-E
(扩展正则表达式)选项的grep
相同。 -o(仅匹配)选项将输出限制为行的匹配部分。我们正在寻找以数字[0-9]结尾的匹配库文件。
list="$(ldd /bin/bash | egrep -o '/lib.*\.[0-9]')"
我们可以使用echo
来检查列表的内容:
echo $list
现在有了列表,我们可以通过以下循环逐步遍历该列表,一次复制一个文件。我们正在使用变量" i"来逐步浏览列表。对于列表中的每个成员,我们将文件复制到chroot
根目录,该目录是$ chr
中保存的值。
-v(详细)选项使cp在执行每个副本时宣布每个副本。 --parents选项确保在chroot环境中创建所有丢失的父目录。
for i in $list; do cp -v --parents "$i" "${chr}"; done
这是输出:
我们将使用该技术来捕获其他每个命令的依赖性。我们将使用循环技术执行实际的复制。好消息是,我们只需要对收集依赖项的命令进行少量编辑即可。
我们可以通过几次按"向上箭头"键从命令历史记录中检索命令,然后进行编辑。循环复制命令根本不需要更改。
在这里,我们使用了向上箭头键来查找命令,并对其进行了编辑,使其显示为"触摸"而不是" bash"。
list="$(ldd /bin/touch | egrep -o '/lib.*\.[0-9]')"
现在,我们可以重复与之前完全相同的循环命令:
for i in $list; do cp -v --parents "$i" "${chr}"; done
并且为我们复制了文件:
现在,我们可以编辑ls的list命令行:
list="$(ldd /bin/ls | egrep -o '/lib.*\.[0-9]')"
同样,我们将使用相同的循环命令。不在乎列表中有哪些文件。它会盲目地处理列表,为我们复制文件。
for i in $list; do cp -v --parents "$i" "${chr}"; done
然后将ls
的依赖项复制给我们:
我们最后一次编辑list
命令行,使其适用于rm
:
list="$(ldd /bin/ls | egrep -o '/lib.*\.[0-9]')"
我们上一次使用循环复制命令:
for i in $list; do cp -v --parents "$i" "${chr}"; done
我们最后的依赖项被复制到我们的chroot
环境中。我们终于可以使用chroot
命令了。该命令设置chroot
环境的根目录,并指定将哪个应用程序作为shell运行。
sudo chroot $chr /bin/bash
我们的" chroot"环境现在处于活动状态。终端窗口提示已更改,并且交互式shell由我们环境中的bash
shell处理。
我们可以尝试引入环境中的命令。
ls
ls /home/dave/Documents
当在环境中使用时,ls
命令会按预期工作。当我们尝试访问环境外部的目录时,命令失败。
我们可以使用" touch"来创建文件,使用" ls"来列出文件,使用" rm"来删除文件。
touch sample_file.txt
ls
rm sample_file.txt
ls
当然,我们也可以使用Bash shell提供的内置命令。如果我们在命令行输入help
,Bash将为我们列出它们。
help
使用exit离开chroot环境:
exit
如果要删除chroot
环境,只需删除它即可:
rm -r testroot/
这将递归删除" chroot"环境中的文件和目录。