linux chroot命令詳解
chroot,即 change root directory (更改 root 目錄)。在 linux 系統(tǒng)中,系統(tǒng)默認(rèn)的目錄結(jié)構(gòu)都是以 /,即以根 (root) 開始的。而在使用 chroot 之后,系統(tǒng)的目錄結(jié)構(gòu)將以指定的位置作為 / 位置。
基本語法
chroot NEWROOT [COMMAND [ARG]...]
具體用法請(qǐng)參考本文的 demo。
為什么要使用 chroot 命令
增加了系統(tǒng)的安全性,限制了用戶的權(quán)力:
在經(jīng)過 chroot 之后,在新根下將訪問不到舊系統(tǒng)的根目錄結(jié)構(gòu)和文件,這樣就增強(qiáng)了系統(tǒng)的安全性。一般會(huì)在用戶登錄前應(yīng)用 chroot,把用戶的訪問能力控制在一定的范圍之內(nèi)。
建立一個(gè)與原系統(tǒng)隔離的系統(tǒng)目錄結(jié)構(gòu),方便用戶的開發(fā):
使用 chroot 后,系統(tǒng)讀取的是新根下的目錄和文件,這是一個(gè)與原系統(tǒng)根下文件不相關(guān)的目錄結(jié)構(gòu)。在這個(gè)新的環(huán)境中,可以用來測(cè)試軟件的靜態(tài)編譯以及一些與系統(tǒng)不相關(guān)的獨(dú)立開發(fā)。
切換系統(tǒng)的根目錄位置,引導(dǎo) Linux 系統(tǒng)啟動(dòng)以及急救系統(tǒng)等:
chroot 的作用就是切換系統(tǒng)的根位置,而這個(gè)作用最為明顯的是在系統(tǒng)初始引導(dǎo)磁盤的處理過程中使用,從初始 RAM 磁盤 (initrd) 切換系統(tǒng)的根位置并執(zhí)行真正的 init,本文的最后一個(gè) demo 會(huì)詳細(xì)的介紹這種用法。
通過 chroot 運(yùn)行 busybox 工具
busybox 包含了豐富的工具,我們可以把這些工具放置在一個(gè)目錄下,然后通過 chroot 構(gòu)造出一個(gè) mini 系統(tǒng)。簡(jiǎn)單起見我們直接使用 docker 的 busybox 鏡像打包的文件系統(tǒng)。先在當(dāng)前目錄下創(chuàng)建一個(gè)目錄 rootfs:
$ mkdir rootfs
然后把 busybox 鏡像中的文件釋放到這個(gè)目錄中:
$ (docker export $(docker create busybox) | tar -C rootfs -xvf -)
通過 ls 命令查看 rootfs 文件夾下的內(nèi)容:
$ ls rootfs
萬事俱備,讓我們開始吧!
執(zhí)行 chroot 后的 ls 命令
$ sudo chroot rootfs /bin/ls
雖然輸出結(jié)果與剛才執(zhí)行的 ls rootfs 命令形同,但是這次運(yùn)行的命令卻是 rootfs/bin/ls。
運(yùn)行 chroot 后的 pwd 命令
$ sudo chroot rootfs /bin/pwd
哈,pwd 命令真把 rootfs 目錄當(dāng)根目錄了!
不帶命令執(zhí)行 chroot
$ sudo chroot rootfs
這次出錯(cuò)了,因?yàn)檎也坏?/bin/bash。我們知道 busybox 中是不包含 bash 的,但是 chroot 命令為什么會(huì)找 bash 命令呢? 原來,如果不給 chroot 指定執(zhí)行的命令,默認(rèn)它會(huì)執(zhí)行 '${SHELL} -i',而我的系統(tǒng)中 ${SHELL} 為 /bin/bash。
既然 busybox 中沒有 bash,我們只好指定 /bin/sh 來執(zhí)行 shell 了。
$ sudo chroot rootfs /bin/sh
運(yùn)行 sh 是沒有問題的,并且我們打印出了當(dāng)前進(jìn)程的 PID。
檢查程序是否運(yùn)行在 chroot 環(huán)境下
雖然我們做了好幾個(gè)實(shí)驗(yàn),但是肯定會(huì)有朋友心存疑問,怎么能證明我們運(yùn)行的命令就是在 chroot 目錄后的路徑中呢?
其實(shí),我們可以通過 /proc 目錄下的文件檢查進(jìn)程的中的根目錄,比如我們可以通過下面的代碼檢查上面運(yùn)行的 /bin/sh 命令的根目錄(請(qǐng)?jiān)诹硗庖粋€(gè) shell 中執(zhí)行):
$ pid=$(pidof -s sh) $ sudo ls -ld /proc/$pid/root
輸出中的內(nèi)容明確的指出 PID 為 46644 的進(jìn)程的根目錄被映射到了 /tmp/rootfs 目錄。
通過代碼理解 chroot 命令
下面我們嘗試自己實(shí)現(xiàn)一個(gè) chroot 程序,代碼中涉及到兩個(gè)函數(shù),分別是 chroot() 函數(shù)和 chdir() 函數(shù),其實(shí)真正的 chroot 命令也是通過調(diào)用它們實(shí)現(xiàn)的:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> int main(int argc, char *argv[]) { if(argc<2){ printf("Usage: chroot NEWROOT [COMMAND...] \n"); return 1; } if(chroot(argv[1])) { perror("chroot"); return 1; } if(chdir("/")) { perror("chdir"); return 1; } if(argc == 2) { // hardcode /bin/sh for my busybox tools. argv[0] = (char *)"/bin/sh"; argv[1] = (char *) "-i"; argv[2] = NULL; } else { argv += 2; } execvp (argv[0], argv); printf("chroot: cannot run command `%s`\n", *argv); return 0; }
把上面的代碼保存到文件 mychroot.c 文件中,并執(zhí)行下面的命令進(jìn)行編譯:
$ gcc -Wall mychroot.c -o mychroot
mychroot 的用法和 chroot 基本相同:
$ sudo ./mychroot ./rootfs
特別之處是我們的 mychroot 在沒有傳遞命令的情況下執(zhí)行了 /bin/sh,原因當(dāng)然是為了支持我們的 busybox 工具集,筆者在代碼中 hardcode 了默認(rèn)的 shell:
argv[0] = (char *)"/bin/sh";
從代碼中我們也可以看到,實(shí)現(xiàn) chroot 命令的核心邏輯其實(shí)并不復(fù)雜。
實(shí)例:通過 chroot 重新設(shè)置 root 密碼
忘記了 root 密碼該怎么辦?接下來的 demo 將演示如何通過 chroot 命令重新設(shè)置 centos7 中被忘記了的 root 密碼。
systemd 的管理機(jī)制中,rescure 模式和 emeryency 模式是無法直接取得 root 權(quán)限的,需要使用 root 密碼才能進(jìn)入 rescure 和 emeryency 環(huán)境。所以我們需要通過其他方式來設(shè)置 root 密碼。我們可以為內(nèi)核的啟動(dòng)指定 "rd.break" 參數(shù),從而讓系統(tǒng)在啟動(dòng)的早期停下來,此時(shí)我們可以通過使用 root 權(quán)限并結(jié)合 chroot 命令完成設(shè)置 root 密碼的操作。下面我們一起來看具體的操作過程。
在系統(tǒng)啟動(dòng)過程中進(jìn)入開機(jī)菜單時(shí)按下字母鍵 e 進(jìn)程開機(jī)菜單的編輯模式:
這就是系統(tǒng)的開機(jī)菜單,按下 e 后進(jìn)入編輯界面:
找到以 "linux16 /vmlinuz-" 開頭的行。如果默認(rèn)沒有看到該行,需要按向下鍵把它滾動(dòng)出來。
然后定位到該行結(jié)尾處,輸入一個(gè)空格和字符串 "rd.break",如下圖所示:
接著按下 ctrl + x 以該設(shè)置繼續(xù)啟動(dòng),啟動(dòng)過程中操作系統(tǒng)會(huì)停下來,這是系統(tǒng)啟動(dòng)過程中的一個(gè)非常早的時(shí)間點(diǎn):
所以系統(tǒng)的根目錄還掛載在 RAM disk 上(就是內(nèi)存中的一個(gè)文件系統(tǒng)),我們可以通過 mount 命令檢查系統(tǒng)當(dāng)前掛載的文件系統(tǒng),下面是我們比較關(guān)心的兩條:
上圖中 mount 命令輸出的第一行說明此時(shí)的根目錄在一個(gè) RAM disk 中, 即 rootfs。
圖中輸出的第二行說明我們的文件系統(tǒng)此時(shí)被掛載到了 /sysroot 目錄,并且是只讀的模式:
而在我們正常登陸系統(tǒng)的情況下,系統(tǒng)根目錄的掛載情況如下:
該時(shí)間點(diǎn)的最大優(yōu)勢(shì)是我們具有 root 權(quán)限!所以讓我們開始設(shè)置新的 root 密碼吧。
先通過下面的命令把 /sysroot 重新掛載為可讀寫的模式:
switch_root:/# mount -o remount,rw /sysroot
然后用下面 chroot 命令把根目錄切換到我們?cè)瓉淼沫h(huán)境中:
switch_root:/# chroot /sysroot
此時(shí)可以理解為:我們以 root 權(quán)限登錄了原來的系統(tǒng),修改密碼就很容易了!用下面的命令為 root 用戶設(shè)置新的密碼:
sh-4.2# echo "new_root_pw" | passwd --stdin root
接下來還要處理 SELinux 相關(guān)的問題。由于當(dāng)前的環(huán)境中 SELinux 并未啟動(dòng),所以我們對(duì)文件的修改可能造成文件的 context 不正確。為了確保開機(jī)時(shí)重新設(shè)定 SELinux context,必須在根目錄下添加隱藏文件 .autorelabel:
sh-4.2# touch /.autorelabel
最后從 chroot 中退出,并重啟系統(tǒng):
sh-4.2# exit switch_root:/# reboot
重新進(jìn)入登陸界面時(shí)就可以使用剛才設(shè)置的密碼以 root 登陸了!
總結(jié)
chroot 是一個(gè)很有意思的命令,我們可以用它來簡(jiǎn)單的實(shí)現(xiàn)文件系統(tǒng)的隔離。但在一個(gè)容器技術(shù)繁榮的時(shí)代,用 chroot 來進(jìn)行資源的隔離實(shí)在是 low 了點(diǎn)。所以 chroot 的主要用途還是集中在系統(tǒng)救援、維護(hù)等一些特殊的場(chǎng)景中。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
linux里daily_routine實(shí)例代碼詳解
在本篇文章里小編給大家整理的是關(guān)于linux里daily_routine實(shí)例代碼以及相關(guān)知識(shí)點(diǎn)內(nèi)容,有需要的朋友們參考下。2019-09-09Ubuntu編譯內(nèi)核模塊,內(nèi)容體現(xiàn)系統(tǒng)日志中
大家好,本篇文章主要講的是Ubuntu編譯內(nèi)核模塊,內(nèi)容體現(xiàn)系統(tǒng)日志中,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12Linux系統(tǒng)使用用戶密鑰ssh主機(jī)訪問
這篇文章主要介紹了Linux系統(tǒng)使用用戶密鑰ssh主機(jī)訪問,它在安全上完全大于直接輸入root 的密碼,有需要的可以了解一下。2016-10-10linux C編程常見的錯(cuò)誤總結(jié)(必看篇)
下面小編就為大家?guī)硪黄猯inux C編程常見的錯(cuò)誤總結(jié)(必看篇)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-12-12對(duì)send(),recv()函數(shù)的全面理解
下面小編就為大家?guī)硪黄獙?duì)send(),recv()函數(shù)的全面理解。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-01-01Linux如何設(shè)置java.library.path
這篇文章主要介紹了Linux如何設(shè)置java.library.path問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12Linux中jar包啟動(dòng)和jar包后臺(tái)運(yùn)行的實(shí)現(xiàn)方式
這篇文章主要介紹了Linux中jar包啟動(dòng)和jar包后臺(tái)運(yùn)行的方式,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-08-08