从零开始构建Linux并提供WEB服务

  • 所使用的工具版本

  • linux-5.8.9 busybox-1.32.0 grub2 Centos8

    #下载Linux内核和busybox
    #linux内核
    wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.8.9.tar.xz
    #常用命令工具集
    wget https://busybox.net/downloads/busybox-1.32.0.tar.bz2
    #实现ssh远程登录工具
    wget https://matt.ucc.asn.au/dropbear/dropbear-2020.81.tar.bz2
    #提供web服务
    wget http://nginx.org/download/nginx-1.19.9.tar.gz
    
  • 系统环境

    vmware内安装Centos8,连接2块磁盘(sda、sdb(40G))

  • 磁盘分区(fdisk /dev/sdb)

    1. 使用o命令清除分区信息,使用n命令分两个区,200M+4G+剩余空间,200M用于boot分区,4G用于交换分区,剩余空间自己使用;
    2. 使用a命令设置1分区为活动分区
    3. 使用t命令设置2分区为82交换分区
    4. 使用w命令保存并退出
    #列出当前磁盘
    fdisk -l
    
    #使用fdisk /dev/sdb进入fdisk界面
    fdisk /dev/sdb
    
    #按照以下操作进行磁盘分区(红色字是需输入的命令)
    [root@208 ~]# **fdisk /dev/sdb**
    
    欢迎使用 fdisk (util-linux 2.32.1)。
    更改将停留在内存中,直到您决定将更改写入磁盘。
    使用写入命令前请三思。
    
    命令(输入 m 获取帮助):**o**
    创建了一个磁盘标识符为 0xa1537ea2 的新 DOS 磁盘标签。
    
    命令(输入 m 获取帮助):**n**
    分区类型
       p   主分区 (0个主分区,0个扩展分区,4空闲)
       e   扩展分区 (逻辑分区容器)
    选择 (默认 p):
    
    将使用默认回应 p。
    分区号 (1-4, 默认  1): 
    第一个扇区 (2048-83886079, 默认 2048): 
    上个扇区,+sectors 或 +size{K,M,G,T,P} (2048-83886079, 默认 83886079): **+200M**
    
    创建了一个新分区 1,类型为“Linux”,大小为 200 MiB。
    
    命令(输入 m 获取帮助):**n**
    分区类型
       p   主分区 (1个主分区,0个扩展分区,3空闲)
       e   扩展分区 (逻辑分区容器)
    选择 (默认 p):
    
    将使用默认回应 p。
    分区号 (2-4, 默认  2): 
    第一个扇区 (411648-83886079, 默认 411648): 
    上个扇区,+sectors 或 +size{K,M,G,T,P} (411648-83886079, 默认 83886079): **+4G**
    
    创建了一个新分区 2,类型为“Linux”,大小为 4 GiB。
    
    命令(输入 m 获取帮助):**n**
    分区类型
       p   主分区 (2个主分区,0个扩展分区,2空闲)
       e   扩展分区 (逻辑分区容器)
    选择 (默认 p):
    
    将使用默认回应 p。
    分区号 (3,4, 默认  3): 
    第一个扇区 (8800256-83886079, 默认 8800256): 
    上个扇区,+sectors 或 +size{K,M,G,T,P} (8800256-83886079, 默认 83886079): 
    
    创建了一个新分区 3,类型为“Linux”,大小为 35.8 GiB。
    
    命令(输入 m 获取帮助):**a**
    分区号 (1-3, 默认  3): **1**
    
    分区 1 的 可启动 标志已启用。
    
    命令(输入 m 获取帮助):**t**
    分区号 (1-3, 默认  3): **2**
    Hex 代码(输入 L 列出所有代码):**82**
    
    已将分区“Linux”的类型更改为“Linux swap / Solaris”。
    
    命令(输入 m 获取帮助):**w**
    分区表已调整。
    将调用 ioctl() 来重新读分区表。
    正在同步磁盘。
    
  • 格式化磁盘

    mkfs.ext3 /dev/sdb1
    mkfs.ext4 /dev/sdb3
    
  • 挂载磁盘

    #临时根文件系统
    mkdir /mnt/rootfs
    mount /dev/sdb1 /mnt/rootfs
    
    #真实根文件系统
    mkdir /mnt/root
    mount /dev/sdb3 /mnt/root
    
    #可以修改主机配置文件实现开机自动挂载(在最后添加两行)
    vim /etc/fstab
    /dev/sdb3 /mnt/root
    /dev/sdb1 /mnt/rootfs
    
  • 编译kernel

    将下载好的kernel解压,使用tar -xvf ./linux-5.8.9.tar.xz;然后进入到kernel目录cd linux-5.8.9,下面开始编译

    tar -xf linux-5.8.9.tar.xz
    cd linux-5.8.9
    
    make x86_64_defconfig
    make menuconfig
    
    #调整编译参数
    (1)General setup  ---> 
    **[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support**  
    (2)Device Drivers  --->
    **[*] Block devices  --->**
    **<*>   RAM block device support**
    **(16)**   Default number of RAM disks 
    **(8196)** Default RAM disk size (kbytes)
    (3)
    File systems  --->
    **<*> Second extended fs support
    <*> The Extended 3 (ext3) filesystem**
    
    #编译
    make
    
    #复制编译好后的文件
    cp arch/x86/boot/bzImage /mnt/rootfs/vmlinux
    
  • 制作文件系统

    • 常用命令通过busybox编译得到

      tar -xf busybox-1.32.0.tar.bz2
      cd busybox-1.32.0
      
      make menuconfig
      
      #调整编译参数
      Settings  --->
      --- Build Options                                                                                           **[*] Build static binary (no shared libs)**
      
      #编译
      make
      
    • 补充其他需要的文件

      1.在电脑上创建一个目录用来制作initrd文件系统,mkdir homeDir

      2.将busybox生成的_install目录下的所有内容拷贝到homeDIr目录

      3.注意将homeDIr中的linuxrc改名为init

      mkdir homeDir
      cd homeDir
      cp -ra ../busybox-1.32.0/_install/* .
      mv linuxrc init
      #创建其他目录
      mkdir -p etc/init.d/
      

      4.在homeDir目录中的etc目录下创建inittab文件

      vim etc/inittab
      
      ::sysinit:/etc/init.d/rcS
      ::respawn:-/bin/sh
      ::askfirst:-/bin/sh
      ::ctrlaltdel:reboot
      ::shutdown:/etc/init.d/shutdown.sh
      

      5.在homeDir/etc/init.d/目录下创建rcS文件

      vim etc/init.d/rcS
      
      #!/bin/sh
      /bin/mount -a
      mkdir -p /dev/pts
      mount -t devpts devpts /dev/pts
      echo /sbin/mdev > /proc/sys/kernel/hotplug
      mdev -s
      

      6.在homeDir目录下创建一个脚本,用来生成initrd文件

      vim make.sh
      
      #!/bin/sh
      rootDir=**/opt/l/tmp**
      rm -rf $rootDir/initrd
      find .|cpio -o -H newc |gzip -9 > $rootDir/initrd
      echo “create initrd successed !!”
      
      #授权并执行
      chmod +x make.sh
      ./make.sh
      

      7.将生成initrd文件拷贝到u盘的boot分区根目录下。

      cp /opt/l/tmp/initrd /mnt/rootfs/
      
  • 安装grub

    grub2-install --root-directory=/mnt/rootfs /dev/sdb
    
    • 创建grub配置文件

      vim /mnt/rootfs/boot/grub2/grub.cfg
      
      set timeout=3
      menuentry 'LysLinux' --class ubuntu --class gnu-linux --class gnu {
      insmod gzio
      insmod ext2
      search --no-floppy --fs-uuid --set=root 1cd9d71c-9b15-493d-8baf-a7a8e9f28ee1
      linux /vmlinux
      initrd /initrd
      }
      

      其中uuid查看方法是使用blkid命令找到对应的启动分区的编号。

      **blkid**
      /dev/sda1: UUID="b604d651-9480-4812-bb3d-08db7239c383" TYPE="ext4" PARTUUID="e8af0437-01"
      /dev/sda2: UUID="2468fX-QKtT-UKi7-2FIF-0yYI-9yuI-gSIcFz" TYPE="LVM2_member" PARTUUID="e8af0437-02"
      /dev/sdb1: UUID="**1cd9d71c-9b15-493d-8baf-a7a8e9f28ee1**" TYPE="ext3" PARTUUID="a1537ea2-01"
      /dev/sdb2: PARTUUID="a1537ea2-02"
      /dev/sdb3: UUID="97c6c7b1-79a0-455e-894c-c9352b12e4fa" SEC_TYPE="ext2" TYPE="ext3" PARTUUID="a1537ea2-03"
      /dev/sr0: UUID="2020-01-03-21-42-40-00" LABEL="CentOS-8-1-1911-x86_64-dvd" TYPE="iso9660" PTUUID="087a73cc" PTTYPE="dos"
      /dev/mapper/cl-root: UUID="1e55f550-4105-43f2-b075-653afda997be" TYPE="xfs"
      /dev/mapper/cl-swap: UUID="f96b1f9f-1fb4-4222-90c2-d55bbb1f49e4" TYPE="swap"
      
  • 同步磁盘数据并关闭主机

    sync
    sync
    sync
    poweroff
    
  • 新建虚拟机挂载新磁盘并启动

    挂载磁盘时,选择IDE磁盘,否则进入系统后可能认不到磁盘

     

     

  • 切换到真正根文件系统

    关闭子系统,启动主机系统

    上面系统启动后,linux回运行到内存中,所有修改均不能生效,需要将文件系统切换到真实的根目录下

    1. 建立真正根文件目录

      cd /mnt/root
      
      #创建相关文件,删除无用文件
      mkdir -p dev etc lib mnt/sysroot proc sys root
      rm linuxrc
      
      #拷贝基本文件
      cp -R /opt/l/busybox-1.32.0/_install/* .
      
      #拷贝配置文件(使用busybox自带的示例配置,上面建立虚拟根文件系统也可以采用这种方式)
      cp -R /opt/l/busybox-1.32.0/examples/bootfloppy/etc/* etc/
      
    2. 修改下fstab和rcS,使用fstab添加sysfs的挂载,使用rcS自动创建设备结点

      vim etc/fstab
      
      proc		/proc	proc	defaults    0	0
      sysfs		/sys	sysfs	defaults    0 0
      
    3. 修改rcS

      vim etc/init.d/rcS
      
      #!/bin/sh
      
      /bin/mount -a
      mdev -s
      
    4. 进入到homeDIr目录,重建init文件

      cd homeDIr
      rm init
      vim init
      
      #!/bin/sh
      #
      echo "exec initramfs init"
      echo "mounting proc and sys"
      
      mount -t proc proc /proc
      mount -t sysfs sysfs /sys
      
      echo "detect and export hardware info"
      mdev -s
      
      #echo "start /bin/sh"
      #exec /bin/sh
      
      echo "Mount real rootfs to /mnt/sysroot..."
      mount -t ext4 /dev/sda3 /mnt/sysroot
      
      echo "Switch to read rootfs..."
      exec switch_root /mnt/sysroot /sbin/init
      
    5. 关闭主系统,启动子系统

      sync
      sync
      sync
      poweroff
      

      此时应该可以进入真实的根文件目录,所有文件修改都会生效,重启后依然保留

       

  • 支持ssh登录

    关闭子系统,启动主机系统

    以下操作都是在真实根目录下进行(/mnt/root)

    1. 支持本地登录

      1. 创建用户数据库文件:passwd,密码影子文件:shadow,用户组文件:group

        #创建用户数据库文件:passwd,密码影子文件:shadow,用户组文件:group
        
        vim /mnt/root/etc/passwd
        root:x:0:0:root:/root:/bin/bash
        
        #生成用户密码
        openssl passwd -1 -salt `openssl rand -hex 4`
        Password: 
        **$1$c4a375d4$e53cXyHuwv4E3O.MI07de0**
        
        vim /mnt/root/etc/shadow
        root:**$1$c4a375d4$e53cXyHuwv4E3O.MI07de0**:16690:0:99999:7:::
        
        #修改文件权限
        chmod go= /mnt/root/etc/shadow
        
        vim /mnt/root/etc/group            
        root:x:0:
        
        vim /mnt/root/etc/sysconfig/network    #设置主机名
        HOSTNAME=www
        
      2. 修改启动配置

        #修改启动配置,如果放开 # ::respawn:-/bin/sh 则不需要登录直接进入系统
        vim /mnt/root/etc/inittab             
        
        ::sysinit:/etc/init.d/rcS
        # ::respawn:-/bin/sh
        ::respawn:/sbin/getty 19200 tty1
        ::respawn:/sbin/getty 19200 tty2
        ::respawn:/sbin/getty 19200 tty3
        ::respawn:/sbin/getty 19200 tty4
        ::respawn:/sbin/getty 19200 tty5
        ::respawn:/sbin/getty 19200 tty6
        ::ctrlaltdel:/bin/reboot
        ::shutdown:/bin/umount -a -r
        
        #修改启动配置rcS
        vim /mnt/root/etc/init.d/rcS
        
        #!/bin/sh  
        /bin/mount -a
        mdev -s
        mkdir /dev/pts
        ifconfig lo 127.0.0.1
        ifconfig eth0 192.168.1.210
        
        [ -r /etc/sysconfig/network ] && source /etc/sysconfig/network
        [ -z "$HOSTNAME" -o "$HOSTNAME" == '(none)' ] && hostname localhost || hostname $HOSTNAME
        
      3. 挂起主机,启动子虚拟机

        sync
        sync
        sync
        poweroff
        

        第1个tty1无法登录,我们需要切换其他tty登录,一般等待60秒超时后再次登录即可,或者按ctrl+c

         

    2. 在主机中编译安装dropbear

      dropbear用于实现ssh远程登录服务

      # 使用前面下载的 dropbear-2020.81.tar.bz2
      tar xf dropbear-2020.81.tar.bz2
      cd dropbear-2020.81
      ./configure
      make PROGRAMS="dropbear dbclient dropbearkey scp"
      make PROGRAMS="dropbear dbclient dropbearkey scp" install
      
      #生成dropbear密钥文件
      mkdir /etc/dropbear
      #生成私钥信息
      dropbearkey -t dss -f /etc/dropbear/dropbear_dss_host_key  
      #生成公钥信息
      dropbearkey -t rsa -s 2048 -f /etc/dropbear/dropbear_rsa_host_key
      
      #在主机中启动dropbear用于测试
      dropbear -p 22022 -F -E        #开启程序然后在前台监测运行信息
      
      #在开启一个会话查看22022端口是否监听
      netstat -ltnp
      
    3. 移植dropbear至子主机

      1. 创建脚本复制程序命令脚本,用于复制命令至子系统中

        # ./bincp.sh             #这是一个脚本程序,这个程序的功能是复制可执行程序同时也会复制依赖
        # Enter a command: bash    #bash的库
        # Enter a command: quit    #这里表示移植bash程序。busybox里面是没有bash的但是兼容bash
        #默认支持的是ash,所以bash还是要移植的。
        
        vim bincp.sh
        
        #!/bin/bash
        #
        target=/mnt/root
        
        clearCmd() {
          if which $cmd &> /dev/null; then
                cmdPath=`which --skip-alias $cmd`
          else
                echo "No such command"
                return 5
          fi
        }
        
        cmdCopy() {
                cmdDir=`dirname $1`
                [ -d ${target}${cmdDir} ] || mkdir -p ${target}${cmdDir}
                [ -f ${target}${1} ] || cp $1 ${target}${cmdDir}
        }
        
        libCopy() {
                for lib in `ldd $1 | grep -o "/[^[:space:]]\\{1,\\}"`; do
                        libDir=`dirname $lib`
                        [ -d ${target}${libDir} ] || mkdir -p ${target}${libDir}
                        [ -f ${target}${lib} ] || cp $lib ${target}${libDir}
                done
        }
        
        while true; do
          read -p "Enter a command: " cmd
          if [ "$cmd" == 'quit' ] ;then
                echo "quit"
                exit 0
          fi
          clearCmd $cmd
          [ $? -eq 5 ] && continue
        
          cmdCopy $cmdPath
          libCopy $cmdPath
        done
        
      2. 移植dropbear相关文件

        #复制相关命令
        ./bincp.sh 
        Enter a command: dropbear
        Enter a command: dropbearkey
        Enter a command: dhclient
        Enter a command: quit
        
        #复制相关类库
        mkdir /mnt/root/etc/dropbear
        mkdir /mnt/root/var/run    #创建dropbear运行时生成的pidfile存放的目录
        
        cp /usr/local/bin/scp /mnt/root/usr/local/bin/
        cp -d /lib64/libnss* /mnt/root/lib64/
        cp -d /usr/lib64/libnss* /mnt/root/usr/lib64/
        cp /etc/nsswitch.conf /mnt/root/etc/
        ls /mnt/sysroot/usr/lib64/ /mnt/root/lib64/
        
        #生成私钥信息
        dropbearkey -t dss -f /mnt/root/etc/dropbear/dropbear_dss_host_key
        #生成公钥信息
        dropbearkey -t rsa -s 2048 -f /mnt/root/etc/dropbear/dropbear_rsa_host_key 
        
        #因为dropbear在登录的时候会检查合法shell,新建配置文件
        vim /mnt/root/etc/shells     
        /bin/ash
        /bin/bash
        /bin/hush
        /sbin/nologin
        /bin/sh
        
        #dropbear配置文件
        vim /mnt/root/etc/sysconfig/dropbear
        keysize=2048
        port=22
        
        #远程登录的会在/dev/pts下生成以数字命名的伪终端设备,现在需要实现该功能。
        #修改配置文件
        vim /mnt/root/etc/fstab
        proc            /proc   proc    defaults    0   0
        sysfs           /sys    sysfs   defaults    0 0
        devpts        /dev/pts    devpts    defaults 0 0
        
      3. 设置开机启动

        #修改配置文件
        vim /mnt/root/etc/init.d/rcS
        
        #!/bin/sh
          
        /bin/mount -a
        mdev -s
        
        mkdir /dev/pts
        
        ifconfig lo 127.0.0.1
        ifconfig eth0 192.168.1.210
        
        sleep 10
        
        /usr/local/sbin/dropbear
        
        [ -r /etc/sysconfig/network ] && source /etc/sysconfig/network
        [ -z "$HOSTNAME" -o "$HOSTNAME" == '(none)' ] && hostname localhost || hostname $HOSTNAME
        
      4. 挂起主机,启动子虚拟机

        sync
        sync
        sync
        poweroff
        

        在外部使用ssh工具登录子虚拟机

         

  • 实现子主机nginx服务web功能

    1. 在主机中编译安装nginx

      # 使用前面下载的 nginx-1.19.9.tar.gz
      tar xf nginx-1.19.9.tar.gz
      cd nginx-1.19.9
      
      ./configure --prefix=/usr/local --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --user=nginx --group=nginx --without-pcre --without-http_rewrite_module --without-http_geo_module --without-http_uwsgi_module --without-http_fastcgi_module --without-http_scgi_module --without-http_memcached_module
      
      make && make install
      
      #创建nginx所需用户组和用户
      groupadd -r nginx
      useradd -r -g nginx nginx
      
      #启动nginx并验证端口是否启动(关闭nginx命令为 nginx -s stop)
      /usr/local/sbin/nginx        #启动nginx程序
      netstat -ltnp
      
    2. 移植dropbear至子主机

      #复制可执行程序和配置文件
      cp -r /etc/nginx/ /mnt/root/etc/
      cp /usr/local/sbin/nginx /mnt/root/usr/local/sbin/
      
      #移植nginx用户
      grep "^nginx" /etc/passwd >> /mnt/root/etc/passwd 
      grep "^nginx" /etc/group >> /mnt/root/etc/group 
      grep "^nginx" /etc/shadow >> /mnt/root/etc/shadow
      
      #创建所需文件夹
      mkdir /mnt/root/usr/local/html
      mkdir /mnt/root/var/log/nginx/
      mkdir /mnt/root/usr/local/logs/
      mkdir /mnt/root/var/lock/subsys/
      
      #创建测试网页
      vim /mnt/sysroot/usr/local/html/index.html
      <h1>Welcome to my opensamlee home!!</h1>
      
    3. 设置开机启动

      #修改配置文件
      vim /mnt/root/etc/init.d/rcS
      
      #!/bin/sh
        
      /bin/mount -a
      mdev -s
      
      mkdir /dev/pts
      
      ifconfig lo 127.0.0.1
      ifconfig eth0 192.168.1.210
      
      sleep 10
      
      /usr/local/sbin/dropbear
      
      /usr/local/sbin/nginx
      
      [ -r /etc/sysconfig/network ] && source /etc/sysconfig/network
      [ -z "$HOSTNAME" -o "$HOSTNAME" == '(none)' ] && hostname localhost || hostname $HOSTNAME
      
    4. 挂起主机,启动子虚拟机

      sync
      sync
      sync
      poweroff
      

      在外部使用浏览器访问子主机

       

  • 优化开机启动脚本

    现在开机启动脚本都集中在rcS文件,不方便扩展,现在拆分下,此操作可以在子主机内进行

    以下操作在子主机内进行

    建立应用的启动脚本

    #创建启动脚本文件夹
    mkdir /etc/rc.d/
    
    vi /etc/rc.d/dropbear.sh
    /usr/local/sbin/dropbear
    
    vi /etc/rc.d/nginx.sh
    /usr/local/sbin/nginx
    
    #授权为可执行文件
    chmod +x /etc/rc.d/*.sh
    

    修改/etc/init.d/rcS文件

    vim /etc/init.d/rcS
    
    #!/bin/sh
    
    /bin/mount -a
    mdev -s
    
    mkdir /dev/pts
    
    ifconfig lo 127.0.0.1
    ifconfig eth0 192.168.1.210
    
    [ -r /etc/sysconfig/network ] && source /etc/sysconfig/network
    [ -z "$HOSTNAME" -o "$HOSTNAME" == '(none)' ] && hostname localhost || hostname $HOSTNAME
    
    clear
    sleep 3
    for i in /etc/rc.d/*.sh;do
        $i start
        sleep 1
    done
    
  • 开启ftp服务

    tcpsvd 0 21 ftpd -w /tmp &
    
    #上面的0表示对所有ip地址都进行侦听
    #ftpd -w这里的参数-w表示client可以对目录执行写操作
    #21指定ftp服务器的默认端口
    #可以使用-t和-T参数设置client在没有任何操作的最大时间之后ftpd主动断开client连接,
    #默认-t为2分钟=2 * 60,-T为1小时=1 * 60 * 60
    
  • 使用别名优化命令

  • vim /etc/profile
    
    # /etc/profile: system-wide .profile file for the Bourne shells
    
    echo
    echo -n "Processing /etc/profile... "
    # no-op
    echo "Done"
    echo
    export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
    export PS1='[\\u@\\h \\W]\\$'
    
    alias rm='rm -i'
    alias ll='ls -l'
    alias vim='vi'
    alias logout='exit'
    

    参考资料

上一篇:解决Gitlab的The remote end hung up unexpectedly错误,解决RPC failed; HTTP 413 curl 22 The requested URL retu


下一篇:5days_企业权限管理(SSM整合)