天天看点

Linux / Unix:chroot 命令实例讲解

一个刚接触 linux 和 unix 的新手。我该如何改变一个命令的根目录?我要怎样改变一个进程的根目录呢,比如用 chroot 命令将web服务与文件系统隔离?我要如何使用 chroot 恢复密码或修复基于 linux/unix的受损坏的环境?
Linux / Unix:chroot 命令实例讲解

在 linux和类 unix 系统下每一个进程/命令的当前工作目录称之为进程/命令的根目录(译注:译者以为此处有误,实际上没有进行过chroot的进程,其根目录是系统的根目录,而不是其工作目录)。你可以使用 chroot 命令改变一个命令的根目录,这最终将会改变当前运行的进程及其子进程的根目录。

如果一个进程/命令运行在一个不能访问外部根目录文件的已修改环境中。这种修改环境通常被称为"监禁目录"(jail)或是"chroot 监禁"。只有特权进程和根用户才能使用 chroot 命令。然而这通常是很有用的:

将特权分配给无特权的进程,例如 web 服务或 dns 服务。

建立测试环境。

不使程序或系统崩溃下,运行旧程序或 abi 兼容的程序。

系统恢复。

重新安装引导装载程序,例如 grub 或 lilo。

密码找回,重置一个已丢失的密码等。

<a target="_blank"></a>

chroot 命令 改变其当前目录,并将根目录变为指定目录,然后如果提供了命令则运行命令,也可以运行一个用户的交互式shell的副本(译注:即bash等。)。请注意并不是每一个程序都可以使用 chroot 命令。

基本语法如下:

chroot /path/to/new/root command

或者

chroot /path/to/new/root /path/to/server

chroot [options] /path/to/new/root /path/to/server

在这个例子中,建立了一个"迷你监狱"用来测试一个只有 ls 命令的 bash shell。首先用 mkdir 命令设定好 jail "监狱" 路径。

$ j=$home/jail

在 $j 内创建目录:

$ mkdir -p $j

$ mkdir -p $j/{bin,lib64,lib}

$ cd $j

$ cp -v /bin/{bash,ls} $j/bin

将所需库文件拷贝到$j。可以用 ldd 命令找到 bash 所依赖的共享库。

$ ldd /bin/bash

输出样例:

linux-vdso.so.1 =&gt; (0x00007fff8d987000)

libtinfo.so.5 =&gt; /lib64/libtinfo.so.5 (0x00000032f7a00000)

libdl.so.2 =&gt; /lib64/libdl.so.2 (0x00000032f6e00000)

libc.so.6 =&gt; /lib64/libc.so.6 (0x00000032f7200000)

/lib64/ld-linux-x86-64.so.2 (0x00000032f6a00000)

直接拷贝上面输出中的库文件到 $j 目录:

$ cp -v /lib64/libtinfo.so.5 /lib64/libdl.so.2 /lib64/libc.so.6 /lib64/ld-linux-x86-64.so.2 $j/lib64/

`/lib64/libtinfo.so.5' -&gt; `/home/vivek/jail/lib64/libtinfo.so.5'

`/lib64/libdl.so.2' -&gt; `/home/vivek/jail/lib64/libdl.so.2'

`/lib64/libc.so.6' -&gt; `/home/vivek/jail/lib64/libc.so.6'

`/lib64/ld-linux-x86-64.so.2' -&gt; `/home/vivek/jail/lib64/ld-linux-x86-64.so.2'

复制 ls 命令所需的库文件到 $j 目录下。用 ldd 命令打印出 ls 命令依赖的共享库:

$ ldd /bin/ls

linux-vdso.so.1 =&gt; (0x00007fff68dff000)

libselinux.so.1 =&gt; /lib64/libselinux.so.1 (0x00000032f8a00000)

librt.so.1 =&gt; /lib64/librt.so.1 (0x00000032f7a00000)

libcap.so.2 =&gt; /lib64/libcap.so.2 (0x00000032fda00000)

libacl.so.1 =&gt; /lib64/libacl.so.1 (0x00000032fbe00000)

libpthread.so.0 =&gt; /lib64/libpthread.so.0 (0x00000032f7600000)

libattr.so.1 =&gt; /lib64/libattr.so.1 (0x00000032f9600000)

list="$(ldd /bin/ls | egrep -o '/lib.*\.[0-9]')"

for i in $list; do cp -v "$i" "${j}${i}"; done

`/lib64/libselinux.so.1' -&gt; `/home/vivek/jail/lib64/libselinux.so.1'

`/lib64/librt.so.1' -&gt; `/home/vivek/jail/lib64/librt.so.1'

`/lib64/libcap.so.2' -&gt; `/home/vivek/jail/lib64/libcap.so.2'

`/lib64/libacl.so.1' -&gt; `/home/vivek/jail/lib64/libacl.so.1'

