一个简洁实用的进入 Chroot 环境的脚本

之前在某处看到了这么一份用于进入 Chroot 环境的 Bash 脚本,感觉不错就收藏了。先贴一下原始脚本:

 1#!/bin/bash
 2
 3CHROOT_DIR=$(dirname $(readlink -f $0))
 4
 5USAGE="
 6Usage: sh $0 [option]
 7
 8Warning: This script cannot be used in compile_env
 9Options:
10    init        init compile_env and mount the required directories
11                no option default to init
12    umount      clean up compile_env
13    --help      Display help information.
14Example:
15    enter  compile_env: sh $0
16                        sh $0 init
17    umount compile_env: sh $0 umount
18"
19
20function fn_umount()
21{
22    i=0
23    while tac /proc/mounts | grep "${CHROOT_DIR}" &> /dev/null
24    do
25        while read line;
26        do
27            if echo $line | grep ${CHROOT_DIR} &> /dev/null; then
28                dir=$(echo $line | awk '{print $2}')
29                umount --lazy $dir
30            fi
31        done < /proc/mounts
32        ((i++))
33        if [ $i -ge 8 ]; then
34            break
35        fi
36    done
37}
38
39function fn_init()
40{
41    tac /proc/mounts | grep "${CHROOT_DIR}/dev" &> /dev/null
42    if [ $? -ne 0 ]; then
43        mount --bind /dev ${CHROOT_DIR}/dev/
44    fi
45    tac /proc/mounts | grep "${CHROOT_DIR}/sys" &> /dev/null
46    if [ $? -ne 0 ]; then
47        mount --bind /sys ${CHROOT_DIR}/sys
48    fi
49    tac /proc/mounts | grep "${CHROOT_DIR}/proc" &> /dev/null
50    if [ $? -ne 0 ]; then
51        mount --bind /proc ${CHROOT_DIR}/proc
52    fi
53    tac /proc/mounts | grep "${CHROOT_DIR}/dev/pts" &> /dev/null
54    if [ $? -ne 0 ]; then
55        mount -n -tdevpts -omode=0620,gid=5 none ${CHROOT_DIR}/dev/pts
56    fi
57
58    chroot ${CHROOT_DIR} /bin/bash --login
59}
60
61#--------------------main-------------------#
62if [ ${CHROOT_DIR} == "/" ]; then
63    echo -e "\033[31m\033[01m[ Warning: This script cannot be used in compile_env ]\033[0m"
64    printf "%s\\n" "$USAGE"
65    exit 1
66fi
67
68if [ $# -gt 1 ]; then
69    echo -e "\033[31m\033[01m[ missing params, please check it! ]\033[0m"
70    printf "%s\\n" "$USAGE"
71    exit 2
72fi
73
74if [ $# -eq 0 ] || [ $1 == "init" ]; then
75    fn_init
76    trap "sh ${CHROOT_DIR}/chroot.sh umount" EXIT
77    exit 0
78elif [ $1 == "umount" ]; then
79    fn_umount
80    exit 0
81else
82    printf "%s\\n" "$USAGE"
83    exit 3
84fi

下面就这个脚本中的一些内容做讲解。

  • umount--lazy 选项

    根据 man umount(8) 所述:

    1-l, --lazy
    2    Lazy unmount. Detach the filesystem from the file hierarchy
    3    now, and clean up all references to this filesystem as soon
    4    as it is not busy anymore.
    

    就是在对文件系统的引用还没有被全部解除的情况下,把文件系统移出文件目录树。这个 man 还给出了它的使用场景:避免系统的重启和关闭过程阻塞于网络文件系统(NFS)或一些本地文件系统无法被卸载。

    实际上使用 umount -l 还是有可能带来风险的,因为你不知道文件向设备的回写到底什么时候会完成,也没有东西可以指示你。比如你用 umount -l 卸载了一块硬盘,命令执行完成后你可能就拔硬盘了,但这个时候硬盘上的文件可能还没有 sync 完(其实你也没法知道到底 sync 完了没有),导致硬盘文件损坏。

    但是在此处问题应该不大,因为挂载的都是基于内存的文件系统或伪文件系统,不存在磁盘和内存不同步的问题。

  • tac:就是将 cat 输出的顺序取反。

  • trap 的含义

    这是一个 Bash 的内置命令(builtin),指定 Bash 在收到某个信号的时候要执行的函数。除信号外,还可以额外指定 EXIT(等同于 0)、DEBUGERR 等情况,其中 EXIT 是指 Bash 退出的时刻,即指定 Bash 退出时要执行的命令。更多细节可查 Bash Manual 4.1 节Bash Guide for Beginners 12.2 节

当然,这份代码还存在可改进之处。使用时根据实际情况调整即可。


Install & Explain SSL Certificates
【C++ 小问答】1:模板实例化