天天看點

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中國”