`/lib64/libpthread.so.0' -&gt; `/home/vivek/jail/lib64/libpthread.so.0'

`/lib64/libattr.so.1' -&gt; `/home/vivek/jail/lib64/libattr.so.1'

最后,chroot 到你的新jail:

$ sudo chroot $j /bin/bash

尝试浏览一下 /etc 或 /var:

# ls /

# ls /etc/

# ls /var/

改变了根目录的 bash 和 ls 程序现在被监禁在$home/$j这个特殊目录中,而且不能再访问外部的目录树,这个目录可以看做是它们的"/"(root)目录。如果配置正确的话,这会极大增强安全性。我通常用这种技术锁定以下的应用程序。

<a href="http://www.cyberciti.biz/tips/chroot-apache-under-rhel-fedora-centos-linux.html" target="_blank">apache - red hat / centos: chroot apache 2 web server</a>

<a href="http://www.cyberciti.biz/faq/howto-run-nginx-in-a-chroot-jail/" target="_blank">nginx - linux nginx: chroot (jail) setup</a>

<a href="http://www.cyberciti.biz/tips/howto-setup-lighttpd-php-mysql-chrooted-jail.html" target="_blank">chroot lighttpd web server on a linux based system</a>

chroot mail server.

chroot bind dns server 等等

键入 exit 即可

$ exit

上述会话样例如下:

Linux / Unix:chroot 命令实例讲解

animated gif 01: linux / unix: bash chroot ls command demo

gif 动画01: linux / unix: bash chroot ls 命令演示

你可以用下面两个命令[轻松的找出 postfix 邮件服务是否已经 chrooted]:

pid=$(pidof -s master)

ls -ld /proc/$pid/root

从基本linux服务中输出样例:

lrwxrwxrwx. 1 root root 0 mar 9 11:16 /proc/8613/root -&gt; /

pid 8613 指向了 / (root) 也就是说这个程序的根目录并没有被改变或是被 chroot。这个方法非常的快速而又直接,不需要打开配置文件。下面是从已经 chroot 的 ngnix 服务中得到的另一个例子:

lrwxrwxrwx 1 nginx nginx 0 mar 9 11:17 /proc/4233/root -&gt; /nginxjail

程序的根目录已经改为 /nginxjail。

## 在 live cd 的提示符下,键入以下命令来恢复数据。##

## /dev/sda1 系统主分区##

# 建立 jail 目录

d=/chroot

mkdir $d

# 挂载 sda1 和其他所需目录

mount /dev/sda1 $d

mount -o bind /dev $d/dev

mount -o bind /sys $d/sys

mount -o bind /dev/shm $d/dev/shm

mount -o bind /proc $d/proc

# 挂载软件raid /dev/md0

mount /dev/md0 $d/data

# chroot 到我们新建的 jail 中。这将允许我们修复引导装载系统(bootloader),或者在所有文件被/dev/null吞噬之前抓取数据。

chroot $d

#你能看见吗?

ls

df

# 将文件置入安全路径

rsync -avr /path/to/my_precious_data_dir [email protected]:/path/to/dest

# 退出 jail ,然后重启或者根据个人所需格式化服务 ;)

exit

umount {dev,sys,[...],}

reboot

别急,还有更精彩的内容!

查看nixcraft下所有其他有关 chroot 命令的文章:

<a href="http://www.cyberciti.biz/faq/ubuntu-mounting-your-encrypted-home-from-livecd/" target="_blank">ubuntu: mount encrypted home directory (~/.private) from an ubuntu live cd</a>

<a href="http://www.cyberciti.biz/tips/howto-linux-unix-rssh-chroot-jail-setup.html" target="_blank">linux configure rssh chroot jail to lock users to their home directories only</a>

<a href="http://www.cyberciti.biz/tips/howto-fix-dual-boot-windows-vista-linux.html" target="_blank">fix a dual boot ms-windows xp/vista/7/server and linux problem</a>

<a href="http://www.cyberciti.biz/tips/restore-debian-linux-grub-boot-loader.html" target="_blank">restore debian linux grub boot loader</a>

你应该在各种情况下都用 chroot 特性吗?从上面的例子看出,这个程序是相当简单的,但是最终可能出现几种不同的问题而结束,例如:

还要注意:

当你升级本地程序时,不要忘记升级已 chroot 的程序。

并非所有程序能够或者应该被 chroot。

任何需要 root 权限操作的程序,对其 chroot 是没意义的。因为通常 root 用户都能脱离 chroot。

--userspec=user:group 使用指定的 用户 和 组 (id 或 名称)

--groups=g_list 指定补充组 g1,g2,..,gn

--help 显示帮助并退出

--version 显示版本信息并退出

原文发布时间为:2014-05-19

本文来自云栖社区合作伙伴“linux中国”