CentOS7

CentOS7

该博客为 Linux 笔记二次整理,较为简短,原笔记参考Linux(CentOS7)学习笔记

1.Shell

1.1.vi/vim

  • 所有 Unix Like 系统都会内置 vi 文本编辑器;很多个别软件的编程接口都会主动调用vi(如crontabvisudoedauota等指令)。

  • 在使用 vim 编辑时,vim 会在与被编辑的文件目录下,在创建一个名为.filename.swp的文件。异常中断 vim 时,.filename.swp不会消失,使用 O 可以只读方式打开,使用 R 可载入.filename.swp的内容,但结束 vim 后.filename.swp不会自动删除。使用 D 可直接删除.filename.swp

  • 常用vi/vim指令模式下的快捷键:

    快捷键 作用
    <ctrl>+f/b 下/上移动一页
    0/Home、$/End 移动到该行最前、最后
    G、nG、gg 移动到文件最后一行、第 n 行、第一行
    n+<Enter>、n+<space> 向下移动 n 行、向后移动 n 个字符
    /word、?word 向光标之前、之后寻找字符(使用 n、N 继续搜寻下一个)
    :n1,n2s/word1/word2/g 在 n1 行与 n2 行中寻找 word1 并将其替换为 word2;若所有行则用1,$s/word1/word2/g,取代前需要确认的话可使用1,$s/word1/word2/gc
    x、X、nx 在一行中,删除光标后一个、前一个、后 n 个字符
    dd、ndd 删除光标所在整行、删除光标所在及以下 n 行
    yy、nyy 复制光标所在整行、复制光标所在及以下 n 行
    p、P 粘贴复制的行到光标所在行之后、之前
    u 复原前一个动作
    <ctrl>+r 重做上一个动作
    . 重复前一个动作
    i、I 从光标处插入、从光标所在行第一个非空白字符处插入
    a、A 从光标下个字符处插入、从光标所在行最后一个字符处插入
    o、O 从光标所在行的上一行、下一行插入
    r、R 取代光标所在字符一次、一直取代
  • vim 指令模式下常用操作:

    • 区块选择:v、V、<ctrl>+v 可选择光标移动的字符、行、块,按 y 复制、按 d 删除、按 p 粘贴。
    • 多文件编辑:输入:files查看当前编辑了那些文件,:n/N切换到下一个/上一个文件。
    • 多窗口:输入:sp会再次打开当前文件,:sp filename会打开 filename 文件,使用 <ctrl>+w 在不同窗口切换。
  • vim 相关文件:

    • ~/.viminfo:记录曾经做过的行为。
    • /etc/vim~/.vimrc:前者保存 vim 整体设置,后者自定义设置。指令模式下:set all可查看,或者设置。

1.2.Shell 变量

  • Shell 未设置变量将为空。

  • Shell 变量分环境变量和自订变量,前者能被子进程继承,后者不能。

  • envexport指令可查看环境变量,setdeclare指令可查看环境变量和自订变量。其中,$$取得本 Shell 的 PID,$?取得上个指令回传值$RANDOM取得/dev/random设备产生的随机数。

  • read,读取变量。加参数-p可指示提示,加参数-t指示等待的秒数,如read -p "input: " -t 30 name

  • declare [-|+][aixr] variable设置变量类型。参数-a-i-x-r将其设置为 array 类型、整数数字类型、环境变量、只读变量。

    Shell 变量默认是字符串。Bash Shell 环境中的计算,默认最多达到整数形态。

    sum=1+1/2;
    echo ${sum} # 1+1/2
    
    declare -i sum=1+1/2;
    echo ${sum} # 1
    

1.3.Bash Shell

  • /etc/shells记录了可以使用的 Shell。

  • Bash Shell 提供的功能有:

    • 记忆使用过的指令。

      前一次登录执行的保存于~/.bash_history,当前执行的暂存于内存。~/.bash_history记录的数据量由 HISTFILESIZE 环境变量值决定。

      history -c将当前 Shell 中的 history 清除,history -w将当前 Shell 中的 history 写入到~/.bash_history

      history查看最近执行的指令,history -d {number}删除指定的指令记录,!{number}执行指定 number 对应指令,!!执行上一条,!{command}执行最近以“command”开头的那一条指令。

    • <tab> 键补全。

    • 设置指令别名。如alias lm='ls -al'

    • 工作前后台控制。

    • Shell Scripts。

    • 提供万用字符*?[][-][^]

  • Bash Shell 常用快捷键:

    快捷键 作用
    <tab> 根据当前目录下文件名补全文件名
    <ctrl>+u/k 删除从光标到指令串最前/最后的字符
    <ctrl>+a/e 将光标移动到指令串最前/最后

    Bash Shell 默认的组合键:

    组合按钮 执行结果
    <ctrl>+c 终止当前命令
    <ctrl>+d EOF
    <ctrl>+m Enter
    <ctrl>+s 暂停屏幕输出
    <ctrl>+q 恢复屏幕输出
    <ctrl>+u 在提示字符下,将整列命令删除
    <ctrl>+z 暂停当前的命令

    Bash Shell 的快捷键可通过stty设置。如:

    stty -a       # 列出所有 stty 参数
    stty erase ^h # 修改删除字符为 <ctrl>+h
    
  • set [-uvCHhmBx],设置 Bash Shell。echo $-查看当前启动了那些选项。

  • Bash Shell 相关文件:

    • ~/.bash_history
    • ~/.bash_logout:登出 Bash Shell 后执行的指令。
    • /etc/issue/etc/issue.net/etc/motd:Bash Shell 进站欢迎信息、通过 telnet 远程登陆程序时 Bash Shell 进站欢迎信息、用户登录后取得信息。
  • Bash Shell 操作环境:

    分为 login shell(由完整的登录流程取得的 Shell)和 non-login shell(取得 Bash Shell 不需重复登录,如 X window 登录 Linux 后以图形化接口启动终端机、原本 Bash 环境下再次下达bash指令)。

    login shell 会按顺序读取配置文件/etc/profile(系统的,最好不要修改,该文件会读取/etc/profile.d/*.sh文件)、~/.bash_profile/~/.bash_login/~/.profile(个人的,前者不存在读取后者,该文件会读取~/.bashrc文件)。

    non-login shell 会读取~/.bashrc文件(该文件还会读取/etc/bashrc文件,而/etc/bashrc又会读取/etc/profile.d/*.sh文件)。

  • 以下指令都会将 stdout、stderr 重定向同一个 list 文件,但第一种会乱序:

    find /home -name .bashrc > list 2> list
    find /home -name .bashrc > list 2>&1
    find /home -name .bashrc > list &>!
    
  • command1; command2中,command1 执行完后,再执行 command2,无论 command1 的执行结果如何。

  • Bash Shell 中常用计算:

    $(command)     # 指令计算
    `command`      # 指令计算
    $( (express) ) # 数值计算
    

    如:

    $(uname -r)                       # 3.10.0-1160.el7.x86_64
    total=$( (${firstnum}*${secnu}) ) # declare -i total=${firstnum}*${secnu}
    

1.4.常用 Bash Shell 指令

  • type [-tpa] {command}查询指令是否为 Bash Shell 内置指令。

    -t参数,指出指令是 file(外部)、alias(别名)、builtin(内部)。

    -p参数,command 是外部指令时,显示完整文件名。

    -a参数,会由 PATH 路径中将含有 command 的指令列出来(包含别名)。该顺序也是指令下达的寻找顺序,即绝对/相对路径指令、Bash 的 alias 指令、Bash 的内置指令、PATH 环境变量中的指令。

  • Bash Shell 的管线指令(可以使用|的指令)只会处理 stdout。常用的有:

    • cut,撷取文本每行中部分内容。

      cut -d '分割字符' -f fields,以分割字符分割,并获取 fields 个。如:

      echo ${PATH} | cut -d ':' -f 5   # 获取前五个
      echo ${PATH} | cut -d ':' -f 3,5 # 获取第三至第五个
      

      cut -c 字符区间,获取指定字符区间内容。如:

      export | cut -c 12-   # 获取第 12 个字符及以后
      export | cut -c 12-20 # 获取第 12-20 个字符
      
    • grep:撷取文本中包含指定内容中的整行。其相关参数:

      -v,反向选择。

      -E,指定内容中包含延展正则表达式。或者使用egrep

      --color=auto 'str',对 str 加上颜色。

      如:

      grep --color=auto 'MANPATH' /etc/man_db.conf
      
    • sort将文本中内容排序。排序是按照分割符分割每行后每行以第一个数据的文字形态进行排序,其字符排序与 locale 有关。分割符默认为/t,通过-k参数可指定以第几个数据,以数字形态可添加-n参数。如:

      cat /etc/passwd | sort -t ':' -k 3 -n # 按照 uid 排序
      
    • uniq,消除重复。-c参数会统计次数。如:

      last | cut -d ' ' -f 1 | sort | uniq -c
      
    • wc,了解指定文本中字数、行数、字符数。-w-l-m参数只会显示其中指定统计数。如:

      cat /etc/passwd | wc -l # 了解账号文件中有多少账号
      
    • tee,将数据流分送一份到文件。-a参数表明以添加到文件中的方式而不是覆盖。如:

      ls -l /home | tee -a ~/homefile | more
      
    • tr,用于删除/取代讯息中的文字。如:

      last | tr '[a-z]' '[A-Z]'   # 将小写转为大写
      cat /etc/passwd | tr -d ':' # 删除输出信息中的 :
      
    • col,有特殊用途。如:

      cat /etc/man_db.conf | col -x | cat -A | more # col -x 将 \t 取代为空白键,cat -A 就不会以 ^I 显示 \t
      
    • join,对比两个文件,在每行中,以某个分隔符(通过-t参数指定)分隔后某个字段(默认第一个字段,可以通过-1-2指定)相同则合为一行,且该字段会在最前显示一次。如:

      join -t ':' -1 4 /etc/passwd -2 3 /etc/group | head -n 3
      

      使用join前一般需要对要处理的文件进行排序。

    • paste,将两个文件按行粘在一起,并以 <tab> 分开(可使用-d参数修改),其中文件可以以-代替,表示 stdin。如:

      cat /etc/group | paste /etc/passwd /etc/shadow - | head -n 3
      
    • expend,将 <tab> 转成空白键(-t参数设置转为几个)。如:

      grep '^MANPATH' /etc/man_db.conf | head -n 3 | expand -t 6 - | cat -A
      

      unexpend用于将空白键转为 <tab> 。

    • split [-bl] file PREFIX,将一个大文件,按行或大小分区,形成小文件。

      -b,按照大小分区,可加单位 b、k、m 等。

      -l,按照行数分区。

      PREFIX代表小文件名前缀。

      如:

      split -b 300k /etc/services services # 得到 servicesaa、servicesab、servicesac……小文件
      ls -al / | split -l 10 - lsroot
      

      将小文件合成一个大文件可使用如下指令:

      cat lsroot* >> lsrootback
      
    • xargs,产生某个指令的参数。-p参数表示每次执行前都会询问,-n参数表示每次传递几个参数,-e参数指定遇到什么字符串结束(中间没有空格)。如:

      # id 指令不是管线指令,可是哦那个 xargs 向其传递参数
      cut -d ':' -f 1 /etc/passwd | head -n 3 | xargs -p -n 1 id
      cut -d ':' -f 1 /etc/passwd | head -n 3 | xargs -e'sync' -n 1 id
      

    前一个指令的 stdout 作为这次的 stdin,可以用-来代替。如:

    tar -cv -f - /home.tar | tar -xv -f - -C /tmp/homeback # 前一个打包到 stdout,经过管线后递给后面的 stdin
    
  • bc,用于数值计算。如:

    echo "123.123*55.9" | bc
    
    num=3
    time echo "scale=${num}; 4*a(1)" | bc -lq
    
  • sed [-nefr] [动作],也是管道指令。

    -n,安静模式,只有经过 sed 特殊处理的那一行(或者动作)才会被列出来。

    -e,直接在命令行界面上进行 sed 动作编辑。

    -f,直接将 sed 的动作写到一个文件中。

    -r,sed 的动作支持延申表达式。

    -i,直接修改读取的文件内容,而不是由屏幕输出。

    动作则为[n1[,n2]]function,必须单引号引起来,function 可以是 a 新增、c 取代(按行)、d 删除、i 插入、p 打印、s 取代(按行中内容)。

    如:

    nl /etc/passwd | sed '2,$d'                  # 删除 2 行到末尾
    nl /etc/passwd | sed '2i drink tea'          # 在第 2 行前添加新行,内容为“drink tea”字符串
    nl /etc/passwd | sed '2a drink tea'          # 在第 2 行后添加新的一行内容
    nl /etc/passwd | sed '2a Drink tea or ...\
    > drink beer ?'                              # 在第 2 行后添加新的两行
    nl /etc/passwd | sed '2,5c No 2-5 number'    # 删除 2-5 行,整体替换为一行“No 2-5 number”字符串
    nl /etc/passwd | sed -n '5,7p'               # 打印 5-7 行
    
    /sbin/ifconfig eth0 | grep 'inet ' | sed 's/^.*inet //g' | sed 's/ *netmask.*$//g' # 获取 eth0 的 IP
    cat /etc/man_db.conf | grep 'MAN' | sed 's/#.*$//g' | sed 's/^$/d'
    
    # 直接修改原文件内容
    sed -i 's/\.$/\!/g' regular_express.txt          # 将每行结尾的“.”换成“!”
    sed -i '$a # This is a test' regular_express.txt # 在最后新填一行“# This is a test”
    
  • awk '条件类型1{动作1} 条件类型2{动作2} ...' filename,主要处理每行的字段内的数据。默认字段分隔符为空白键或 <tab>。

    $0代表一行数据,$1$2……代表第一个、第二个……字段。

    awk内置变量有:NF每行拥有的字段总数、NR目前处理的第几行数据、FS目前分割字符(默认空白键)。

    awk的格式内容想要以print打印时,对于非变量的文字部分要用双引号括起来。如:

    last -n 5 | awk '{print $1 "\t" $3}'
    

    awk的条件逻辑运算有:>大于、<小于、>=大于等于、<=小于等于、==等于、!=不等于。如:

    cat /etc/passwd | awk 'BEGIN {FS=":"} $3 < 10 {print $1 "\t " $3}'
    

    这里添加{FS=":"}设置分割符,不添加关键字BEGIN的话会在第二行才开始生效。

    awk{}中的动作有多个时,可用;或 <enter> 间隔。printf 格式加上\n才能分行。awk中的变量可直接使用不加$符号,如:

    cat /etc/passwd | cut -d ':' -f 1,3 | sort -t ':' -k 2 -n | awk 'BEGIN{FS=":"} {printf "%15s \t %4d \n", $1, $2}'
    
    # pay.txt
    # Name    1st      2nd      3th
    # VBird   23000    24000    25000
    # DMTsai  21000    20000    23000
    # Bird2   43000    42000    41000
    
    cat pay.txt | \
    awk 'NR==1{printf "%10s %10s %10s %10s %10s\n", $1, $2, $3, $4, "Total"}
    NR>=2{total = $2 + $3 + $4
    printf "%10s %10d %10d %10d %10.2f\n", $1, $2, $3, $4, total}'
    
  • diff,通常是用在同一文件(或软件)的新旧版本差异上,以行为单位来进行比对的,也可比对目录。如:

    cp /etc/passwd passwd.old
    cat /etc/passwd | sed -e '4d' -e '6c no six line' > passwd.new
    diff passwd.old passwd.new
    
  • cmp [-l] file1 file2,将两个文件按字节进行比较。默认只比较到第一个不同字节,-l参数则比较所有。

  • patch [-R] -pN < patch_file,用于使用 patch 文件将旧文件更新为新文件,或者将新文件还原为旧文件。其中-R参数表示还原,-pN表示取消几层目录。

    制作 patch 文件可以使用diff,如:

    diff -Naur passwd.old passwd.new > passwd.patch
    

    然后这里可以使用该 patch 文件更新、还原:

    patch -p 0 < passwd.patch
    patch -R -p 0 < passwd.patch
    

    这里-pN为 0 是因为使用diff制作 patch 文件时,新旧文件处于同级目录下。

  • pr,文件打印准备。

  • man -f相当于whatisman -k相当于apropos。这两个特殊指令要使用需要创建 whatis 数据库才行(在 root 身份下下达指令mandb)。

    manual page 的数据通常放在/usr/share/man这个目录。

    manual page 的查找路径放在/etc/man_db.conf中。

1.5.正则表达式

  • 正则表达式与 locale 相关。如LANG=CLANG=zh_TW时,[A-Z]会有不同结果。

  • 正则表达式和 Bash Shell 万用字符*是完全不同的东西。cpls等指令并未支持正则表达式,使用的是 Bash Shell 本身的万用字符而已。

  • 特殊符号:

    特殊符号 代表意义
    [:alnum:] 英文大小写字符及数字,即 0-9,A-Z,a-z
    [:alpha:] 英文大小写字符,即 A-Z,a-z
    [:blank:] 空白键与 <tab>
    [:cntrl:] 键盘上的控制按钮,即 CR、LF、Tab、Del 等等
    [:digit:] 数字,即 0-9
    [:graph:] 除了空白字符(空白键与 <tab>)外的其他所有按键
    [:lower:] 小写字符,即 a-z
    [:print:] 可以被打印出来的字符
    [:punct:] 标点符号
    [:upper:] 大写字符,即 A-Z
    [:space:] 会产生空白的字符,包括空白键、<tab>、CR 等等
    [:xdigit:] 16 进位的数字类型,包括 0-9,A-F,a-f
  • {}在 Bash Shell 中有特殊意义,使用成正则表达式时需要转义(\)。

  • 延展正则表达式有:|+?()()+

1.6.Shell Scripts

  • 脚本文件得有 rx 权限。

  • /bin/sh其实是/bin/bash的软链接文件。

  • Shell Scripts 中,第一行#!/bin/bash宣告这个文件按内语法使用 Bash Shell 的语法。那么当这个程序被执行时,它就能够载入 Bash Shell 相关的环境配置文件(一般来说是 non-login shell 的~/.bashrc。其他的#都是注释的用途。一般来说要注释添加:内容与功能、版本信息、作者与联络方式、创建日期、历史记录等。

  • test指令来指定判断式,其中各参数含义为:

    test参数
    测试的标志 代表意义
    对于某个文件名的文件类型判断
    -e、-f、-d 该文件名是否存在、该文件名是否存在且为文件、该文件名是否存在且为目录
    -b、-c 该文件名是否存在且为block device设备、该文件名是否存在且为character device设备
    -S、-p、-L 该文件名是否存在且为Socket文件、该文件名是否存在且为FIFO(pipe)文件、该文件名是否存在且为链接文件
    关于文件权限侦测,但root权限常有例外
    -r、-w、-x 该文件名是否存在且有可读、可写、可执行权限
    -u、-g、-k 该文件名是否存在且有SUID、SGID、SBIT属性
    -s 该文件名是否存在且为非空白文件
    两个文件中的比较
    -nt、-ot newer than、older than
    -ef 判断file1与file2是否同一个inode
    关于两个整数之间的判定
    -eq、-ne equal、not equal
    -gt、-lt greater than、less than
    -ge、-le greater than or equal、less than or equal
    判定字符串
    test -z、-n string 判断字符串是否为0、非0
    test str1==、!=str2 判断字符串是否相等、不等
    多重条件判定
    -a、-o、! and、or、not
  • Shell Scripts 中,test 判断式可以用[]代替,需要注意中括号两边要用空白字符分隔(避免与正则表达式模糊),括号内的变量最好用双引号引起来,常量最好用单/双引号引起来。如:

    name="VBird Tsai"
    [ ${name} == "VBird" ]   # 比较 VBird Tsai == "VBird"
    [ "${name}" == "VBird" ] # 比较 "VBird Tsai" == "VBird"
    
  • Shell Scripts 中的流程控制语句:

    # 多个条件可以写在一个中括号里,也可以写在多个中括号,中间用 &&(and)或 ||(or)隔开
    if [ 条件判断式一 ]; then
    	指令
    elif [ 条件判断式二 ]; then
    	指令
    else
    	指令
    fi
    
    case $变量名称 in
    	"第一个变量内容")
    		程序段
    		;;
    	"第二个变量内容")
    		程序段
    		;;
    	*)
    		程序段
    		;;
    esac
    
    while [ condition ]
    do
    	程序段
    done
    
    until [ condition ]
    do
    	程序段
    done
    
    for var in con1 con2 con3 ...
    do
    	程序段
    done
    # seq 可取连续数字如:seq 1 100(取整数1-100)。也可使用 Bash 内置机制 {1..100} 取代。
    
    for ((初始值;限制值;执行步阶))
    do
    	程序段
    done
    
    function fname() {
    	程序段
    }
    # Shell Scripts 的 function 定义要在调用之前。
    
  • sh [-nvx] {scripts}的参数:

    -n:不执行 scripts,只检查语法。

    -v:执行 scripts 前,将 scripts 内容输出到屏幕上。

    -x:将使用到的 scripts 内容显示到屏幕上。

  • Shell Scripts 中,$#代表参数个数$@代表各个参数变量相当于"$1""$2""$3"...$*代表所有参数相当于"$1 $2 $3..."(这里默认的分割为空白键)。$0为指令名,$n为第n个参数。shift n可以删除掉前面n个参数。

  • 通过sh script.sh./script.sh方法执行 Shell Scripts,会在子进程中执行,其中的自订变量在执行完成后就失效。

    通过source script.sh. script.sh方法执行 Shell Scripts,在原进程中执行,自订变量在执行完成之后依然生效。

  • ${变量#关键字}${变量##关键字}${变量%关键字}${变量%%关键字}${变量/旧字串/新字串}${变量//旧字串/新字串}${str-expr}${str:-expr}${str+expr}${str:+expr}${str=expr}${str:=expr}${str?expr}${str:?expr}

2.用户管理

2.1.账号与群组

  • 用户登录时的处理:根据输入的账号名,去/etc/passwd找寻对应的 UID,并读取 GID,在/etc/group中根据 GID 找寻组名。在/etc/shadow中根据 UID 核对密码。最后进入 Shell 控管阶段。

  • 相关文件内容:

    • /etc/passwd,每行代表一个账号,其字段解释:

      账号名称 : 密码 : UID : GID : 使用者信息说明栏 : 主文件夹 : Shell
      
      • 密码:早期密码放在/etc/passwd的密码字段,现在放在/etc/shadow中,这里只会是个"x"。
      • UID:0 表示系统管理员(不建议有多个账号的 UID 为 0);1-999 系统账号使用(1-200 由 distributions 自行创建的账号,201-999 是若有使用者有系统账号需求时可以使用的),通常这些账号是不可登陆的;1000-60000 给一般使用者用的。
      • GID:初始群组的 ID。
      • Shell:使用的默认 Shell。
    • /etc/group,每行代表一个用户组,其字段解释:

      群组名称 : 群组密码 : GID : 此群组支持的账号名称
      
      • 群组密码:通常不需要设置,这个设置通常是给群组管理员使用的,同样被移动到/etc/gshadow去了,这个字段只会是"x"。

      • 此群组支持的账号名称:多个用逗号,之间不要有空格。

        在新版Linux中,初始群组的用户群不会加入该字段。

    • /etc/shadow,保存用户密码相关信息,其字段解释:

      账号名称 : 密码 : 最近更改密码的日期 : 密码不可变动天数 : 密码需要重新变更的天数 : 密码需要变更期限前的警告天数 : 密码过期后的宽限时间 : 账号失效日期 : 保留
      
    • /etc/gshadow,保存用户组密码相关信息,其字段解释:

      群组名称 : 密码栏 : 群组管理员账号 : 有加入该群组支持的所属账号
      
      • 密码栏:!开头或空表示无合法密码,即无群组管理员。
      • 有加入该群组支持的所属账号:与/etc/group对应栏内容相同。
  • 相关指令:

    • authconfig --test | grep 'hashing',了解 shadow 采用的加密机制。

    • groups,检查自身群组,第一个是有效群组(当前登录的群组)。

    • newgrp groupname,切换有效群组。会以另一个 Shell 来开启,使用后可exit退出。

    • useradd,创建用户,常用参数如下:

      • -u,指定 UID。
      • -g,指定初始群组。
      • -G,指定该账号还加入的群组。
      • -M-m,不要、要创建主文件夹(系统账号/一般账号有该参数)。
      • -c,说明(即/etc/passwd中的第 5 栏)。
      • -d,指定某个目录成为主文件夹。
      • -r,创建一个系统账号。
      • -s,指定 Shell。
      • -e,指定失效日。

      useradd会参考以下文件:

      • /etc/default/useradd,可使用useradd -D查看,其解释如下:

        • GROUP=100:表示新建账号的初始群组使用 GID 为 100 的,为 users 群组。但这个不会生效,这是用于公共群组机制。而我们创建的使用的是私有群组机制,他会创建一个与用户名相同的群组,并作为初始群组,主文件夹的权限为 700。

        • HOME=/home:默认主文件夹所在目录。

        • INACTIVE=-1:密码失效日。

        • EXPIRE=:账号失效日。

        • SHELL=/bin/bash:默认shell。

        • SKEL=/etc/skel:使用者主文件夹的内容数据参考目录。主文件夹中的内容都是由/etc/skel/所复制过去的。

        • CREATE_MAIL_SPOOL=yes:是否主动帮使用者创建邮件信箱。

      • /etc/login.defs,其解释如下:

        • MAIL_DIR:使用者默认邮箱放置目录。
        • shadow 密码第 4、5、6 字段,其中的PASS_MIN_LEN已经失效,被 PAM 模块取代。
        • UID/GID 指定数值:注意的是,系统给予一个账号 UID 时,先参考 UID_MIN,再在/etc/passwd中寻找最大 UID,该值加 1 为新账号的 UID。
        • CREATE_HOME yes:指明不添加-M/-m参数时是否创建使用者主文件夹。
        • UMASK 077:主文件夹的umask。
        • USERGROUPS_ENAB yes:如果使用 userdel 删除账号时,该账号所属初始群组没帐号了,该初始群组也会被删除。
        • ENCRYPT_METHOD SHA512:密码加密机制。
    • passwd,修改密码,可以通过以下格式:

      echo "newpwd" | passwd --stdin username # 注意密码明文会记录到 Bash History
      passwd [option] username
      passwd                                  # 修改当前用户密码
      

      option 参数常用的有:

      • -S,列出密码相关参数,即/etc/shadow文件中的大部分内容。
      • -l-u,锁定、解除锁定账号,即通过在/etc/shadow密码栏中添加、删除!!前缀来让密码生效、失效。
      • -n-x-w修改/etc/shadow第 4、5、6 字段,接天数。
      • -i,修改/etc/shadow第 7 字段,接日期。

      除 root 外,使用passwd修改密码会使用 PAM 模块进行密码校验,这个管理机制被写在/etc/pam.d/passwd中,该文件与密码有关的测试模块就是使用的 pam_cracklib.so,这个模块会检验密码相关信息并取代/etc/login.defs内的PASS_MIN_LEN设置。

      chage -l username相当于passwd -S username,也可添加相关参数修改密码相关信息。chage可以设置使用者在第一次登录时强制他一定要修改密码后才能继续使用。如:

      useradd lisi
      echo "abc123123" | passwd --stdin lisi
      chage -d 0 lisi
      

      这里设置了 lisi 账号的创始时间为 1970/1/1,所以有问题,登录 lisi 账号时会要求修改密码。

    • usermod,修改用户相关信息。其参数与useradd类似,还有类似于passwd-l-u参数的-L-U参数。

    • userdel,删除账号。

      注意如果账号只是暂时不用,修改/etc/shadow的第 8 字段(账号失效日期)为 0 即可,不用删除账号。

      确定要删除账号时,最好先用find / -user username指令查出整个系统属于该用户的文件并删除。

    • id,指令查询自己相关的 UID/GID 等信息。

      finger,查询自己相关的信息,大部分在/etc/passwd中的内容,由于这个指令有点危险,所以新版本中已默认不安装这个软件了。

    • chfnchsh,修改/etc/passwd文件,这两个文件权限都是 SUID。

    • groupadd [-g gid] [-r] groupname,创建群组。

      -g,指定 GID。

      -r,创建系统群组。

    • groupmod [-g gid] [-n group_name] groupname,修改群组。

      -g,指定新 GID。

      -n,指定新群组名。

    • groupdel groupname,删除群组。当有账号以该群组为初始群组时,该群组无法删除。

    • 群组管理员功能,流程:

      gpasswd testgroup             # root 为群组设置密码
      gpasswd -A zhangsan testgroup # root 添加群组管理员
      gpasswd -a zhangsan testgroup # zhangsan 即可为 testgroup 群组添加用户
      gpasswd -a lisi testgroup
      

2.2.ACL

  • 检查是否支持 ACL:

    dmesg | grep -i acl
    
  • setfacl [-bkRd] [{-m|-x} ACL_option] {file_name | directory_name},设置 ACL。

    -m-x,不可混用,表示设置、删除后续 ACL 参数。

    -b,移除所有的 ACL 参数。

    -k,移除默认的 ACL 参数。

    -R,递回设置 ACL,即包括次目录都会被设置。

    -d,设置默认 ACL,只对目录有效,在该目录新建的数据会引用此默认值。

    ACL_option 格式为:

    u:[username]:[rwx]  # 针对用户设置
    g:[groupname]:[rwx] # 针对用户组设置
    m:[rwx]             # mask 设置
    

    使用者或群组所设置的权限必须要存在与 mask 的权限设置范围内才有效。

    如:

    setfacl -m u:yangyi:rx acl_test1
    setfacl -m u:lisi:- acl_test1
    setfacl -m g:mygroup1:rx acl_test1
    setfacl -m m:rx acl_test1
    setfacl -m d:u:yangyi:rx acl_test_dir
    
    setfacl -x u:yangyi acl_test1
    setfacl -x d:u:yangyi acl_test_dir
    
  • getfacl {file_name|directory_name},获取 ACL 设置。

2.3.用户切换

  • su指令切换用户。

    su              # 切换到 root 用户,使用 non-login shell
    su -            # 切换到 root 用户,使用 login shell
    su -l username  # 切换到目标用户,使用 login shell
    

    -c [statement],只是在对应用户下执行相关指令。

  • sudo [-b] [-u username] statement,以对应用户执行指令(Bash Shell 尚未改变)。

    -b,将指令放在背景中执行,不对当前 Shell 产生影响。

    -u,不使用此参数表明以 root 用户执行指令。

    如:

    sudo sh -c "sync && sync && shutdown -h now"
    

    sudo在 5 分种内再次输入不需要再次输入密码。

    只有在/etc/sudoers内配置的用户才能使用sudo指令。配置/etc/sudoers最好使用visudo指令以保持该文件规范。/etc/sudoers配置行对应内容:

    username/%groupname	登陆者的来源主机名称=(可切换的身份)	可下达的指令的绝对路径
    

    如:

    root    ALL=(ALL)   ALL
    %wheel  ALL=(ALL)   ALL
    %wheel  ALL=(ALL)   NOPASSWD: ALL # 使用 sudo 时不用输入密码
    
    # myuser 用户就不能使用 sudo 切换 root 下修改 root 的密码
    myuser  ALL=(root)  !/usr/bin/passwd, /usr/bin/passwd [[:alpha:]]*, !/usr/bin/passwd root
    
    # 使用别名,别名一定要大写
    User_Alias ADMPW = pro1, pro2, pro3, myuser1, myuser2
    Cmnd_Alias ADMPWCOM = !/usr/bin/passwd, /usr/bin/passwd [[:alpha:]]*, !/usr/bin/passwd root
    ADMPW   ALL=(root)  ADMPWCOM
    

2.4.PAM

  • PAM 借由一个在/etc/pam.d/中与程序相同文件名的配置文件来进行一连串的认证分析需求。

    login程序的 PAM 配置文件/etc/pam.d/login

    #%PAM-1.0
    auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so
    auth       substack     system-auth
    auth       include      postlogin
    account    required     pam_nologin.so
    account    include      system-auth
    password   include      system-auth
    # pam_selinux.so close should be the first session rule
    session    required     pam_selinux.so close
    session    required     pam_loginuid.so
    session    optional     pam_console.so
    # pam_selinux.so open should only be followed by sessions to be executed in the user context
    session    required     pam_selinux.so open
    session    required     pam_namespace.so
    session    optional     pam_keyinit.so force revoke
    session    include      system-auth
    session    include      postlogin
    -session   optional     pam_ck_connector.so
    

    /etc/pam.d/system-auth

    #%PAM-1.0
    # This file is auto-generated.
    # User changes will be destroyed the next time authconfig is run.
    auth        required      pam_env.so
    auth        required      pam_faildelay.so delay=2000000
    auth        sufficient    pam_unix.so nullok try_first_pass
    auth        requisite     pam_succeed_if.so uid >= 1000 quiet_success
    auth        required      pam_deny.so
    
    account     required      pam_unix.so
    account     sufficient    pam_localuser.so
    account     sufficient    pam_succeed_if.so uid < 1000 quiet
    account     required      pam_permit.so
    
    password    requisite     pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
    password    sufficient    pam_unix.so sha512 shadow nullok try_first_pass use_authtok
    password    required      pam_deny.so
    
    session     optional      pam_keyinit.so revoke
    session     required      pam_limits.so
    -session     optional      pam_systemd.so
    session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
    session     required      pam_unix.so
    

    #%PAM-1.0宣告 PAM 版本,其它#开头的都是注释。

    之后每行由三个字段组成:验证类别、控制标准、PAM 模块与该模块参数。

    • 验证类别(Type),分为 4 种:

      • auth:认证,主要用来检验使用者的身份验证,这种类别通常是需要密码来验证的,所以后续接的模块是用来检验使用者的身份。
      • account:大部分在进行授权,这种类别主要检验使用者是否具有正确的使用权限。如使用过期密码无法登录。
      • session:管理使用者在这次登录(或者使用这个指令)期间,PAM 所给予的环境设置。这个类别通常用在记录使用者登录与登出时的信息。如使用susudo指令时,/var/log/secure含有许多 PAM 说明以及“session open, session close”信息。
      • password:提供验证的修订工作。如修改密码。

      这 4 个验证类别通常是有顺序的。

    • 控制标准:

      • required:验证成功带有 success 标志,否则 failure 标志。无论是否成功均继续后续验证流程。
      • requisite:验证失败立即回报原程序 failure 标志,并终止后续验证流程,否则带有 success 标志并进行后续流程。由于失败就终止,所以失败时产生的 PAM 信息无法通过后续模块记录。
      • sufficient:与 requisite 相反,成功回传 success 标志并终止后续验证流程,否则带有 failure 标志进行后续验证流程。
      • optional:这个模块控制项目大多是在显示讯息而不是用在验证方面。
  • PAM 常用模块:

    • pam_securetty.so:限制 root 只能从安全终端机登录。安全终端机的设置在/etc/securetty中。

    • pam_nologin.so:限制一般使用者是否能够登录主机。/etc/nologin存在时,所有一般使用者无法再登录了(对 root 和已经登录的一般账号无影响)。

    • pam_selinux.so、pam_console.so、pam_unix.so。

    • pam_loginuid.so:验证使用者的 UID 是否真的时我们所需要的数值(一般账号 UID 均大于等于 1000)。

    • pam_env.so:用于设置环境变量。有额外的环境变量需要设置,可参考/etc/security/pam_env.conf的说明。

    • pam_pwquality.so:检验密码强度。最早之前其实是使用 pam_cracklib.so 这个模块,后来改为 pam_pwquality.so 并兼容 pam_cracklib.so,同时提供/etc/security/pwquality.conf这个文件可额外指定默认值。

    • pam_limits.so:ulimit指令其实就是使用这个模块提供的能力,更多细部设置参考/etc/security/limits.conf

  • PAM 要用到的文件:

    • /etc/pam.d/*:每个程序个别的 PAM 配置文件。
    • /lib64/security/*:PAM 模块文件实际放置目录。
    • /etc/security/*:其它 PAM 环境的配置文件。
    • /usr/share/doc/pam-*/:详细的 PAM 说明文件。
  • login的 PAM 验证机制流程:

    1. auth 阶段:
      1. 经过 pam_securetty.so 判断,如果使用者是 root,则会参考/etc/securetty设置。
      2. 经过 pam_env.so 设置额外的环境变量。
      3. 通过 pam_unix.so 检验密码。不通过则回报给login程序。
      4. 通过 pam_succeed_if.so 判断 UID 是否大于等于 1000,小于则回报失败。
      5. 以 pam_deny.so 拒绝连线。
    2. account 阶段:
      1. 经过 pam_nologin.so 判断/etc/nologin是否存在,若存在一般不允许使用者登录。
      2. 以 pam_unix.so 和 pam_localuser.so 进行账号管理。
      3. 以 pam_succeed_if.so 判断 UID 是否小于 1000,小于则不记录登录信息。
      4. 以 pam_permit.so 允许该账号登录。
    3. password 阶段:
      1. 以 pam_pwquality.so 设置密码仅能尝试错误 3 次。
      2. 以 pam_unix.so 通过 SHA512、shadow 等功能进行密码验证,通过则回报 login 程序。
      3. 否则以 pam_deny.so 拒绝登录。
    4. session 阶段:
      1. 以 pam_selinux.so 暂时关闭 SELinux.
      2. 使用 pam_limits.so 设置使用者能够操作的系统资源。
      3. 登录成功后开始记录相关信息在登录文件中。
      4. 以 pam_loginuid.so 规范不同 UID 权限。
      5. 打开 pam_selinux.so 功能。
  • 如果发生无法登录或者产生一些无法预期得错误时,PAM 会将数据记载在/var/log/security中。

  • 之所以 root 无法通过 telnet 而能通过 ssh 登录,是因为 telnet 引用 login 的 PAM 模块,其中/etc/securetty并没有写入 telnet 远程连线的 pts/n 动态终端机接口设备名称,而 ssh 使用/etc/pam.d/sshd,其流程验证阶段并没有加入 pam_securetty.so,也就没有/etc/securetty限制。

  • ulimit 指令的功能,其实可通过 PAM 实现,即配置/etc/security/limits.conf文件。

2.5.相关指令

  • w/who,了解目前已登录到系统上的使用者。

  • lastlog,了解每个账号最近登录的时间。

  • write 使用者账号 [使用者所在终端接口],可向目标使用者发送信息,会立即显示到目标使用者的终端上。

    mesg n,拒收任何人(除 root)发送给自己的信息。

    wall "信息",向所有使用者发信息。

  • mail -s "邮件标题" username[@localhost] < file,发送邮件。

    mail,查询邮件,交互窗口中输入?获取帮助。

  • pwck,检查/etc/passwd中得信息,主文件夹是否存在、对比/etc/passwd/etc/shadow信息是否一致。

  • pwconv,将etc/passwd中密码移动到/etc/shadow,将原本得密码设为"x"。若/etc/shadow中没有相关得密码数据,则会去/etc/login.defs取用相关得密码数据创建。一般手动改设置账号会使用该指令。

  • pwunconv,将/etc/shadow中密码写回/etc/passwd,并将/etc/shadow删除。

  • chpasswd,读入未加密前的密码,经过加密后写入/etc/shadow中。chpasswd 会读/etc/login.defs中的加密机制,若不适用该加密机制可加参数-c/-e处理。如:

    echo "zhangsan:abcabc" | chpasswd
    

3.磁盘管理

3.1.磁盘分区

  • MBR 与 GPT 分区:

    • MBR 的扩展分区并不是只占一个区块,而是会分布在每个分区的最前面几个扇区来记载分区信息。

    • GPT 使用 34个 LBA 区块来记录分区信息。整个磁盘的最后 33 个 LBA 也拿来作为另一个备份。

      LBA0(MBR 相容区块):前 446 Bytes 存储开机程序。后原本记录分区表的记录特殊标准以此表明为 GPT 格式。

      LBA1(GPT 表头记录):记录分区表本身位置与大小、备份用的 GPT 分区放置位置、分区表的检验机制码(CRC32).

      LBA2-33(实际记录分区信息处):每个 LBA 可记录 4 笔分区记录。

    • MBR 分区使用fdisk,GPT 分区使用gdisk/partedfdisk使用柱面作为分区最小单位,而gdisk默认使用 sector。

    • 磁盘没有超过 2TB,Linux 默认以 MBR 模式处理分区表。使用 GPT 分区表需要在安装时指定参数inst.gpt,使用 GPT 时需要 BIOS Boot。

  • 磁盘分区时,应该先用lsblk/blkid先找到磁盘,再用parted来找出分区表类型,最后使用fdisk/gdisk分区。最后使用partprobe -s更新现在使用的分区表(加参数-s会显示信息),可使用cat /proc/partitions查看。

3.2.分区格式化

  • 格式化:

    创建新的分区后,需要对磁盘格式化(创建文件系统)。

    格式化为 XFS 使用mkfs.xfs,如mkfs.xfs -f -d agcount=2 /dev/sda4grep 'processor' /proc/cpuinfo)。使用mkfs -t xfs可查看mkfs.xfs的参数说明。

    格式化为 EXT4 使用mkfs.ext4,如mkfs.ext4 /dev/sda5mkfs.ext4大部分默认设置在/etc/mke2fs.conf文件中。

  • 文件系统:

    • U 盘使用的文件系统一般为 FAT 格式,读取方式不用 inode 用”链接“一个个块。
    • 老式 Linux 采用 EXT 文件系统,新式使用 XFS。
    • 使用dumpe2fs可查询 EXT 文件系统的 superblock 信息。
  • 文件系统常用指令:

    • dfdu:前者列出文件系统的整体磁盘使用量,后者评估文件系统的磁盘使用量(常用在推估目录所占容量)。

    • 检查/修复文件系统:

      xfs_repairfsck.ext4在扫描磁盘时可能造成部分文件系统的修订,所以执行时,被检查的分区务必不能挂载到磁盘上

      • xfs_repair,用于检查/修复 XFS 文件系统。如:

        xfs_repair /dev/sda4 # 检查 /dev/sda4 分区的文件系统
        

        由于根目录无法卸载,需要添加-d参数。

      • fsck.ext4,用于检查/修复 EXT4 文件系统。如:

        dumpe2fs -h /dev/sda5 | grep 'Blocks per group'
        fsck.ext4 -b 32768 /dev/sda5
        
    • 修改 Label Name 和 UUID:

      • xfs_admin [-lu] [-L label] [-U uuid] 设备文件名用于查询/修改 XFS 文件系统的 Label Name、UUID。-l-u-L-U列出、修改设备文件的 Label Name、UUID。如:

        umount /dev/sda4
        xfs_admin -u /dev/sda4
        uuidgen
        xfs_admin -U ... /dev/sda4
        mount UUID=... /dev/sda4
        
      • tune2fs [-l] [-L label] [-U uuid] 设备文件名用于查询/修改 EXT4 文件系统的 Label Name、UUID。

3.3.挂载

  • 如果被挂载的目录不是空的话,挂载之后原本目录中的内容会暂时消失,新分区被卸载后内容会还原。

  • mount指令用于挂载:

    mount -a,依照/etc/fstab中内容进行挂载。

    mount [-l],显示目前挂载信息-l参数会显示 Label 名称。

    mount [-t 文件系统] {LABEL='...' | UUID='...' | 设备文件名} 挂载点-t参数指定挂载的文件系统类型,如 xfs、ext4、vfat。

    实际上不需要-t参数。Linux 会根据文件系统的 superblock 搭配 Linux 自己的驱动程序去测试挂载,测试成功则使用该类型的文件系统挂载。测试挂载文件系统类型的优先顺序保存在/etc/filesystems,Linux 系统已载入的文件系统类型保存在/proc/filesystems,Linux 支持的文件系统驱动程序在/lib/modules/$(uname -r)/kernel/fs/中。

    重新挂载根目录:

    mount -o remount,rw,auto /
    

    mount还可以将一个目录挂载到另一个目录上。如:

    mkdir /data/var
    mount /var /data/var
    ls -lid /var /data/var
    
  • umount用于挂载卸载。可以使用挂载点卸载,也可使用设备文件名卸载。如:

    umount /dev/sda4
    umount /data/var
    
  • /etc/fstab中开机挂载配置的字段含义:

    Device                    MountPoint   fileSystem   parameters   dump   fsck 
    磁盘设备文件名/UUID/label   挂载点        文件系统       文件系统参数
    

    /etc/fstab是开机时的配置文件,实际 filesystem 的挂载是记录到/etc/mtab/proc/mounts这两个文件当中的。

3.4.设备文件

  • Linux 通过 major 和 minor 来确定设备文件,这两个值含有特殊意义,不能随意设置。

  • mknod 设备文件名 [bcp] [Major] [Minor]指令新建设备文件,bcp 分别代表存储、输入、FIFO 设备文件。如:

    mknod /dev/sda10 b 252 10
    mknod /tmp/testpipe p
    rm /dev/sda10 /tmp/testpipe
    

3.5.示例

# 检查磁盘信息
lsblk                 # 查看磁盘信息
blkid                 # 查看磁盘 uuid
parted /dev/sda print # 查看 /dev/sda 的分区格式(GPT)

# 创建新分区 /dev/sda4,1G,XFS,用于 /data/xfs 挂载
gdisk /dev/sda                                                     # 创建分区、1G、8300
partprobe -s
cat /proc/partitions
grep 'processor' /proc/cpuinfo; mkfs.xfs -f -d agcount=4 /dev/sda4 # 格式化
mkdir -p /data/xfs; blkid /dev/sda4; mount UUID="..." /data/xfs    # 挂载
df /data/xfs                                                       # 查看 /data/xfs 使用情况

# 创建新分区 /dev/sda5,1G,Swap,用于内存交换
gdisk /dev/sda      # 创建分区、1G、8200
partprobe -s
mkswap /dev/sda5    # 格式化
swapon /dev/sda5    # 开启该分区作为 swap
free                # 查看内存使用情况,或者使用 swapon -s
# swapoff /dev/sda5 # 关闭对应使用的分区
# swapon -a         # 根据 /etc/fstab 打开交换分区

# 使用 loop 挂载
dd if=/dev/zero of=/srv/loopdev bs=1M count=512                              # 制作大文件
mkfs.xfs -f /srv/loopdev                                                     # 格式化
mkdir -p /data/loop; blkid /srv/loopdev; mount -o loop UUID="..." /data/loop # 挂载
df /data/loop                                                                # 查看 /data/loop 的使用情况

# 修改 /etc/fstab 开机挂载内容
vim /etc/fstab
/dev/mapper/centos-root   /            xfs    defaults                      0 0
UUID="..."                /boot        xfs    defaults                      0 0
/dev/mapper/centos-home	  /home        xfs    defaults,usrquota,prjquota    0 0
/dev/mapper/centos-swap	  swap         swap   defaults                      0 0
UUID="..."                /data/xfs    xfs    defaults                      0 0
UUID="..."                swap         swap   defaults                      0 0
/srv/loopdev              /data/loop   xfs    defaults,loop                 0 0

3.6.Quota

  • EXT 的 quota 限额主要针对于整个文件系统,所以大多对挂载点进行设计;XFS 可以使用 project 模式,针对于个别目录来设计。

  • 启用 SELinux 时,在默认情况下,quota 仅能针对/home进行设置。不能对 root 设置 quota。

  • XFS 的 quota 是整合到文件系统内的。相比较du,XFS 下xfs_quota指令更快。

  • quota 可分别针对使用者、群组和个别目录(user、group、project)进行设置,但群组和个别目录不能同时设置。quota 可对 inode(文件数量)和 block(磁盘使用量)进行设置。

  • quota 的设置分 hard 和 soft。达到 hard 时,就不能继续使用磁盘。达到 soft 时会警告并给予宽限时间,在宽限时间内将使用容量降于 soft 以下会消除限制,否则超过宽限时间时会将 hard 设置为当前 soft。一般默认的宽限时间为 7 天。

  • XFS 的 quota 在挂载之初就宣告了,因此无法使用mount -o remount重新启动 quota 功能,必须写入/etc/fstab文件中。对于/etc/fstab中 quota 限制的项目主要有三项:

    • uquota/usrquota/quota:针对使用者账号设置。
    • gquota/grpquota:针对群组的设置。
    • pquota/prjquota:针对单一目录的设置,但是不可与 grpquota 同时存在。

    修改完/etc/fstab后测试挂载前,记得登出所有一般账号,否则无法卸载。

  • xfs_quota -x -c "statement" [mount_point],其中 statement 可以是:

    print,单纯列出目前主机内的文件系统参数等数据。

    df,与df指令一样的功能,可以添加-b(block)、-i(inode)、-h等参数。

    report,列出目前的 quota 项目,有-urg(user、group、project)及-bi等数据。

    state,说明目前支持 quota 的文件系统的信息,有没有启动相关项目等。

    如:

    xfs_quota -x -c "print"
    xfs_quota -x -c "df -h" /home
    xfs_quota -x -c "report -ubih" /home
    xfs_quota -x -c "state"
    

    xfs_quota -x -c "limit [-ug] b[soft|hard]=N i[soft|hard]=N name",设置 user、group 的 quota。

    xfs_quota -x -c "timer [-ug] [-bir] Ndays",设置宽限时间。

    限额目录,需要使用“专案名称,专案识别码”,专案识别码与目录关系保存在/etc/projects中,专案识别码与专案名称关系保存在/etc/projid中。专案名称使用前需要进行初始化。

  • 设置 quota 流程示例:

    • 设置用户与用户组 quota 示例:

      df -hT /home   # -h 参数将显示单位,-T 参数显示文件系统类型
      vim /etc/fstab
      
      /dev/mapper/centos-home /home xfs defaults,usrquota,grpquota 0 0
      
      umount /home
      mount -a
      mount | grep 'home'
      
      xfs_quota -x -c "state"
      xfs_quota -x -c "limit -u bsoft=250M bhard=300M meyok" /home
      xfs_quota -x -c "report -ubih" /home
      xfs_quota -x -c "limit -g bsoft=950M bhard=1G meyok" /home
      xfs_quota -x -c "report -gbih" /home
      xfs_quota -x -c "timer -ug -b 14days" /home
      xfs_quota -x -c "state" /home
      
    • 设置目录 quota 示例:

      df -hT /home   # -h 参数将显示单位,-T 参数显示文件系统类型
      vim /etc/fstab
      
      /dev/mapper/centos-home /home xfs defaults,usrquota,prjquota 0 0
      
      umount /home
      mount -a
      mount | grep 'home'
      
      echo "11:/home/meyok/test" >> /etc/projects
      echo "meyokprj_test:11" >> /etc/projid
      xfs_quota -x -c "project -s meyokprj_test" # 初始化专案名称
      xfs_quota -x -c "project -s print" /home
      xfs_quota -x -c "report -pbih" /home
      
      xfs_quota -x -c "limit -p bsoft=250M bhard=300M meyokprj_test" /home
      xfs_quota -x -c "report -pbih" /home
      
  • xfs_quota -x -c "statement" [mount_point]中 statement 还可以是:

    disableenable,暂时关闭、打开 quota 限制。

    off,完全关闭 quota,使用后只能重新挂载才能重新启动 quota。

    remove,移除 quota 限制设置,必须在off后才能执行

    如:

    xfs_quota -x -c "disable -up" /home
    xfs_quota -x -c "enable -up" /home
    xfs_quota -x -c "off -up" /home
    xfs_quota -x -c "remove -p" /home
    
  • 对于跨文件系统设置 quota 的 project 功能,可用链接在本文件系统中生成链接文件链接另一文件系统中的需要设置 quota 的文件,然后对链接文件设置 quota 即可。

3.7.RAID

  • RAID 技术可将各小磁盘组成大磁盘。

  • RAID 各的等级

    • RAID 0(等量模式,stripe):各磁盘分成等量的区块,名为 chunk。文件写入时按照 chunk 大小分割好,然后依次分布到各个小磁盘上。最小的磁盘放满了,该磁盘就不放了,只依序放到更大的磁盘上。

      此模式下,任何一块小磁盘损坏后都无法恢复。

    • RAID 1(映射模式,mirror):需要两个同样大小的小磁盘,否则以最小磁盘容量为主。这种模式会让文件分别保存在两块小磁盘上,小磁盘保存的内容相同都为整个原文件。因此感觉整体 RAID 容量少了 50%。

      此模式下,优点在于数据的备份,一块小磁盘损坏后,另一块小磁盘还有一样的数据可恢复。

    • RAID 1+0(或 RAID 0+1):即先让两块小磁盘RAID 1,所有RAID1在使用RAID 0模式(或先RAID 0,再RAID 1)。RAID 1+0 是目前存储厂商推荐的模式。

    • RAID 5:至少需要 3 块小磁盘。写入有点类似 RAID 0,但循环写入时,每颗磁盘还会加入一个同位检查数据(parity),这个数据会记录其它磁盘的备份数据。每个循环写入时,都会有部分的 parity 被记录下来,并且记录的 parity 每次都记录在不同磁盘。只有一块小磁盘顺坏后,可根据其它磁盘的检查码来重建原本磁盘内的数据。

      此模式下,RAID 的容量像是少了一块小磁盘。而 RAID 6 类似 RAID 5 但使用了两颗小磁盘容量用于存储 parity,因此可容许两块磁盘损坏。

  • 预备磁盘(spark disk)用于,当 RAID 内某块小磁盘损坏时,以预备磁盘代替该磁盘,进行 RAID 复原。

  • CentOS 提供软件磁盘整列为 mdadm 这套软件。这套软件会以 partition 或 disk 为磁盘的单位。软件磁盘阵列由于是系统仿真的,因此使用的设备文件名是系统的设备文件,文件名为/dev/md0/dev/md1……。

  • 软件磁盘阵列设置指令mdadm格式:

    mdadm --detail /dev/md0
    mdadm --create /dev/md[0-9] --auto=yes --chunk=NK --raid-devices=N --spare-devices=N /dev/sdx /dev/hdx...
    

    --detail,后面接哪个磁盘整列设备的详细信息。

    --create,为创建 RAID 的选项。

    --auto=yes,决定创建后面接的软件磁盘阵列设置,亦即/dev/md0/dev/md1……

    后面接的设备文件名总数必须等于--raid-devices--spare-devices总数。

  • 创建 RAID5 等级软件磁盘阵列示例:

    gdisk -l /dev/sda
    # Number  Start (sector)    End (sector)  Size       Code  Name
    # ...
    #    4        65026048        67123199   1024.0 MiB  FD00  Linux RAID
    #    5        67123200        69220351   1024.0 MiB  FD00  Linux RAID
    #    6        69220352        71317503   1024.0 MiB  FD00  Linux RAID
    #    7        71317504        73414655   1024.0 MiB  FD00  Linux RAID
    #    8        73414656        75511807   1024.0 MiB  FD00  Linux RAID
    
    # yum install -y mdadm
    mdadm --create /dev/md0 --auto=yes --level=5 --chunk=256K --raid-devices=4 --raid-devices=1 /dev/sda{4,5,6,7,8}
    mdadm --detail /dev/md0
    cat /proc/mdstat # 查看系统软件磁盘阵列的情况
    
    # 格式化为 XFS 文件系统,stripe(chunk)大小为 256K;4 个分区组成 RAID5 实际保存内容只有 3 个分区;数据宽度为 256k*3
    mkfs.xfs -f -d su=256k,sw=3 -r extsize=768k /dev/md0
    mkdir /srv/raid
    mount /dev/md0 /srv/raid
    df -Th /srv/raid
    
  • 仿真 RAID 错误的救援:

    mdadm --manage /dev/md0 --fail /dev/sda7   # 仿真 /dev/sda7 出错
    # 此时系统会启用 spare disk 那块并修复
    # 关闭 Linux,拔出 /dev/sda7,装上新的 /dev/sda7
    mdadm --manage /dev/md0 --remove /dev/sda7 # 从 RAID 中移除这块磁盘
    mdadm --manage /dev/md0 --add /dev/sda7
    
  • 新的 distribution 大多会自己搜寻/dev/md[0-9]然后在开机的时候给予设置好所需要的功能,不过还是建议修改以下配置文件。Software RAID 的配置文件在/etc/mdadm.conf中。

    mdadm --detail /dev/md0 | grep -i 'uuid'
    vim /etc/mdadm.conf
    
    ARRAY /dev/md0 UUID=...
    
    blkid /dev/md0 # 注意这个 UUID 与上面那个不一样
    vim /etc/fstab
    
    UUID=... /srv/raid xfs defaults 0 0
    
    umount /dev/md0; mount -a
    df -Th /srv/raid
    
  • 关闭软件 RAID:

    umount /srv/raid
    vim /etc/fstab
    
    #UUID=... /srv/raid xfs defaults 0 0
    
    # 覆盖掉 RAID 的 metadata 以及 XFS 的 superblock
    dd if=/dev/zero of=/dev/md0 bs=1M count=50
    mdadm --stop /dev/md0
    dd if=/dev/zero of=/dev/sda4 bs=1M count=10
    dd if=/dev/zero of=/dev/sda5 bs=1M count=10
    dd if=/dev/zero of=/dev/sda6 bs=1M count=10
    dd if=/dev/zero of=/dev/sda7 bs=1M count=10
    dd if=/dev/zero of=/dev/sda8 bs=1M count=10
    
    cat /proc/mdstat
    vim /etc/mdadm.conf
    
    #ARRAY /dev/md0 UUID=...
    

    上述中dd指令是用于分区重新规划,因为 RAID 的相关数据其实也会存一份在磁盘中,如果只是将配置文件删除并关闭了 RAID,但是分区没有重新规划,重新开机后还是会将 RAID 创建起来,只是可能会换个名字如/dev/md127

3.8.LVM

  • LVM 默认使用 4MB 的 PE 块。

  • LV 设备文件名通常指定为/dev/vgname/lvname的格式。

  • 通过交换 PE,将原本 LV 中的 PE 转移到其它设备中以降低 LV 容量,将其他设备中的 PE 加到此 LV 中以加大容量。

  • 数据写入 LV 时有两种方式:假如将/dev/sda1/dev/sda2这两个 partition 加入 VG 中

    • 线性模式(Linear):线性模式会在/dev/sda1容量用完后,/dev/sda2的硬盘才会使用。
    • 交错模式(triped):交错模式会把一笔数据分成两份,分别写入/dev/sda1/dev/sda2

    LVM 的主要用处时实现一个可以弹性调整容量大小的文件系统上,所以使用线性模式更好。交错模式类似 RAID 0,如果要强调性能与备份,那么就可以直接使用 RAID 而不是 LVM。

  • 创建 LVM 示例:

    • DIsk 阶段:

      gdisk -l /dev/sda
      # Number  Start (sector)    End (sector)  Size       Code  Name
      # ...
      #    4        65026048        67123199   1024.0 MiB  8E00  Linux LVM
      #    5        67123200        69220351   1024.0 MiB  8E00  Linux LVM
      #    6        69220352        71317503   1024.0 MiB  8E00  Linux LVM
      #    7        71317504        73414655   1024.0 MiB  8E00  Linux LVM
      #    8        73414656        75511807   1024.0 MiB  8E00  Linux LVM
      
    • PV 阶段:

      pvscan                     # 搜寻目前系统中任何具有 PV 的磁盘
      pvcreate /dev/sda{4,5,6,7} # 将实体分区创建为 PV
      pvscan
      pvdisplay /dev/sda4        # 更详细地列示出 PV 信息
      
    • VG 阶段:

      vgscan
      vgcreate -s 16M meyokvg /dev/sda{4,5,6} # 新建 VG
      vgscan
      pvscan
      vgdisplay meyokvg
      
      vgextend meyokvg /dev/sda7 # 向 VG 中添加一个 PV
      
    • LV 阶段:

      lvcreate -L 2G -n meyoklv meyokvg
      lvscan
      lvdisplay /dev/meyokvg/meyoklv
      
    • 文件系统阶段:

      mkfs.xfs /dev/meyokvg/meyoklv
      mkdir /srv/lvm
      mount /dev/meyokvg/meyoklv /srv/lvm
      df -hT /srv/lvm
      
  • 放大 LV 容量,XFS 和 EXT 都可以,但 XFS 不能缩小。放大是通过在文件系统中增加 block group 实现的,格式化的位置在于该设备后来新增的部分,设备前面已存在的文件系统没有变化。而新增的格式化过的数据,在反馈回原本的 superblock 而已。

  • 放大 LV 容量示例:

    vgdisplay meyokvg
    lvresize -L +500M /dev/meyokvg/meyoklv
    lvscan
    df -hT /srv/lvm
    # LV 虽然增大,但文件系统没有增加。
    xfs_info /srv/lvm   # 查看原本文件系统中 superblock 信息
    xfs_growfs /srv/lvm # 增大文件系统容量
    df -hT /srv/lvm
    
  • LVM thin Volume 创建出的 LV 使用大小一定不能超过其 thin pool LV 大小

  • 制作 LVM thin Volume:

    lvcreate -L 1G -T meyokvg/meyoktpool # 创建 meyoktpool thin pool LV,实际大小 1G
    lvs meyokvg
    
    lvcreate -L 10G -T meyokvg/meyoktpool -n meyokthin1 # 通过 meyoktpool LV 创建 meyokthin LV,虚拟大小 10G
    lvs meyokvg
    
    mkfs.xfs /dev/meyokvg/meyokthin1
    mkdir /srv/thin
    mount /dev/meyokvg/meyokthin1 /srv/thin
    df -hT /srv/thin
    
  • 快照区与被快照的 LV 必须要在同一个 VG 上(因为他们会共享相同的 PE)。不推荐使用 thin pool 快照。

    原始数据被修改后,对应 LV 中的 PE 会被移动到快照区的 PE,如果修改的 PE 量超过快照区的 PE,那么快照功能将失效。

  • 创建快照示例,为/etc/meyokvg/meyoklv创建快照:

    vgdisplay meyokvg                                    # 查看剩余多少 PE 未使用
    lvcreate -s -l 10 -n meyoksnap1 /dev/meyokvg/meyoklv # -l 指出使用多少 PE 作为快照区
    lvsidplay /dev/meyokvg/meyoklv                       # 可以看到 VG 量和原本 /dev/meyokvg/meyoklv 相同
    

    如果这时挂载快照 LV,那么看到的数据和原本一样:

    mkdir /srv/snapshot1
    mount -o nouuid /dev/meyokvg/meyoksnap1 /srv/snapshot1 # 由于不允许挂载相同的 UUID 设备,需要添加 -o 参数
    df -hT /srv/lvm /srv/snapshot1
    
  • 利用快照 LV 复原示例:

    # 更改以下 /dev/meyokvg/lvm LV 内容
    cp -a /usr/share/doc /srv/lvm
    rm -rf /srv/lvm/log
    rm -rf /srv/lvm/sysconfig
    lvdisplay /dev/meyokvg/meyoksnap1 # 查看快照区 PE 被用掉多少
    xfsdump -l 0 -L lvm1 -M lvm1 -f /home/lvm.dump /srv/snapshot1 # 备份
    
    # 恢复
    umount /srv/snapshot1
    lvremove /dev/meyokvg/meyoksnap1
    
    umount /srv/lvm
    mkfs.xfs -f /dev/meyokvg/meyoklv
    mount /dev/meyokvg/meyoklv /srv/lvm
    xfsrestore -f /home/lvm.dump -L lvm1 /srv/lvm
    

    之所以不直接格式化/dev/meyokvg/meyoklv再将/dev/meyok/meyoksnap1内容复制过去,是因为格式化时也会做快照,快照 LV 的 PE 大小可能不够。

  • 移除 LVM 示例:

    umount /srv/lvm /srv/thin /srv/snapshot1
    lvs meyokvg
    lvremove /dev/meyokvg/meyokthin1 /dev/meyokvg/meyoktpool
    lvremove /dev/meyokvg/meyoklv
    vgvhange -a -n meyokvg  # 这里将 testvg 修改为不具有 active 标志
    vgremove meyokvg
    pvremove /dev/sda{4,5,6,7}
    

4.文件管理

4.1.FHS

  • FHS(Filesystem Hierarchy Standard,文件系统结构层次标准):

    一些代表性的目录
    可分享的 不可分享的
    不变的 /usr(软件放置处) /etc(配置文件)
    /opt(第三方协力软件) /boot(开机与核心档)
    可变动的 /var/mail(使用者邮件信箱) /var/run(程序相关)
    /var/spool/news(新闻群组) /var/lock(程序相关)

    FHS 要求必须要存在的目录:

    • /bin:在单人维护模式下还能被操作的指令。
    • /boot:开机会使用到的文件。
    • /dev:设备与周边设备文件。
    • /etc:系统主要的配置文件。一般来说,这个目录下各文件属性可被一般使用者查询,但只有 root 有权修改。
    • /lib:开机时用到的函数库,以及在/bin//sbin/下面的指令会调用的函数库。
    • /media:可移除设备。包括软盘、光盘、DVD等设备暂时挂载于此。
    • /mnt:暂时挂载额外设备。
    • /opt:第三方协力软件。
    • /run:系统开机后所产生的各项信息。
    • /sbin:开机所需要的指令。
    • /srv:一些网络服务启动之后,这些服务所需要取用的数据目录。
    • /tmp:正在执行的程序暂时放置文件的地方。
    • /usr:第二层FHS。
    • /var:第二层FHS,主要为放置变动的数据。

    FHS 建议可以存在的目录:

    • /home
    • /lib<qual>
    • /root

    其他:

    • /lost+found:使用 EXT 文件系统格式才会有的一个目录。文件系统发生错误时,将一些遗失的片段放置到这个目录。
    • /proc:该目录本身是一个虚拟文件系统,放置的数据在内存中,不占用硬盘空间。
    • /sys:与/proc类似。
  • 根目录的..是根目录。

4.2.文件权限

  • rwx 对于文件夹指的是否能读到文件名、修改文件名、进入该目录(没有 x 无法进入目录执行程序)。

  • 文件特殊属性:

    • Set UID:出现在文件拥有者的 x 权限上。仅对二进制程序有效。执行者需要有 x 权限。

      SUID 权限仅在执行该程序的过程中有效,执行者将具有该程序拥有者 owner 的权限

      如:passwd具有 SUID 权限,用户使用passwd修改密码时临时获得 root 的权限,所以能修改/etc/passwd文件。

    • Set GID:出现在文件/目录拥有组的 x 权限上。

      对于文件 SGID 仅对二进制程序有效。执行者需要有 x 权限。执行者将具有该程序拥有者群组的权限。

      对于目录,使用者若对该目录有 rx 权限,可进入该目录,使用者在该目录下的有效群组变为该目录的群组;若还有 w 权限,使用者创建的新文件群组就为该目录的群组。

    • Sticky Bit:只对目录有效。使用者有 wx 权限时,使用者在该目录下创建的目录和文件只有自己和 root 才能删除。

    文件权限出现大写 S/T 说明没有 x 这个权限。

  • 文件类型简写说明:

    简写 含义
    d 目录
    - 文件
    l 链接文件
    b RAM 设备
    c 一次性读取设备(例如鼠标、键盘)
    s 数据接口文件(sockets)
    p 数据输送档(FIFO、pipe)
  • 默认创建文件/目录权限为 $ 666/777 - umask $,umask 默认设置在/etc/bashrc中(root 为 022,一般用户为 002),调用umask/umask 002可查看/修改。

4.3.常用文件相关指令

  • 查询文件内容可使用:cattacnlmorelessheadtailod

  • file {filename}:查看文件类型等信息。如属于 ASCII、data 或者 binary,有没有使用动态函数库等等。

  • chattr [+-=] [ASacdistu] file/dir,设置文件隐藏属性。

    A,存取此文件/目录时,atime 不会修改。

    S,对文件的任何修改将以同步方式写入磁盘。

    a,该文件只能增加数据,不能修改、删除数据,只有 root 可设置此属性。

    c,自动压缩该文件。读取时自动解压缩,存储时压缩后再存储。

    d,当 dump 程序执行时该文件/目录不会被 dump。

    i,此文件不能被删除、改名、设置链接、无法写入或新增数据,只有 root 可设置此属性。

    s,如果该文件被删除会完全移除出硬盘空间。

    u,与s相反,被删除其实数据内容还在硬盘,可用来救援该文件。

  • lsattr [-adR] file/dir,查询文件隐藏属性。

    a,也显示隐藏属性。

    d,如果后面是目录,仅显示目录本身属性而非目录中文件属性。

    R,连同子目录数据一同显示。

  • 搜索文件路径可以使用:whichwhereislocatefind寻找对应文件的路径,一般先用whereis/locate,实在找不到用find

    which,寻找 PATH 路径下的可执行文件的路径。

    whereis,寻找/bin/sbin下面的可执行文件以及/usr/share/man下面的 manual page 文件。

    locate,根据已创建的数据库/var/lib/mlocate里面的数据寻找对应文件路径(文件名包含就行)。

    该数据库每天一更新,使用updatedb可更新 locate 数据库(该指令会读取/etc/updatedb.conf中的设置,然后去硬盘里面进行搜寻文件名的动作更新数据库文件)。

    find [PATH] [option] [action],在硬盘中寻找文件(其本身就搜索次目录)。如:

    find /usr/bin /usr/sbin -perm /7000 -exec ls -l {} \;
    
  • tar [-z|-j|-J] [-c|-t|-x] [-v] -f {filename} [-C {directory}] [-P]用于将多个文件打包/分解成一个文件,同时可以压缩/解压缩。

    文件扩展名为Zzipgzbz2xz分别表示由 compress、zip、gzip、bzip2、xz 程序压缩后的文件;文件扩展名为tar表示打包文件。前者后 3 种和tar扩展可联合起来一起表示相关信息。

    -z-j-J,分别表示压缩程序为 gzip、bzip2、xz。

    -c-t-x,分别表示压缩、查看包内文件名、解压缩。

    -v,显示压缩/解压缩处理的文件名。

    -C,用在解压缩指明解压缩到的目录。

    -P压缩时,默认会将根目录删除以方便解压缩时指定加压目录,添加此参数不会删除根目录。

    只解压缩某个文件可以使用如下方式:

    tar -jtv -f /root/etc.tar.bz2 | grep 'shadow'
    tar -jxv -f /root/etc.tar.bz2 etc/shadow
    
  • printf '打印格式' 实际内容,用于格式化打印内容。如:

    printf '%s\t %s\t %s\t %s\t %s\t \n' $(cat printf.txt)
    printf '%10s %5i %5i %5i %8.2f \n' $(cat printf.txt | grep -v Name)
    
  • ulimit [-SHacdfltu] [配额],设置用户对文件使用的限制。

    -S-H,警告、严格设置。

    -a,不加任何其他参数,显示目前用户的限制额度。

    -c,限制核心文件(程序出错时系统可能将内存信息写入文件,该文件称为核心文件)的最大容量。

    -f,此 Shell 可创建最大文件大小(一般设置为 2GB),单位 KBytes。

    -d,程序可使用最大断裂内存(segment)容量。

    -l,可用于锁定的内存量。

    -t,可使用的最大 CPU 时间,单位秒。

    -u,单一使用者可以使用的最大程序数量。

    如:

    ulimit -a
    ulimit -f 10240
    

    -f设置只能继续变小。

    复原ulimit设置最简单方法是重新登录。

4.4.XFS 文件系统的备份与还原

  • xfsdump,用于备份整个 XFS 文件系统,它要求该文件系统已被挂载,备份下来只能由xfsrestore解析,通过文件系统的 UUID 分辨各个备份文件,不能备份两个具有相同 UUID 的文件系统。

    xfsdump是积累备份。第一次备份是完整备份为 level 0,此后备份为积累备份为 level 1、level 2……,level 记录放置于/var/lib/xfsdump/inventory中。

    如备份/boot

    xfsdump -l 0 -L boot_all -M boot_all -f /srv/boot.dump /boot
    ll /srv/boot.dump
    ll /var/lib/xfsdump/inventory
    xfsdump -I
    
    dd if=/dev/zero of=/boot/testing.img bs=1M count=10
    xfsdump -l 1 -L boot_2 -M boot_2 -f /srv/boot.dump1 /boot
    ll /srv/boot*
    xfsdump -I
    

    -l参数指定备份等级,-L参数记录备份的 session 标头(这里可写文件系统的简易说明),-M参数记录存储的媒体标头(这里可写此媒体的简易说明),-f参数指定产生的文件,-I参数从/var/lib/xfsdump/inventory列出目前备份的信息状态。

  • xfsrestore,用于 XFS 系统,需要积累复原。

    如复原/boot

    xfsrestore -I
    xfsrestore -f /srv/boot.dump -L boot_all /boot # 这里复原同名会被覆盖,其他新文件会被保留
    xfsrestore -f /srv/boot.dump1 /boot
    

    如果仅复原某一个文件,可以使用如下指令:

    xfsrestore -f /srv/boot.dump -L boot_all -s grub2 /boot
    

    如果不知道复原的文件名,可使用交互模式:

    xfsrestore -f /srv/boot.dump -i /boot
    ->ls
    ->add grub
    ->add grub2
    ...
    ->extract
    

4.5.登录文件

  • 登录文件的权限通常是设置为仅有 root 能够读取而已。

  • 常见的几个登录文件(在/var/log/下):

    • boot.log:开机的时候系统核心会去侦测与启动硬件,接下来开始各种核心支持的功能启动等。这些流程都会记录在/var/log/boot.log里面。不过这个文件只会存这次开机启动的信息,前次的不会保留下来。
    • cron:crontab 调度是否被执行、进行过程有无错误、/etc/crontab是否撰写正确。
    • dmesg:记录系统在开机的时候核心侦测过程所产生的各项信息。
    • lastlog:记录系统上面所有账号最近一次登录系统时的相关信息。lastlog指令就是利用这个文件的记录信息来显示的。
    • maillogmail/*:记录邮件的往来信息,其实主要是记录 postfix(SMTP 协定提供者)与 dovecot(POP3 协定提供者)所产生的讯息。
    • messages:几乎系统发生的错误讯息(或者是重要的信息)都会记录在这个文件中。
    • secure:基本上,只要牵涉到“需要输入账号密码”的软件,那么当登录时(不管登录正确或错误)都会被记录在此文件中。包括系统的 login 程序、图形接口登录所使用的 gdm 程序、su、sudo 等程序、还有网络连线的 ssh、telnet 等程序,登录信息都会被记载在这里。
    • wtmpfaillog:这两个文件可以记录正确登录系统中的账号信息(wtmp)与错误登录时所使用的账号信息(faillog)。last指令就是读取wtmp来显示的。
    • httpd/*samba/*:不同的网络服务会使用它们自己的登录文件来记载它们自己产生的各项讯息。上述目录则是个别服务所制定的登录文件。

    不同的 Linux distributions 通常登陆文件的文件名不会相同。

  • 登录文件有两种方式产生:软件开发商自行定义写入的登录文件与相关格式;由 Linux distribution 提供的登录文件管理服务来统一管理。

  • 基本上,系统由 systemd 所管理,那所有经由 systemd 启动的服务,如果在启动会结束的过程中发生一些问题或者是正常的讯息,就会将该讯息由 systemd-journald.service 以二进制的方式记录下来,之后再将这个讯息发送给 rsyslog.service 作进一步的记载。

    systemd-journald.service 的记录主要都放置于内存中。我们也能够通过journalctl以及systemctl status unit.service来查看各个不同服务的登录文件。

    CentOS5 以前,要达成 syslog 的功能是由一支名为 syslogd 的 daemon 来完成的,从 CentOS6 以来则是通过 rsyslogd 这个 daemon。

  • 登录文件条目的一般格式:

    日期及时间 来源主机名 启动此事件的服务名/指令/函数名 该讯息的实际数据内容
    
  • rsyslogd 针对各种服务与讯息记录在某些文件的配置文件就是/etc/rsyslog.conf,格式为:

    服务名称[.=!]讯息等级 讯息记录的文件名或设备或主机
    
    • 服务名称:有 kern(kernel)、user、mail、daemon、auth、syslog、lpr、news、uucp、cron、authpriv、ftp、local0-local7

      相对序号 服务类别 说明
      0 kern(kernel) 核心产生的讯息,大部分都是硬件侦测以及核心功能的启用
      1 user 使用者层级所产生的信息,例如用户使用logger指令来记录登录文件的功能
      2 mail 与邮件收发相关的讯息
      3 daemon 主要是系统的服务所产生的讯息,例如 systemd
      4 auth 主要与认证/授权有关的机制,例如 login、ssh、su
      5 syslog 就是由syslog相关协定产生的信息,其实就是rsyslogd这支程序本身产生的信息
      6 lpr 打印相关的信息
      7 news 与新闻群组服务器有关的东西
      8 uucp 全名为 Unix to Unix Copy Protocol,早期用于 unix 系统间的程序数据交换
      9 cron 就是例行性工作调度 cron/at 等产生讯息记录的地方
      10 authpriv 与 auth 类似,但记录较多账号私人的信息,包括pam模块的运行等
      11 ftp 与 FTP 通讯协定有关的讯息输出
      16-23 local0-local7 保留给本机用户使用的一些登陆文件讯息,较常与终端机互动
    • 讯息等级数值高到低为:7debug、6info、5notice、4warning(warn)、3err(error)、2crit、1alert、0emerg(panic)。除了 0-6 间还有两个比较特殊的等级 debug(错误侦测等级)和 none(不需登录等级)。

    • 服务名称与讯息等级之间的连号有:

      • .:代表比后面还要严重的等级。
      • .=:代表所需要的等级就是后面接的等级。
      • .!:代表不等于,即是除了该等级外的其他等级都记录。

    rsyslog.conf示例:

    mail.*						-/var/log/maillog
    news.*;cron.*				/var/log/cronnews
    *.*;news,cron,mail.none		/var/log/messages # 或者 *.*;news.none;cron.none;mail.none
    

    其中的“-”,是由于邮件产生的信息多,因此希望先将邮件产生的信息存储在内存中,等到数据量够大了才一次性的将所有数据都填入磁盘内。

  • rsyslogd 的登录文件只有被编辑过(使用 vi/vim)就无法继续写入。可以重新启动 rsyslog.service 服务来让它继续提供服务。

  • 为登录文件添加 a 属性可以一定程度上可以保护登录文件的信息安全,但进行登录文件轮替时(logrotate),将会无法移动该登录文件的文件名。

    chattr +a /var/log/admin.log
    chattr -a /var/log/admin.log
    
  • rsyslogd 提供了登录文件服务器功能,可以让 client 的登录文件上传到 server 中。配置方法如下:

    对于 server:

    ip addr # 192.168.1.100
    vim /etc/rsyslog.conf
    
    $ModLoad imudp
    $UDPTCPServerRun 514
    
    $ModLoad imtcp
    $InputTCPServerRun 514
    
    systemctl restart rsyslog.service
    netstat -tunlp
    

    对于 client:

    vim /etc/rsyslog.conf
    
    *.*		@192.168.1.100
    
    *.*		@@192.168.1.100
    
    systemctl restart rsyslog.service
    
  • logrotate 轮替实际是通过 cron/ancron 实现的,/etc/cron.daily/logrotate保存了每天要进行的登录文件轮替行为。

  • logrotate 的配置文件/etc/logrotate.conf设置默认值,/etc/logrotate.d/*中设置细部值,然后被读入到/etc/logrotate.conf覆盖默认值。

    一般来说,各服务的登录文件轮替设置单独配置成一个文件,放在/etc/logrotate.d/中。

    /etc/logrotate.conf中的内容:

    weekly							# 默认每周进行一次rotate工作
    rotate 4						# 保留几个登录文件
    create							# 由于登录文件被更名,因此创建一个新的来继续存储之意
    dateext							# 让被轮替的文件名加上日期作为文件名
    # compress						# 被更动的登录文件是否需要压缩
    include /etc/logrotate.d		# 将该目录中的所有文件都读进来进行rotate工作
    /var/log/wtmp {					# 仅对/var/log/wtmp所设置的参数
    	monthly
    	create 0664 root utmp		# 指定新建文件的权限于所属账号、群组
    	minsize 1M					# 文件大小一定要超过1M后才进行rotate
    	rotate 1					
    }
    /var/log/btmp {
        missingok
        monthly
        create 0600 root utmp
        rotate 1
    }
    

    /etc/logrotate.d/syslog中的内容:

    /var/log/cron
    /var/log/maillog
    /var/log/messages
    /var/log/secure
    /var/log/spooler
    {
        missingok
        sharedscripts
        postrotate
            /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
        endscript
    }
    

    其中,被处理的登录文件绝对名放在最前,进行轮替的参数设置使用{}包括起来,执行脚本被放在 sharedscripts 与 endscript 之中,prerotate 与 postrotate 分别指出在执行 logrotate 之前和之后的指令。

    假如登录文件有 a 隐藏属性,logrotate 轮替可能无法成功修改文件名,可利用 prerotate 与 postrotate 参数解决这个问题,如:

    chattr +a /var/log/admin.log
    vim /etc/logrotate.d/admin
    
    /var/log/admin.log
    {
    	monthly
    	size=10M
    	rotate 5
    	compress
    	sharedscripts
    	pretrotate
    		chattr -a /var/log/admin.log
    	endscript
    	sharedscripts
    	postrotate
    		/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null | true
    		/usr/bin/chattr +a /var/log/admin.log
    	endscript
    }
    
  • rsyslogd 必须在开机完成并且执行了 rsyslogd 后,登录文件才会开始记录。要记录系统在开机过程、启动服务的过程中的信息,在以前核心还得自己产生一个 klogd 服务,然后等到 rsyslogd 启动后传送给他处理。但现在 systemd 是核心唤醒的第一支执行的软件,他可主动调用 systemd-journald 来协助记载登录文件,上述信息可被直接记录到 systemd-journald 里去。

    systemd-journald 是内存的登陆文件记录方式,它以文件型态被放在/run/log/下面。

    /run在 CentOS7 其实是内存内的数据,所以重新开机后,下面的数据就被刷新了

  • 使用journalctl查询 systemd-journald.service 的数据:

    journalctl
    journalctl --since "2015-08-08 00:00:00" --until "2015-08-19 00:00:00"
    journalctl --since today
    journalctl --since yesterday --until today
    journalctl _SYSTEMD_UNIT=crond.service -n 10		# 列出对应unit的最新10条
    journalctl _COMM=su _COMM=login -n 10				# 列出su、login执行的登陆文件讯息,最新10条
    journalctl -p err									# 列出等级为err的登陆文件讯息
    journalctl SYSLOG_FACILITY=4 SYSLOG_FACILITY=10		# 列出auth、authpriv相关的登陆文件讯息
    journalctl -f										# 以实时变化列出,结束使用ctrl+c
    
  • logger指令将数据存储到登陆文件,格式为:logger [-p 服务名称.等级] "讯息"。如logger -p user.info "I will check logger command"

  • systemd-journald 的配置文件主要参考/etc/systemd/journald.conf的内容。

  • 保存journalctl所读取的登陆文件,需要创建/var/log/journal目录:

    mkdir /var/log/journal
    chown root:systemd-journal /var/log/journal
    chmod 2775 /var/log/journal
    systemctl restart systemd-journald.service
    

    不过既然有 rsyslog.service 以及 logrotate,建议 journald.service 产生的登录文件放在/run/log下。

  • logwatch 会每天分析一次登录文件,并且将数据以 email 的格式发送给 root。

5.程序管理

5.1.例行性工作调度

  • at是可以处理仅执行一次就结束调度的指令,新版 distributions 可能默认并没有启动其守护进程 atd。

    yum install -y at
    
  • at指令产生所运行的工作,会以文本方式保存在/var/spool/at内。

  • 使用/etc/at.allow/etc/at.deny进行 at 的使用限制。如果有/etc/at.allow,只有写在这个文件中的用户才能使用at;如果没有/etc/at.allow,有/etc/at.deny,没有写在这个文件中的用户才能使用at;两个文件都没有,只有 root 才能使用at

  • at指令示例:

    at 23:00 2015-08-04
    at> /bin/sync
    at> /bin/sync
    at> /sbin/shutdown -h now
    at> <EOT> # <ctrl>+d
    
    atq     # 查看 at 工作条目
    at -c 1
    atrm 1  # 删除第一个 at 工作
    
  • at会进入另一个 at Shell 执行指令,所以下达指令最好使用绝对路径指令。任务执行时的目录是at指令下达时的目录。stdout 和 stderr 会被传送到执行者的 mailbox 中(没有信息输入则不发送,可使用-m参数强制发送)。

  • batch是利用at来进行指令的下达的,它再 CPU 工作负载小于 0.8 时才进行所下达的任务。CentOS7 下batch已不支持时间参数。

    如:

    batch
    at> /usr/bin/updatedb
    at> <EOT>
    
  • atcrontab是按每分钟检测工作是否应该执行。


  • crontab这个指令所设置的工作会循环的一直进行下去。cron 除了可以使用指令执行外,亦可编辑/etc/crontab来支持。其守护进程为 crond,该服务默认启动。

  • crontab能否使用与at类似,可在/etc/cron.allow/etc/cron.deny中配置。

  • crontab产生的任务保存在/var/spool/cron中,以账号作为判别。

  • crontab执行的每一项工作会被保存在/var/log/cron这个登陆文件中,确定 Linux 是否被植入木马可查看这个文件看看。

  • crontab [-u usename] [-l|-e|-r]控制 cron 任务。

    -u,仅 root 可使用,为指定用户编辑 cron 任务。

    -l,参看 cron 任务内容。

    -e,编辑 cron 任务。

    -r,删除所有 cron 任务。

    如:

    crontab -e
    
    */5 * * * * /home/meyok/test.sh
    

    其格式为:

    分 时 日期 月份 星期 指令
    

    指令下达最好使用绝对路径。星期和月日不要同时设置。

  • crontab -e的指令其实是使用/usr/bin/crontab这个可执行文件。

  • 一般来说,cron 默认有三个地方会有可执行脚本配置文件:/etc/crontab/etc/cron.d/*/var/spool/cron/*

    • /etc/crontab,放置系统的例行性任务。

      其中MAILTO=root表明/etc/crontab中例行性工作的指令发送错误时,或者工作有 stdout、stderr 应该发送的 mail 给 root。

      /etc/crontab的 cron 任务格式与crontab -e指令编写格式类似:

      分 时 日期 月份 星期 执行者 指令
      

      由于 cron 任务是读到内存中的,修改完该文件可能不会马上执行,需重启 crond 守护进程。

    • /etc/cron.d/*,放置软件的 cron 定时任务。

      /etc/cron.d/0hourly中含有如下 cron 任务:

      01 * * * * root run-parts /etc/cron.hourly
      

      run-parts /etc/cron.hourly的作用是,会在 5 分钟内随机选择一个实现执行/etc/cron.hourly/下所有可执行文件。


  • anacron 可以主动帮助时间到了但没执行的调度,anacron 其实是个程序而非服务。每小时被 crontab 执行一次的可执行文件/etc/cron.hourly/0anacron,会执行/usr/sbin/anacron -s

  • anacron 配置文件/etc/anacrontab内容:

    # /etc/anacrontab: configuration file for anacron
    
    # See anacron(8) and anacrontab(5) for details.
    
    SHELL=/bin/sh
    PATH=/sbin:/bin:/usr/sbin:/usr/bin
    MAILTO=root
    # the maximal random delay added to the base delay of the jobs
    RANDOM_DELAY=45
    # the jobs will be started during the following hours only
    START_HOURS_RANGE=3-22
    
    #period in days   delay in minutes   job-identifier   command
    1       5       cron.daily              nice run-parts /etc/cron.daily
    7       25      cron.weekly             nice run-parts /etc/cron.weekly
    @monthly 45     cron.monthly            nice run-parts /etc/cron.monthly
    

    /var/spool/anacron/*中记录了最近执行 anacron 任务的时间戳,当前时间与该时间戳的差值大于对应/etc/anacrontab中 period in days 时,就会执行对应的run-parts /etc/cron...指令。

  • 所以,每天、每周、每月一定要执行的二进制文件放在/etc/cron.daily//etc/cron.weekly//etc/cron.monthly/

5.2.工作管理

  • 背景工作不能使用 <ctrl>+c 终止,背景执行工作不能等待 terminal/Shell 输入。

  • jobs [-l],查看背景工作状态-l参数查看 PID。“+”代表代表最近被放到背景的工作号码,“-”代表第二近。

  • <ctrl>+z,暂停当前前景工作并放入背景。

  • fgfg -fg %1,将背景工作拿到前景继续执行。

    bg %3,将暂停的背景工作继续在背景执行。

  • kill -9 %1kill -15 %1,前者强制结束工作,后者正常结束工作(默认)。

    查看 signal:

    kill -l
    
  • nohup 可以让你在离线或登出系统后,还能让工作继续执行。nohup 并不支持 Bash Shell 内置的指令。其输出讯息会在~/nohup.out

5.3.进程管理

  • ps -l,查询当前 Bash Shell 下相关的进程,其字段解释:

    • F:process flags,说明这个程序的总结权限。为 4 表示权限为 root,为 1 表示此子程序仅 fork 未 exec。

    • S:STAT,表明程序状态。

      • R:表示正在运行。

      • S:表示正在睡眠状态(idle),可被唤醒(signal)。

      • D:不可被唤醒的睡眠状态,通常这支程序在等待 I/O 情况。

      • T:停止状态,可能是在工作控制或出错(traced)状态。

      • Z:Zombie,僵尸状态,程序已终止但无法被移除内存之外。

    • UID/PID/PPID。

    • C:代表 CPU 使用率,单位为百分比。

    • PRI/NI:Priority/Nice,被 CPU 所执行的优选顺序,越小越先。

    • ADDR/SZ/WCHAN:与内存有关。ADDR 是 kernel function,指出该程序在内存的哪个部分,如果是个 running 程序一般会显示”-“。SZ 代表此程序用掉多少内存。WCHAN 表示目前程序是否运行中(“-”)。

    • TTY:登录者终端机位置,若为远程登录则使用动态终端接口(pts/n)。

    • TIME:实际花费 CPU 的时间。

    • CMD。

    ps -aux,查看系统所有程序,其字段解释:

    • USER、PID、%CPU、%MEM。
    • VSZ:该 process 使用的虚拟内存量(KBytes)。
    • RSS:该 process 占用的固定内存量(KBytes)。
    • TTY、STAT。
    • START:该 process 触发启动的时间。
    • TIME、COMMAND。

    ps -lA,列出所有程序。

    ps -axjf,列出类似程序树的程序显示。

    列出的程序中发现 CMD 后面有<defunct>,就代表为僵尸进程。通常僵尸进程无法管控,而直接交给 systemd 这支程序负责,它是系统的第一支程序。

  • top [-d 数字] | top [-bnp],动态观察程序的变化。

    -d,指定几秒刷新一次,默认 5。

    -b,以批次方式执行。-n-b搭配,表示需要进行几次 top 的输出结果。

    -p,指定PID。

  • pstree [-A|U] [-up],查看程序树。-A/-U表明以 ASCII/万国码字符连接。-u-p参数表示显示 username、pid。

  • killall [-iIe] [command_name],根据程序 kill。如:

    killall -1 rsyslogd # 给予 rsyslogd 这个指令启动的 PID 一个 SIGHUP 的讯号
    killall -9 httpd    # 终止以 httpd 启动的所有程序
    killall -i -9 bash  # 以交互方式
    
  • PRI 是核心动态调整的,使用者无法直接调整 PRI 值。$ PRI(new) = PRI(old) + nice $。nice 值可取 -20~19,root 随意调整自己与其他人的 nice 值,一般使用者只能调整自己的 nice 值,且不能为负数,且只能调大。nice 指令nice [-n 数字] command,renice 指令renice [number] PID。nice 值是会在父子进程中传递。

  • free,观察内存使用情况。

  • uname,查阅系统与核心相关信息。

  • uptime,观察系统启动时间与工作负载。

  • netstat [-atunlp],追踪网络或插槽挡。

    -a,将目前系统上所有的连接、监听、Socket 数据都列出来。

    -t,列出 TCP 网络封包的数据。

    -u,列出 UDP 网络封包的数据。

    -n,不以程序的服务名称,以 port 来显示。

    -l,列出目前正在监听的网络服务。

    -p,列出该网络服务的程序 PID。

    netstat输出分成两部分:

    • 网络之间连线,其字段解释为:

      • Proto,网络的封包协议,主要是 TCP、UDP。
      • Recv-Q:非由使用者程序链接到此 socket 的复制的总 Bytes 数。
      • Send-Q:非由远程主机传送过来的 acknowledged 总 Bytes 数。
      • Local Address:本地端的 IP:port 情况。
      • Foreign Address:远程主机的 IP:port 情况。
      • State:连线状态,主要有创建(ESTABLISED)和监听(LISTEN)。

      其中本地 IP 为 127.0.0.1 的只对本机开放,0.0.0.0 或 ::: 的代表对整个 Internet 开放。

    • 本地程序之间通过 socket file,其字段解释为:

      • Proto,一般就是 Unix。
      • RefCnt,连接到此 socket 的程序数。
      • Flags,连线的旗标。
      • Type,socket 存取的类型,主要有确认连线的 STREAM 与不需确认的 DGRAM 两种。
      • State,若为 CONNECTED 表示多个程序之间已经连线建立。
      • Path,连接到此 socket 的相关程序路径,或者是相关数据输出的路径。
  • 所有核心侦测的讯息,不管是开机时候还是系统运行过程中,反正只要是核心产生的讯息,都会被记录到内存中的某个保护区段。dmesg指令就能够将该区段的讯息读出来。

  • vmstat,动态了解系统资源的运行。

  • 基本上,目前主机上面的各个程序的 PID 都是以目录的型态存在于/proc/中。其中cmdline为这个程序被启动的指令串,environ为这个程序的环境变量内容。如果是针对于整个 Linux 系统相关的参数在/proc/下。

  • fuser [-umv] [-k [i] [-signal]] file/dir可让我们了解到某个文件(或文件系统)目前正在被哪些程序所利用。如:

    fuser -uv .
    
    fuser -muv /home
    umount /home
    fuser -mki /home
    
    yum install -y psmisc
    
  • lsof [-aUu] [+d],列出被程序所打开的文件文件名。如:

    lsof
    lsof -u root -a -U
    lsof +d /dev
    
  • pidof [-sx] program_name,找出某支正在执行的程序的 PID。如:

    pidof systemd rsyslogd
    

5.4.SELinux

  • 传统 rwx 权限是通过 DAC 管控,主体是用户;而 SELinux 是通过 MAC 方式来空管程序,它控制的主体是程序,目标是该程序能否读取的文件资源。

  • 在 SELinux 控制下,主体(程序)获取目标(文件系统)时,主体程序首先需要通过 SELinux 政策内的规则放行后,还要与目标资源进行安全性文本比对。

    SELinux 的政策有三种:

    • targeted:针对网络服务限制较多,针对本机限制较少,是默认的政策。
    • minimum:由 targeted 修订而来,仅针对选择的程序来保护。
    • mls:完整的 SELinux 限制,限制方面较为严格。

    sestatus,查看 SELinux 政策等信息。

    主体程序在内存中,其安全性文本的存入与其同在(可通过ps -eZ查看),而文件的安全性文本在 inode 中(可通过ls -Z查看)。安全性文本主要由冒号分隔的三个字段组成:

    • Identify:身份识别。

      unconfined_u 指不受限用户。一般指该文件来自于不受限的程序产生的,如 login shell 的 Bash Shell 程序产生的文件。

      system_u 系统用户。指该文件是系统自己产生的文件。

    • Role:角色。

      object_r 代表的是文件或目录等文件资源。

      system_r 代表的是程序。一般使用者也会被指定称为 system_r。

    • Type:类型。基本上一个主体程序能否读取到这个文件资源与类型相关。而类型字段在文件与程序的定义不太相同,分别是:

      • type:在文件资源上被称为类型。
      • domain:在主体程序上被称为领域。

      domain 需要与 type 搭配,则该程序才能顺利地读取文件资源。

  • SELinux 运行的三种模式:enforcing 强制模式、permissive 宽容模式(SELinux 不匹配会有警告但不会限制 domain/type 的存取,常用于 SELinux 的 debug)、disabled 关闭。

    getenforce,获取 SELinux 的运行模式。

    setenforce [0|1],修改 SELinux 运行模式为 permissive/enforing。

    从 disabled 切换到 enforcing 之后,可能有一堆服务无法正确启动。最简单的解决办法是设置为 permissive 并使用restorecon -Rv /重新还原所有 SELinux 设置。

  • /etc/selinux/config,SELinux 的安全政策与运行模式的配置文件。

  • getsebool -asestatus -b获取系统上 SELinux 的全部政策规则。

    了解这些规则限制内容可通过 seinfo 等工具。

    yum install -y setools-console

    seinfo [-Atrub],其中:

    -A,列出 SELinux 的状态、规则布尔值、身份识别、角色、类别等所有信息。

    -u,列出 SELinux 的所有身份识别(Identify)种类。

    -r,列出 SELinux 的所有角色(Role)种类。

    -t,列出 SELinux 的所有类别(Type)种类。

    -b,列出所有规则的种类。

    seinfo
    #Statistics for policy file: /sys/fs/selinux/policy
    #Policy Version & Type: v.31 (binary, mls)
    
    #   Classes:           130    Permissions:       272
    #   Sensitivities:       1    Categories:       1024
    #   Types:            4793    Attributes:        253
    #   Users:               8    Roles:              14
    #   Booleans:          316    Cond. Expr.:       362
    #   Allow:          107834    Neverallow:          0
    #   Auditallow:        158    Dontaudit:       10022
    #   Type_trans:      18153    Type_change:        74
    #   Type_member:        35    Role allow:         37
    #   Role_trans:        414    Range_trans:      5899
    #   Constraints:       143    Validatetrans:       0
    #   Initial SIDs:       27    Fs_use:             32
    #   Genfscon:          103    Portcon:           614
    #   Netifcon:            0    Nodecon:             0
    #   Permissives:         0    Polcap:              5
    

    sesearch [-A] [-s 主体类别] [-t 目标类别] [-b 布尔值],其中:

    -A,列出后面数据中,允许“读取或放行”的相关数据。

    -t,后面还要接类别,如-t httpd_t

    -b,后面还要接 SELinux 的规则,如-b httpd_enable_ftp_server

    如:

    # 找寻 crond_t 领域的主体程序能读取的文件 SELinux type
    sesearch -A -s crond_t | grep 'spool'
    #...
    #allow crond_t system_cron_spool_t : file { ioctl read ...
    #allow crond_t system_cron_spool_t : dir { ioctl read ...
    #allow crond_t cron_spool_t : file { ioctl read write ...
    #allow crond_t cron_spool_t : dir { ioctl read write ...
    #allow crond_t user_cron_spool_t : lnk_file { read getattr } ;
    #...
    
    cd ~ && touch checktime && mv checktime /etc/cron.d
    ll -Z /etc/cron.d/checktime
    # unconfined_u:object_r:admin_home_t
    ps -eZ | grep 'crond'
    # system_u:system_r:crond_t
    sesearch -A -s crond_t | grep 'admin_home_t'
    
    semanage boolean -l | grep 'httpd_enable_homedirs'
    # SELinux boolean                State Default  Description
    # httpd_enable_homedirs          (off  ,  off)  Allow httpd to enable homedirs
    # httpd_enable_homedirs 的功能是允许 httpd 程序去读取使用者主文件夹
    sesearch -A -b httpd_enable_homedirs
    
  • setsebool [-P] SELinux_boolean [0|1],修改 SELinux 规则的布尔值。其中-P参数会写入到配置文件中使得修改在以后依然有效。如:

    getsebool httpd_enable_homedirs
    setsebool -P httpd_enable_homedirs 1
    getsebool httpd_enable_homedirs
    
  • chcon 手动修改文件的 SELinux type:

    chcon [-R] [-t type] [-u user] [-r role] file
    chcon [-R] --reference=范例档 file
    

    如:

    chcon -v --reference=/etc/cron.d/0hourly /etc/cron.d/checktime
    

    restorecon 让文件恢复为默认的 SELinux type:

    restorecon [-Rv] file/dir
    

    如:

    restorecon -Rv /etc/cron.d
    
  • 文件的默认 SELinux type 可通过 semanage 设置:

    semanage {login|user|port|interface|fcontext|translation} -l
    semanage fcontext -{a|d|m} [-first] file_spec
    

    如:

    semanage fcontext -l | grep -E '^/etc |^/etc/cron' # 查询 /etc、/etc/cron.d 默认的 SELinux type
    
    semanage fcontext -l | grep '^/srv'                               # var_t
    mkdir /srv/mycron
    cp /etc/cron.d/checktime /srv/mycron
    ll -dZ /srv/mycron /srv/mycron/checktime                          # var_t
    
    semanage fcontext -a -t system_cron_spool_t "/srv/mycron(/.*)?"   # 修改 /srv/mycron 及其子目录下文件默认 SELinux type
    semanage fcontext -l | grep '^/srv/mycron'                        # system_cron_spool_t
    
    restorecon -Rv /srv/mycron
    
  • setroubleshoot 服务会将关于 SELinux 的错误讯息与克服方法记录在/var/log/messages/var/log/setroubleshoot/*中。该服务需要两个软件 setroubleshoot 与 setroubleshoot-server。原本的 SELinux 信息本来是以 auditd 与 setroubleshootd 服务来记录的,CentOS6 后将两者整合在 auditd 中了,并没有 setroubleshootd,因此安装完 setroubleshoot-server 需要重启 auditd。

    yum install -y setroubleshoot
    

    CentOS 对 setroubleshootd 的运行方式是:先由 auditd 调用 audispd 服务,audispd 服务启动 sedispatch 程序,sedispatch 程序将原本的 auditd 讯息转成 setroubleshootd 讯息,进一步存储下来的。

5.5.Daemon

  • System V 版本下,启动服务管理的方式是 init 脚本程序。系统核心调用的第一张程序是 init,然后 init 去唤起所有的系统所需要的服务。

    • 所有的服务启动脚本放在/etc/init.d/下,需要对其操作时使用如下指令

      /etc/init.d/daemon [start|stop|restart|status]
      
    • init 下 daemon 依据是独立启动或被一只总管程序分为两大类:

      • 独立启动模式(stand alone):服务独立启动,直接常驻于内存。
      • 总管程序(super daemon):由特殊的 xinetd 或 inetd 这两个总管程序提供 socket 对应或 port 对应的管理。xinetd 又被称为 super daemon。
    • daemon 是可能会有相依性的。init 在管理员自己手动处理服务时,是没有办法协助相依服务的唤醒的。

    • init 可根据使用者自订的执行等级(runlevel)来唤醒不同的服务,基本上有 7 个执行等级,比较重要的是:1 单人维护模式、3 纯文本模式、5 文字加图形界面。

      各个执行等级的启动脚本是通过/etc/rc.d/rc[0-6].d/SXXdaemon链接到/etc/init.d/daemon,S 为启动该服务,XX 是数字为启动顺序。

      由于有 SXX 设置,所以开机时可以依序执行所有需要的 daemon,解决 daemon 相依问题。

    • init 下创建上述 SXXdaemon 不需要手动创建链接文件,而是使用如下指令

      chkconfig daemon [on|off]
      chkconfig --list daemon
      
    • 切换 runlevel 可执行以下指令

      init runlevel
      

      不需要手动启动、关闭对应执行等级的 daemon。

  • CentOS7 以后,RedHat 系列 distribution 放弃了 System V 开机启动服务,而是用 systemd 这个启动服务管理机制。

    • systemd 可以让所有的服务同时启动,即使存在 daemon 相依性。
    • systemd 服务常驻内存,仅用systemctl指令处理服务管理。
    • systemd 可以自订服务 daemon 相依性检查。启动某个 daemon 其相依性 daemon 也会被启动。
    • systemd 将 daemon 按功能分类。每个 daemon 是一个 unit,将其分为 service、socket、target、path、snapshot、timer 等类型。
    • systemd 的 target 是将许多 daemon 集合,类似 System V 的 init 中的 runlevel。执行 target 项目即执行其对应的 daemons。
    • systemd 相容于 init 的脚本启动。旧的 init 启动脚本呢也能够通过 systemd 来管理,只是更进阶的 systemd 功能没办法支持。
  • systemd 无法取代 init 的方面:

    • 在 runlevel 的对应上,systemd 大概仅有对应到 init runlevel 1、3、5 的 target。
    • systemd 仅用systemctl指令管理服务,支持的参数有限。而 init 下/etc/init.d/脚本可以自订参数。
    • 如果某个服务启动是管理员自己手动执行启动的,而不是使用systemctl指令启动,那么 systemd 无法检测到该服务进而无法管理。
    • systemd 启动时,无法通过 stdin 传入讯息。
  • systemd 相容于旧式 System V,通过以下指令查看对应关系:

    ll -d /usr/lib/systemd/system/runlevel*.target | cut -c 28-
    

    System V 与 systemd 切换 runlevel 的指令对应关系:

    System V systemd
    init 0 systemctl poweroff
    init 1 systemctl rescue
    init [234] systemctl isolate multi-user.target
    init 5 systemctl isolate graphical.target
    init 6 systemctl reboot
  • systemd 的配置文件在如下目录,按照其中执行脚本的优先级从低到高排序:

    • /usr/lib/systemd/system/:每个服务最主要的启动脚本设置,类似 System V 的/etc/init.d/下面的文件。
    • /run/systemd/system/:系统执行过程中所产生的服务脚本。
    • /etc/systemd/system/:管理员依据主机系统的需求所创建的执行脚本,类似 System V 的/etc/rc.d/rc[0-6].d/SXXdaemon之类的功能。

    /etc/systemd/system/下其实是一大堆链接文件,实际执行脚本配置文件放在/usr/lib/systemd/system/中。所以修改某个 daemon 的设置应该修改/usr/lib/systemd/system/中脚本。

  • /usr/lib/systemd/system/下依据扩展名区分服务类型:

    • service:一般服务类型,主要是系统服务,包括服务器本身所需要的本机服务以及网络服务。
    • socket:内部程序数据交换的插槽服务。
    • target:执行环境类型,其实就是一群 unit 集合。
    • mount/automount:文件系统挂载相关的服务。
    • path:侦测特定文件或目录类型。某些服务需要侦测某些特定的目录来提供伫列服务,例如最常见的打印服务,就是通过侦测打印伫列目录来启动打印功能。
    • timer:循环执行的服务,类似于 anacrontab,不过是 systemd 主动提供的,比 anacrontab 更加有弹性。
  • systemctl简单指令:

    systemctl [start|stop|restart|reload|enable|disble|status|is-active|is-enable] [unit]
    

    unit 常见状态:

    • active(running):正有一只或多只程序正在系统中执行的意思。
    • active(exited):仅执行一次就正常结束的服务,目前并没有任何程序在系统中执行。如开机或者挂载时才会进行一次的 quotaon 功能。
    • active(waiting):正在执行当中,不过还再等待其他的事件才能继续执行。
    • inactive:这个服务目前没有执行的意思。

    daemon 的默认状态:

    • enabled:这个 daemon 将在开机时被执行。
    • disabled:这个 daemon 在开机时不会被执行。
    • static:这个 daemon 不可自己启动(enable 不可),不过可能会被其他的 enabled 的服务来唤醒。
    • mask:这个 daemon 无论如何都无法被启动,因为已经被强制注销。可通过systemctl unmask方式改回原本状态。

    不要使用kill来关闭正常运行的 daemon,那样 systemd 无法继续监控该服务。

    enable、disble,会添加、删除对应/etc/systemd/system/XXX.taregt.wants/下链接文件。

    start、stop,会添加、删除对应/etc/systemd/system/下链接文件。

    mask、unmask,会添加、删除对应/etc/systemd/system/下链接到/dev/null的文件。

    观察系统上的服务:

    systemctl [list-units|list-unit-files] [--type=TYPE] [--all]
    

    list-unitssystemctl不加参数时自动加的参数,列出启动的 unit。

    -all,列出所有 unit。

    list-unit-files,列出其 state。

    --type=TYPE,指定需要列出 unit 类型。

  • 列出 target unit:

    systemctl --type=target --all
    

    其中比较重要与操作模式相关的 target 有:

    • graphical.target,文字加上图形界面,包含multi-user.target
    • multi-user.target,纯文本模式。
    • rescue.targetemergency.target,救援方面的模式。
    • shutdown.target,关机流程。
    • getty.target,可以设置几个 tty 之类的。

    文字加上图形界面与纯文本的转变:

    systemctl get-default                  # 获取默认操作模式
    systemctl set-default graphical.target # 修改默认操作模式为图形界面
    
    systemctl isolate graphical.target     # 修改当前操作模式为图形界面
    

    target unit 应该使用 isolate 而不是 start、stop、restart。

    除此之外 systemd 提供的简单切换操作模式指令:

    systemctl poweroff|reboot|suspend|hibernate|rescue|emergency
    

    suspend 数据依然在内存中,关闭了大部分硬件,并未关机。

    hibernate 将数据保存到硬盘中,然后关机。

  • 分析 unit 之间的依赖性:

    systemctl list-dependencies [unit] [--reverse]
    

    --reverse,反向跟踪谁依赖该 unit。

  • systemd 相关目录文件:

    • /etc/sysconfig/*:几乎所有的服务会初始化的一些选项设置写入到这个目录下。
    • /var/lib/:一些会产生数据的服务都会将他的数据写入到该目录下。
    • /run/:放置了好多 daemon 的暂存盘。
  • 获取 socket 服务的 socket file 路径可使用以下指令:

    systemctl list-sockets
    
  • 服务与对应端口设置在/etc/services文件中。

  • 关闭网络服务示例:

    netstat -tunlp | grep 'avahi'
    systemctl list-units --all | grep 'avahi-daemon'
    systemctl stop avahi-daemon.service
    systemctl stop avahi-daemon.socket
    systemctl disable avahi-daemon.service avahi-daemon.socket
    
  • 额外修改原有 unit 配置建议。以 vsftpd.service 为例:

    • /usr/lib/systemd/system/vsftpd.service:官方释出的默认配置文件。不做修改。
    • /etc/systemd/system/vsftpd.service.d/custom.conf/etc/systemd/system/下创建 unit 名加.d后缀的目录,在该目录下添加自定义配置文件。
    • /etc/systemd/system/vsftpd.service.wants/:此目录下添加链接文件,表示 unit 执行后,建议执行的 unit。
    • /etc/systemd/system/vsftpd.service.requires/:此目录下添加链接文件,表示 unit 执行前,需要执行的 unit。
  • unit 配置文件说明。以/usr/lib/systemd/system/sshd.service为例:

    [Unit]
    Description=OpenSSH server daemon
    Documentation=man:sshd(8) man:sshd_config(5)
    After=network.target sshd-keygen.service
    Wants=sshd-keygen.service
    
    [Service]
    Type=notify
    EnvironmentFile=/etc/sysconfig/sshd
    ExecStart=/usr/sbin/sshd -D $OPTIONS
    ExecReload=/bin/kill -HUP $MAINPID
    KillMode=process
    Restart=on-failure
    RestartSec=42s
    
    [Install]
    WantedBy=multi-user.target
    

    设置的项目是可以重复的,不过后面的值会取代前面的值。

    空白行、开头为#;代表注释。

    配置组说明:

    • [Unit]:unit本身说明,以及与其它相依 daemon 的设置。

      • Description:简易说明。systemctl list-unitssystemctl status deamon会参考此内容。
      • Document:提供管理员进行进一步的文件查询功能。
      • After/Before:说明此 unit 在哪个 daemon 启动之后/之前,仅说明并未强制,但不按照此启动可能出现问题。
      • Requires:明确规定此 unit 在哪个 daemon 启动后才能启动。
      • Wants:规范这个 unit 启动之后最好还要启动什么服务。
      • Conflicts:与哪些服务不能同时启动。
    • [Service]:规范服务启动的脚本、环境配置文件文件名、重新启动方式等等。不同的 unit 对应不同的类型。

      • Type:说明这个 daemon 启动的方式,会影响ExecStart

        • simple:默认值,这个 daemon 主要由ExecStart接的指令串来启动,启动后常驻于内存中。
        • forking:由ExecStart启动的程序通过 spawns 延伸出其他子程序作为此 daemon 的主要服务。原生的父程序在启动结束后就会终止运行。
        • oneshot:与simple类似,不过这个程序在工作完毕后就结束了,不会常驻在内存中。
        • dbus:与simple类似,但这个 daemon 必须要在取得一个 D-Bus 的名称后,才会继续运行。因此设置这个项目时,通常也要设置BusName=才行。
        • idle:与simple类似,意思是,要执行这个 daemon 必须要所有的工作都顺利执行完毕才会执行。这类的 daemon 通常时开机到最后才执行即可的服务。
      • EnvironmentFile:指定启动脚本的环境配置文件。

      • ExecStart:就是实际执行此 daemon 的指令或脚本程序。也可使用ExecStartPreExecStartPost设置实际启动服务前、后进行额外的指令行为。使用指令串仅接受“指令 参数 参数”格式,不支持<>>>|&等特殊字符,很多 Bash Shell 语法也不支持。若要支持比较完整的 Bash 语法,使用Type=oneshot才行。

      • ExecStop:与systemctl stop有关,关闭此服务时所进行的指令。

      • ExecReload:与systemctl reload有关的指令行为。

      • Restart:当设置为 1 时,则当此 daemon 服务终止后,会再次启动此服务。

      • RemainAfterExit:当设置为 1 时,则当此 daemon 所属的所有程序都终止后,此服务会再尝试启动。

      • TimeoutSec:若这个服务在启动或关闭时,因为某些缘故导致无法顺利“正常启动或正常结束”的情况下,则我们要等多久才进入“强制结束”的状态。

      • KillMode:可以是processcontrol-groupnone中的一种。

        • process:当 daemon 终止时,只会终止主要的程序(ExecStart接的后面那串指令)。
        • control-group:当 daemon 终止时,则由此 daemon 所产生的其他 control-group 程序,也都会被关闭。
        • none:当 daemon 终止时,没有程序会被关闭。
      • RestartSec:与Restart有点相关性,如果这个服务被关闭,然后需要重新启动时,大概要 sleep 多少时间在重新启动的意思。默认100ms。

    • [Install]:将此 unit 安装到哪个 target 里。

      • WantedBy:后面接的大部分是*.target unit,意思是这个 unit 本身是附挂在哪一个 target unit 下面的。
      • Also:当目前这个 unit 本身被 enable 时,Also后面接的 unit 也请 enable 的意思。
      • Alias:进行一个链接的别名的意思。当systemctl enable相关的服务时,则此服务会进行链接文件的创建。
  • System V 中要让系统额外执行某些程序的话,可将其指令/脚本的绝对路径名称写到/etc/rc.d/rc.local中。systemd 则推荐自己书写 unit 脚本,放在/etc/systemd/system/下(并非/usr/lib/systemd/system/下,方便区分是自己写的而不是系统的),使用systemctl enable unit将其添加到/etc/systemd/system/X.wants/下(X 为 default.target)。

  • 新建 vsftpd2.service 使其以 555 作为监听接口示例:

    # 新建 vsftpd2.service 配置文件
    cd /etc/vsftpd
    cp -a vsftpd.conf vsftpd2.conf
    vim vsftpd2.conf # listen_port=555
    
    # 新建 vsftpd2.service
    cd /etc/systemd/system
    cp /usr/lib/systemd/system/vsftpd.service vsftpd2.service
    vim vsftpd2.service    # 修改 ExecStart 指令,使用 vsftpd2.conf 配置文件
    
    systemctl daemon-reload
    systemctl list-unit-files --all | grep 'vsftpd'
    systemctl status vsftpd2.service
    systemctl restart vsftpd.service vsftpd2.service
    systemctl enable vsftpd.service vsftpd2.service
    systemctl status vsftpd.service vsftpd2.service
    netstat -tnlp
    

    也可直接向如下这样做,原因参考下一点:

    # 新建 vsftpd3.service 配置文件
    cd /etc/vsftpd
    cp -a vsftpd.conf vsftpd3.conf
    vim vsftpd2.conf # listen_port=2121
    
    # 存在 vsftpd@.service,其 ExecStart 为 /usr/sbin/vsftpd /etc/vsftpd/%i.conf
    systemctl start vsftpd@vsftpd3.service
    systemctl status vsftpd@vsftpd3.service
    
  • 修改 TTY 数量设置:

    getty.target 中,该 target unit 启动后会执行服务:

    After=getty@tty1.service
    

    使用systemctl show getty.target查看,能看到默认设置,cat getty.target是看不到默认设置的。

    事实上,getty@tty1.service 并不存在。这时,其实执行 getty@.service 服务,而中间的 tty1 被当作 %I 传入 getty@.service 中。而 getty@.service 中ExecStart实际是:

    ExecStart=-/sbin/agetty --noclear %I $TERM
    

    -/sbin/agetty --noclear tty1。通过“@”与“%I”/“%i”实现重复服务配置的简化。

    /etc/systemd/logind.confNAutoVTs设置了默认启动 TTY 的数量。修改后,通过以下指令更新:

    systemctl stop getty@tty[2、3、4……].service # 如果是减少 TTY 数量,先要关闭多余已开启的 TTY
    systemctl restart systemd-logind.service
    

    暂时启动一个新的 TTY 可使用:

    systemctl start getty@tty[2、3、4……].service
    
  • 制作一个备份自己系统的服务示例:

    vim /backups/backup.sh
    
    #!/bin/bash
    
    source="/etc /home /root /var/lib /var/spool/{cron,at,mail}"
    target="/backups/backup-system-$(date +%Y-%m-%d).tar.gz"
    [ ! -d /backups ] && mkdir /backups
    tar -zcvf ${target} ${source} &> /backups/backup.log
    
    chmod a+x /backups/backup.sh
    ll /backups/backup.sh
    vim /etc/systemd/system/backup.service
    
    [Unit]
    Description=backup my server
    Requires=atd.service
    
    [Service]
    Type=simple
    ExecStart=/bin/bash -c " echo /backups/backup.sh | at now"
    
    [Install]
    WantedBy=multi-user.target
    
    systemctl daemon-reload
    systemctl start backup.service
    systemctl status backup.service
    
  • timer unit 可用于定时执行的服务。创建这样一个服务需要 timers.target 启动,有 sname.service 和 sname.timer 存在(sname 为自定义服务名)。

    sname.timer 配置文件中,[timer]设置:

    • OnActiveSec:当 timer.target 启动多久后执行这只 unit。
    • OnBootSec:当开机多久后才执行。
    • OnStartupSec:但 systemd 第一次启动之后过多久才执行。
    • OnUnitActiveSec:对应 service unit 在最后一次启动后,隔多久后再执行一次。
    • OnUnitInactiveSec:对应 service unit 在最后一次停止后,隔多久后再执行一次。
    • OnCalendar:使用实际时间的方式启动服务。
    • Unit:一般不需要设置,指定 service unit。
    • Persistent:与OnCalendar搭配,指定其是否持续进行。设置 yes 达到类似 anacron 效果。

    时间设置格式:

    如果是固定时间,则为 E、yyyy-MM-dd、HH:mm:ss,如 Thu、2015-08-13、13:40:00。

    如果是间隔,单位为 us/usec、ms/msec、s/sec/second/seconds、m/min/minute/minutes、h/hr/hour/hours、d/day/days、w/week/weeks、month/months、y/year/years。

    还可使用英文常用口语化日期代表,如 now、today、tomorrow、hourly、daily、weekly、monthly、+3h10m、2015-08-16。

  • 为上述 backup.service 设置 backup.timer 示例:

    vim /etc/systemd/system/backup.timer
    
    [Unit]
    Description=backup my server timer
    
    [Timer]
    OnBootSec=2hrs
    OnUnitActiveSec=2days
    
    [Install]
    WantedBy=multi-user.target
    
    [Unit]
    Description=backup my server timer
    
    [Timer]
    OnCalendar=Sun *-*-* 02:00:00
    Persistent=true
    
    [Install]
    WantedBy=multi-user.target
    
    systemctl daemon-reload
    systemctl enable backup.timer
    systemctl restart backup.timer
    
  • systemd 对 System V 设置/etc/rc.d/rc.local相容,这是 rc-local.service 提供的功能。该服务不需要手动启动,只要/etc/rc.d/rc.local具有 x 权限该服务就自动开启。

    systemctl status rc-local.service
    systemctl list-dependencies multi-user.target | grep 'rc-local'
    chmod a+x /etc/rc.d/rc.local
    ...
    systemctl daemon-reload
    systemctl list-dependencies multi-user.target | grep 'rc-local'
    systemctl status rc-local.service
    
  • 由于 systemd 启动服务是同步运行的,getty@.service 启动后,systemd-logind.service 或 systemd-user-sessions.service 可能还未启动完成,这就导致一开始输入正确密码无法登录系统,需要等待一段时间。

  • CentOS7 默认启动服务简易说明:

    • atd、crond、auditd、getty@、quotaon。
    • cpupower:提供 CPU 的运行规范。
    • firewalld:CentOS7 以后,iptables 服务的启动脚本已经被忽略了,使用 firewalld 来取代 iptables 服务器。
    • network(active(exited))、NetworkManager(active(running)):CentOS7 以后,系统建议使用 NetworkManager 搭配其nmcli指令来处理网络设置,而不再推荐使用 network 服务。
    • rc-local:相容于/etc/rc.d/rc.local的调用方式。
    • rsyslog:可以记录系统所产生的各项讯息,包括/var/log/messages内的几个重要登录文件。
    • abrtd、accounts-daemon、alsa-X、avahi-daemon、brandbot、rhel-*、chronyd、ntpd、ntpdate、cups、dbus、dm-event、multipathd 等。

6.软件管理

6.1.Tarball 安装

  • Linux 上面的软件几乎都是经过 GPL 的授权,所以每个软件几乎均提供原始程序码,并且你可以自行修改该程序码,以符合你个人的需求。

  • Linux 默认函数库在/lib//lib64/。默认 include 头文件在 /usr/include/

  • Tarball 的侦测程序的文件名为configure或者是config

  • make取用变量优先级从高到低为make命令行、makefile 文件设置变量、Shell 变量。makefile 中$@代表当前 target。

  • Tarball 安装步骤:

    1. 将 Tarball 文件在/usr/local/src目录下解压缩。
    2. 在解压缩后查看INSTALLREADME相关内容。
    3. 以自动侦测程序configureconfig侦测作业环境,并创建 Makefile 文件。
    4. 编译并安装。建议是安装到一个独立的目录中,如/usr/local/packages。而且必需手动将这个软件的 manual page 写到/etc/man_db.conf中。
  • 默认情况下,原本的 Linux distribution 释出安装的软件大多在/usr中,而使用者自行安装的软件则建议放置在/usr/local里。

  • 使用 Tarball 方式安装 ntp 范例:

    cd /usr/local/src
    tar -zxvf /root/ntp-4.2.8p3.tar.gz
    cd ntp-4.2.8p3
    vi INSTALL
    ./configure --help | more
    ./configure --prefix=/usr/local/ntp --enable-all-clocks --enable-parse-clocks
    make clean; make
    make check
    make install
    
  • 可使用 patch 更新源代码文件,然后重新 make 编译安装。通常来说 patch file 文件指正对于前一个版本。

  • 将常用到的动态函数库载入内存中:

    1. /etc/ld.so.conf里面写下想要读入高速缓存内存当中的动态函数库所在的目录。
    2. 利用ldconfig这个可执行文件将/etc/ld.so.conf的数据读入高速缓存当中。
    3. 同时也将数据记录一份在/etc/ld.so.cache这个文件当中。

    如:

    vim /etc/ld.so.conf.d/meyok.conf
    
    /usr/lib64/mysql
    
    ldconfig
    ldconfig -p
    
  • ldd [-vdr] [filename],列出可执行文件依赖的动态函数库。

  • md5sumsha1sumsha256sum,获取指纹。

6.2.RPM

  • RPM 是以一种数据库记录的方式来将你所需要的软件安装到你的 Linux 系统的一套管理机制。它安装的软件先编译过然后打包成 RPM 机制的包装软件(扩展名为rpm)。安装对应软件时,依赖的软件未安装则默认不予安装(依赖性信息在 rpm 包中,而本地安装的软件信息在数据库中,通过这两者信息对比确定是否安装了依赖软件)。

  • 软件一般被释出为两种 RPM,类似software-x.x.rpm是一般使用的,而类似software-devel-x.x.rpm是开发使用的。

  • RPM 软件安装后的相关信息会被写入/var/lib/rpm/目录下的数据库文件中。

  • rpm指令:

    • RPM 安装:

      rpm -ivh package_name
      

      -i,安装。

      -v,查看细部安装信息。

      -h,显示安装进度。

      如:

      rpm -ivh a.i386.rpm b.i386.rpm
      rpm -ivh http://website.name/path/pkgname.rpm
      

      安装时还可添加参数:--nodeps--replacefiles--replacepkgs--force--test--justdb--nosignature--prefix path--noscripts

    • RPM 升级、更新:

      rpm -Uvh|-Fvh package_name
      

      -U,没有安装则安装,原软件是旧版则升级。

      -F,没有安装则不安装,原软件是旧版则升级。

    • RPM 查询:

      rpm -q software_name  # 查询软件是否安装
      rpm -qa               # 列出所有已安装的软件
      rpm -qi software_name # 列出该软件详细信息
      rpm -ql software_name # 列出该软件的所有文件、目录完整路径
      rpm -qc software_name # 列出该软件在 /etc/ 下的所有配置文件
      rpm -qd software_name # 列出该软件的说明文档(man)
      rpm -qR software_name # 列出与该软件相依赖的软件
      rpm -qf filename      # 找出该文件所属软件
      rpm -q --scripts      # 列出是否具有安装后需要执行的脚本档
      
      rpm -qp[icdlR] rpm_name # 找出某个 RPM 文件内信息
      
    • RPM 验证:

      rpm -Va                        # 列出系统上所有可能被改动过的文件
      rpm -V installed_software_name # 若该软件所含文件被改动过,会被列出来
      rpm -Vp rpm_name               # 列出该软件内可能被改动过的文件
      rpm -Vf filename               # 列出某个文件是否被改动过
      

      查询出来的讯息含义:

      S 指容量大小、M 指 rwx 属性、5 指 MD5 指纹码、D 指设备 major 和 minor 码、L 指路径、U 指所属用户、G 指所属群组、T 指文件创建时间、P 指功能,对应内容是否改变。

      c、d、g、l、r 分别标志这是配置文件、数据文件、不应该被该软件包含的鬼文件、授权文件、README。

  • 有些软件需要要求安装数码签章才能安装软件。如安装 CentOS 的数码签章(位于/etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS7):

    rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS7
    rpm -qa | grep 'pubkey' # 一般来说,数码签章安装后的金钥软件名会带有 pubkey
    rpm -qi gpg-pubkey-...
    
  • RPM 解除安装一定要先解除那些依赖它的软件。

    rpm -e software_name
    rpm -e --nodeps software_name # 不管依赖强制解除
    
  • 由于 RPM 文件常常会安装、移除、升级,可能某些动作导致 RPM 数据库内文件损坏。那么可以通过以下指令修复:

    rpm --rebuilddb # 重建数据库
    

6.3.YUM

  • YUM 克服了 RPM 的软件依赖。在 YUM 服务器中存在清单列表,用户端从 YUM 服务器下载软件时,会先下载清单列表,然后比对本地数据库看缺少什么软件,再在 YUM 服务器上下载缺少的软件从而克服 RPM 的软件依赖。

  • yum指令:

    • YUM 查询:

      yum [option] [查询工作项目] [相关参数]
      

      相关参数可以是:

      search,搜寻某个软件名称或者是描述的重要关键字。

      list,列出目前 yum 所管理的所有软件名称与版本,类似rpm -qa

      info,同上,类似于rpm -qai

      provides,从文件去搜寻软件,类似rpm -qf

      如:

      yum search raid     # 找寻 raid 相关软件
      yum info mdadm      # 找出 mdadm 这个软件的功能如何
      yum list            # 列出 yum 服务器上面提供的所有软件名称
      yum list updates    # 列出目前服务器上可供本机进行升级的软件
      yum list pam*       # 列出以 pam 开头的软件
      yum provides passwd # 列出提供 passwd 这个文件的软件
      
    • YUM 安装与升级:

      yum [option] [安装与升级的工作项目] [相关参数]
      

      相关参数可以是:

      install,表示安装。

      update,表示升级,不接任何项目表示这个系统升级。

    • YUM 解除安装:

      yum [option] remove 项目
      

    option 可以是:

    -y,当yum要求输入自动提供 yes。

    --installroot=/somepath,将该软件安装到/somepath而不是默认路径。

    --enablerepo=,启用某个软件库。

  • YUM 的位于/etc/yum.repos.d/下配置文件各字段含义:

    [base]:代表软件库名称,可以顺便取名但是不能重复。

    • name,说明软件库意义,重要性不高。
    • mirrorlist=,列出这个软件库可以使用的映射站台。
    • baseurl=,软件库实际网址。
    • enable=1,启用该软件库,否则为 0。
    • gpgcheck=1,指定是否需要 RPM 文件内的数码签章。
    • gpgkey=,数码签章公钥所在位置。

    使用自己配置的文件,需要放到该目录下,且拓展名必须为repo

    修改配置文件之后,由于 yum 会下载软件库清单到/var/cache/yum中,这时需要更新本机清单:

    yum clean all
    
  • 列出目前 yum server 所使用的软件库:

    yum repolist all
    
  • YUM 的群组功能:

    yum [选项] [软件群组]
    

    选项有:

    grouplist,列出所有可使用的软件群组。

    groupinfo,后接 group_name,了解该软件群组内含所有软件。

    groupinstall,安装一组软件群组。

    groupremove,解除安装一组软件群组。

    如:

    yum grouplist
    yum groupinfo 'Scientific Support'
    

    软件群组安装时,可选软件并不会安装。如果要安装软件群组中所有软件,需要修改/etc/yum.conf文件,在distroverpkg那行下添加如下行:

    group_package_types=default,mandatory,optional
    

6.4.SRPM

  • SRPM 是没有经过编译的 RPM,与 RPM 相比多了configure这些文件,与 Tarball 相比它又有依赖软件信息。其扩展名为src.rpm

7.boot loader 与核心

7.1.开机流程

  • CentOS7 系统开机流程:

    1. 载入 BIOS 的硬件信息与进行自我测试,并依据设置取得第一个可开机的设备。
    2. 读取并执行第一个开机设备内的 MBR 的 boot loader(即 grub2、spfdisk 等程序)。
    3. 依据 boot loader 的设置载入 Kernel,Kernel 会开始侦测硬件与载入驱动程序。
    4. 在硬件驱动成功后,Kernel 会主动调用 systemd 程序,并以 default.target 流程开机(假设 default.target 是 graphical.target)。
      • systemd 执行 sysinit.target 初始化系统及 basic.target 准备操作系统。
      • systemd 启动 multi-user.target 下的本机与服务器服务。
      • systemd 执行 multi-user.target 下的/etc/rc.d/rc.local文件
      • systemd 执行 multi-user.target 下的 getty.target 及登录服务。
      • systemd 执行 graphical 需要的服务。
  • 每个文件系统(filesystem 或者是 partition)都会保留一块开机扇区(boot sector)提供 OS 安装 boot loader,而通常 OS 默认都会安装一份 boot loader 到它根目录所在文件系统的 boot sector 上

    GPT 分区的 LBA0 与 MBR 分区的一号区块兼容,以下对此区块均称为 MBR。

    boot loader 的内容使用 BIOS 的 INT 13 中断读取的。

    boot loader 的功能如下:

    • 提供菜单,让使用者选择不同的开机项目(多重开机的重要功能)。
    • 载入核心文件 Kernel,直接指向可开机的程序区段开始操作系统。
    • 控制权转交,将开机管理功能转交给其他 boot loader 负责。

    安装 Linux 时,可选择将 boot loader 安装到 MBR 上去,这样 MBR 和 boot sector 上都有 boot loader。安装 Windows 时,默认将 boot loader 在 MBR 与 boot sector 上都要安装。而 Windows 的 boot loader 不提供控制权转交功能,所以安装多 OS 时,必须先安装 Windows,再安装 Linux

  • Linux 核心文件 Kernel 为/boot/vmlinuz-*(名字含有rescue是救援用的核心文件)。

    为硬件开发商与其他核心功能开发者便利,Kernel 是可以通过动态载入核心模块。一般来说,非必要的功能且可以编译成模块的核心功能,目前 Linux distributions 都会将其编译成核心模块(如 USB、SATA、SCSI 的驱动程序)。核心模块位于/lib/modules/中。

  • 由于/lib目录必须和/存在同一分区,所以读取核心模块,必须先挂载/。若/是被挂载在譬如 SATA 磁盘上的,那么挂载/又需要核心模块中 SATA 的驱动程序,这就造成了一个死循环。该问题是通过虚拟文件系统(Initial RAM Disk 或 Initial RAM Filesystem)解决的。该系统一般使用/boot/initrd-*/boot/initramfs-*,与 Kernel 文件一样,它也能通过 boot loader 载入内存。

    Initial RAM Disk 文件会在内存解压缩后仿真为一个文件系统,可通过该文件系统中的程序来载入开机过程中需要的核心模块,一般这些模块就是 USB、RAID、LVM、SCSI 等文件系统与磁盘接口的驱动程序。使用完后,释放该文件系统并挂载真实的/文件系统,然后开始后续正常的开机流程。

    查看 Initial RAM Disk 文件内容示例:

    # 查看文件内容(同时查看文件最前的数据介绍大小)
    # lsinitrd /boot/initramfs-3.10.0-229.el7.x86_64.img # 教材上的版本
    lsinitrd /boot/initramfs-3.10.0-1160.el7.x86_64.img
    
    mkdir /tmp/initramfs && cd /tmp/initramfs
    # 将虚拟文件系统做成压缩文件(教材上的版本存在最前的数据介绍,会占用一定空间需要跳过)
    # dd if=/boot/initramfs-3.10.0-229.el7.x86_64.img of=initramfs.gz bs=11264 skip=1
    dd if=/boot/initramfs-3.10.0-1160.el7.x86_64.img of=initramfs.gz
    ll initramfs.gz; file initramfs.gz;
    
    gzip -d initramfs.gz # 解压缩
    file initramfs       # 解压缩后产生一个 cpio 文件
    cpio -i -d -H newc --no-absolute-filenames < initramfs # 解开 cpio 文件
    
    ll usr/lib/systemd/system/default.target  # 查看该虚拟文件系统执行开机的 target unit
    # ... usr/lib/systemd/system/default.target -> initrd.target
    systemctl list-dependencies initrd.target # 查看 initrd.target unit 的服务依赖
    
  • 粗略分析 graphical.target 相依赖的服务,其 systemd 开机流程大约是:

    1. local.fs、swap.target:这两个 target 主要在挂载/etc/fstab里所规范的文件系统与相关的内存交换空间。
    2. sysinit.target:这个 target 主要在侦测硬件,载入所需要的核心模块等动作。
    3. basic.target:载入主要周边硬件驱动程序与防火墙相关任务。
    4. multi-user.target 下面的其它一般系统或网络服务的载入。
    5. 图形界面相关服务如 gdm.service 等其他服务的载入。
  • systemd 有自己的配置文件处理方式,但为相容于 System V,很多服务还是会读取/etc/sysconfig/下环境配置文件。

    开机过程会用到的主要配置文件:

    • /etc/modules-load.d/*.conf:单纯要核心载入模块的位置。

    • /etc/modprobe.d/*.conf:可以加上模块参数的位置。

    • /etc/sysconfig/*

      • authconfig:规范使用者的身份验证机制,包括是否使用/etc/passwd/etc/shadow等文件、密码记录时的加密算法、是否使用外部密码服务提供的账号验证等。

        不建议手动修改该文件,而是使用authconfig -tui指令来修改。

      • cpupower:cpupower.service 读取该文件。主要是 Linux 核心如何操作 CPU 的原则,一般是以最大性能方式。

      • firewalldiptables-configip6tables-configebtables-config:与防火墙的启动外带的参数有关。

      • network-scripts/*:设置网卡。

    如开机要求载入 nf_conntrack_ftp 模块(一个针对 FTP 防火墙的模块)。

    vim /etc/modules-load.d/meyok.conf
    
    nf_conntrack_ftp
    
    options nf_conntrack_ftp ports=555
    

    一个模块/驱动程序写一行,可设置参数

    重新开机该模块就会在开机时被载入。如果不想重新开机测试查看,而现在查看可通过以下指令:

    lsmod | grep 'nf_conntrack_ftp'
    systemctl restart systemd-modules-load.service
    lsmod | grep 'nf_conntrack_ftp'
    

7.2.核心模块

  • 核心与核心模块的位置:

    • 核心:/boot/vmlinuz/boot/vmlinuz-version
    • 核心解压缩所需 RAM Disk:/boot/initramfs/boot/initramfs-version
    • 核心模块:/lib/modules/version/kernel/lib/modules/$(uname -r)/kernel
    • 核心源代码:/usr/src/linux/usr/src/kernels/(要安装才会有,默认不安装)

    如果该核心被顺利的载入系统当中了,那么就会有几个信息记录下来:

    • 核心版本:/proc/version
    • 系统核心功能:/proc/sys/kernel
  • /lib/modules/$(uname -r)/modules.dep记录了模块依赖性。

    将一个模块载入到核心模块的依赖管理方法,以载入自己的a.ko模块(假如该模块是自己编写的一个网卡驱动程序)示例:

    cp a.ko /lib/modules/$(uname -r)/kernel/drivers/net
    depmod
    

    核心模块的扩展名一定是ko

  • lsmod,列出目前载入的核心模块,以及被那些模块使用。

  • modinfo [-adln] [module_name|filename],列出模块信息。

  • insmodrmmod,手动载入、删除模块:

    insmod [/full_path/module_name] [parameters]
    rmmod [-fw] module_name
    

    如:

    insmod /lib/modules/$(uname -r)/kernel/fs/vfat/vfat.ko
    lsmod | grep 'fat'
    rmmod fat
    

    insmod载入的模块,其依赖的模块没有载入时,是无法载入的。

  • modprobe [-r] module_name,自动载入、删除模块(-r参数),包括依赖模块未载入时自动载入。如:

    modprobe cifs
    lsmod | grep 'cifs'
    modprobe -r cifs
    
  • 如果有特殊需求导致需要让载入的模块加上某些参数,那么就配置/etc/modprobe.d/*.conf文件,与/etc/modules-load.d/*.conf配置方法相同。

7.3.grub2

  • 由于 MBR 充其量也就 446 Bytes,无法装下整个 boot loader,所以 Linux 将 boot loader 的程序码执行与设置值载入分成两个阶段来执行:

    1. 执行 boot loader 主程序:这个主程序必须被安装在开机区,即是 MBR 或 boot sector。
    2. 主程序载入配置文件:通过 boot loader 载入所有配置文件与相关的环境参数文件。一般来说,配置文件都在/boot下面。

    与 grub2 有关的文件放在/boot/grub2/下面。

  • CnetOS7 采用的 boot loader 是 grub2。grub2 的优点:

    • grub2 认识与支持较多的文件系统,并且可以使用 grub2 的主程序直接在文件系统中搜寻核心文件名。
    • 开机的时候,可以自行编辑与修改开机设置项目,类似 Bash Shell 的指令模式。
    • 可以动态搜寻配置文件,而不需要在修改配置文件后重新安装 grub2,即是修改/boot/grub2/grub.cfg中的内容后,下次开机就生效。

    前两点就是 Linux 可以将 grub2 分别安装到 MBR 和文件系统中的原因。

  • grub2 对磁盘的代号设置与传统 Linux 完全不同,使用的是如下代号:

    (hd0,1)      # 一般的默认语法,由 grub2 自动判断分区格式
    (hd0,msdos1) # 此磁盘分区为 MBR
    (hd0,gpt1)   # 此磁盘分区为 GPT
    # hd 表示硬盘
    

    磁盘代号从 0 开始,分区代号从 1 开始。

  • /boot/grub2/grub.cfg的重要内容:

    • set default,默认开机选项。

    • set timeout,默认等待选择秒数。

    • menuentry,菜单的每一个选项。其后跟着选项,而{}中的内容是选择该选项后执行的动作。

      • set root='hd0,gpt2',指定 boot loader 所在设备。

        作者的/boot是单独被挂载在/dev/sda2上的,所以这里是hd0,gpt2

      • linux16 /vmlinuz-... root=/dev/mapper/centos-root ...,执行 Linux 核心文件加载。

        核心文件名需要和set root一起配置。

        由于作者的/boot被单独挂载,上述set root指的是/boot,所以核心文件并未书写/boot;如果/boot并未单独挂载,set root的设置应该是指/,那么这里的核心文件名应该添加/boot路径。

        root参数指定/目录位于哪个设备。使用 Linux 指定设备的方法,而非 grub2 的磁盘代号设置。

        这里使用的是 Linux 的设备文件名,也可使用 UUID、LABEL,类似root=UUID=1111.2222.33...这个格式。

      • initrd16 /initramfs-...,执行 Initial RAM Disk 文件加载。与linux16类似,文件名要与set root配合使用。

  • 不建议直接修改/boot/grub2/grub.cfg配置文件,而是修改以下配置文件后,使用grub2-mkconfig指令重建 grub.cfg 文件

    • /etc/default/grub:主要环境配置文件。
    • /etc/grub.d/:菜单创建的脚本。
    vim /etc/default/grub
    vim /etc/grub.d/...
    grub2-mkconfig -o /boot/grub2/grub.cfg
    
  • /etc/default/grub重点项目:

    默认设置:

    GRUB_TIMEOUT=5
    GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
    GRUB_DEFAULT=saved
    GRUB_DISABLE_SUBMENU=true
    GRUB_TERMINAL_OUTPUT="console"
    GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet"
    GRUB_DISABLE_RECOVERY="true"
    
    • GRUB_TIMEOUT,菜单选择等待秒数。-1表示一定要使用者选择。
    • GRUB_TIMEOUT_STYLE,是否隐藏菜单。常用设置值有:
      • menu,显示。默认设置。
      • countdown,不显示菜单,只显示剩余等待秒数。
      • hidden,不显示菜单和剩余等待秒数。
    • GRUB_TERMINAL_OUTPUT,输出的画面应该使用哪个终端机。主要设置值有:consoleserialgfxtremvga_text
    • GRUB_DEFAULT,指定哪个 menuentry 作为开机默认选项。可设置为saved数字title 名ID 名
    • GRUB_CMDLINE_LINUX,核心外加参数功能。
  • /etc/grub.d/grub2-mkcnfig指令创建 grub.cfg 的一些脚本。主要的几个脚本解释:

    • 00_header:主要在创建初始的显示项目。大部分在/etc/default/grub里面所设置的变量,大概都会在这个脚本当中被利用来创建 grub.cfg。
    • 10_linux:根据分析/boot下面的文件,尝试找到正确的 Linux 核心与读取这个核心需要的文件系统模块与参数等,都在这个脚本运行后找到并设置到 grub.cfg 当中。这个脚本会将所有在/boot下面的每一个核心文件都对应到一个 menuentry。
    • 30_os-prober:默认会到系统上找其他的分区里面可能含有的操作系统,然后将该操作系统做成 menuentry。如果不想将其他操作系统侦测到拿来开机,在/etc/default/grub里加上GRUB_DISABLE_OS_PROBER=true
    • 40_custom:如果还有其他自己手动加上去的 menuentry,或者是其他的需求,建议在这个文件中补充。
  • 制作自己的 menuentry 一般通过修改/etc/grub.d/40_custom文件。如设置一个 menuentry 默认使用 graphical.target:

    vim /etc/grub.d/40_custom
    
    menuentry 'My graphical CentOS Linux (3.10.0-1160.el7.x86_64)' ... --id 'mygraphical' {
            ...
            linux16 ... systemd.unit=graphical.target
            ...
    }
    
    grub2-mkconfig -o /boot/grub2/grub.cfg
    
  • grub2 实现 boot loader 的控制权转交,一般在 menuentry 设置两个参数,一个是指定前往的 boot sector 所在分区代号,另一个是设置 chainloader 在那个分区的 boot sector(第一个扇区)上。如设置两个 menuentry,在 MBR 分区下,一个前往位于/dev/sda2上的 Windows 系统,一个前往默认的 MBR 环境:

    menuentry 'Go to Windows' --id 'windows' {
            insmod chain          # 载入 chainloader 模块
            insmod ntfs           # 载入 Windows 文件系统模块
            set root=(hd0,msdoc2)
            chainloader +1
    }
    menuentry 'Go to MBR' --id 'mbr' {
            insmod chain
            set root=(hd0)
            chainloader +1
    }
    
  • 如果有特殊需要所以想重制 initramfs 文件,可以使用dracut/mkinitrd来处理。

    CentOS7 应该用dracut,不过mkinitrd也有所保留。

    如:

    # 以 dracut 的默认功能创建一个 initramfs 虚拟磁盘文件
    dracut -v initramfs-test.img $(uname -r)
    # 额外加入 e1000e 网卡驱动与 ext4/nfs 文件系统在新的 initramfs 内
    dracut -v --add-drivers "e1000e" --filesystems "ext4 nfs" initramfs-new.img $(uname -r) 
    lsinitrd initramfs-new.img | grep -E '(e1000|ext4|nfs)'
    
  • 如果 Linux 原来并非使用 grub2,可使用grub2-install来进行安装。grub2-install大概仅能安装 grub2 主程序与相关软件到/boot/grub2/目录中去。其指令格式为:

    grub2-install [--boot-directory=DIR] INSTALL_DEVICE
    

    --boot-directory指定安装目录,默认/boot/grub2

    如果INSTALL_DEVICE是这个磁盘(如/dev/sda),主程序能安装到 MBR 中。如果INSTALL_DEVICE是 XFS 的某个分区(如/dev/sda4),那么可能无法安装到对应 boot sector,需要强制安装。如:

    grub2-install /dev/sda # 安装主程序到 MBR
    
    grub2-install --skip-fs-probe /dev/sda4 # 这里依然失败
    grub2-install --force --recheck --skip-fs-probe /dev/sda4
    # MBR 和 /dev/sda4 的 boot sector 都被安装了一份
    
  • 设置开机画面使用图形显示方式示例:

    vim /etc/default/grub
    
    ...
    GRUB_TERMINAL=gfxterm		# 设置主要的终端机显示为图形界面
    GRUB_GFXMODE=1024x768x24	# 图形界面的X,Y,彩度数据
    GRUB_GFXPAYLOAD_LINUX=keep	# 保留图形界面,不要使用text
    ...
    
    grub2-mkconfig -o /boot/grub2/grub.cfg
    
  • 可以通过 grub2 的账号(并非 Linux 系统的账号)来控制用户可选择的 menuentry,以及 menuentry 命令行修改。

    grub2 账号分为 superusers 和普通用户。其限制规则如下:

    • 对于 menuentry 命令行修改:只要 superusers 被设置,普通用户将被限制所有 menuentry 命令行修改(可以进入 menuentry 命令行),而 superusers 不受限制

    • 对于可选择的 menuentry:通过在 menuentry 添加参数--unrestricted--users username来限制哪些普通用户能选择该 menuentry。

      如果设置为--unrestricted,不需要密码就可使用该 menuentry。如果设置为--users "username",只有 superusers 和设置的 user 可使用该 menuentry。否则,只有 superusers 可使用该 menuentry。

      grub2 为/bootKernel 对应的 menuentry 创建的默认参数有--unrestricted

      cat /etc/grub.d/10_linux | grep 'CLASS'
      # CLASS="--class gnu-linux --class gnu --class os --unrestricted"
      

    superusers、普通用户以及密码在/etc/grub.d/01_users中设置。设置 superusers 语句为set superusers="username"。密码设置的格式有两种方式:

    password username pwd
    password_pbkdf2 username encrypted_pwd
    

    设置示例:

    grub2-mkpasswd-pbkdf2    # 查看密码密文
    vim /etc/grub.d/01_users
    
    #!/bin/sh -e
    cat << EOF
    set superusers="meyok"
    password_pbkdf2 meyok encrypted_pwd
    password_pbkdf2 yangyi encrypted_pwd
    EOF
    
    vim /etc/grub.d/40_custom
    
    menuentry 'Go to Windows' --id 'windows' {
            ...
    }
    menuentry 'My Rescue CentOS' --users yangyi {
            ...
            linux16 ... systemd.unit=rescue.target
            ...
    }
    
    grub2-mkconfig -o /boot/grub2/grub.cfg
    

    此时作者的有 4 个 menuentry。所有 menuentry 都不能进行命令行修改。grub2 为/boot下 Kernel 创建的两个 menuentry 任何用户都不需要输入密码即可选择进入;名为“Go to Windows”的 menuentry 只有 superusers(这里为 meyok)才能输入密码选择进入;名为“My Rescue CentOS”的 menuentry 可以被 superusers 和 yangyi 输入密码选择进入。

7.4.开机过程的问题解决

  • 如果忘记 root 密码,可通过以下方法解决:

    进入 menuentry 命令行,在linux16后添加参数rd.break,然后按下 <ctrl>+x 开始开机。

    linux16 ... rd.break
    

    这时就进入了一个用户为 root 的 Shell。

    rd.break是在 Ram Disk 中的 OS 系统状态。原来使用的 OS 中,作者的根目录/是被挂载在/dev/mapper/centos-root下的,而 Ram Disk 的 OS 系统,/dev/mapper/centos-root挂载的是/sysroot并非/,所以需要修改一下根目录(chroot)。同时,修改密码后,/etc/shadow的安全性文本会被取消,重新启动时会出现问题,可以通过两种方法解决:

    • 新建/.autorelabel空文件,让系统在开机的时候自动使用默认的 SELinux type 重新写入 SELinux 安全性文本到每个文件中去。
    • 修改完 root 密码后,修改/etc/selinux/config中 SELinux 模式修改为 permissive。重启后,执行restorecon -Rv /etc恢复/etc下安全性文本为默认,然后改回/etc/selinux/config中 SELinux 模式修改为 enforing 并执行setenforce 1

    如:

    mount # 查看挂载情况,对于作者 /dev/mapper/centos-root 应该挂载 /sysroot
    mount -o remount,rw /sysroot         # 将该目录挂载为可写
    chroot /sysroot                      # 切换根目录
    echo 'new_pwd' | passwd --stdin root # 修改 root 密码
    touch /.autorelabel
    exit
    reboot
    
  • 如果想开机后,直接使用 root 下的 Bash Shell,可通过进入 menuentry 命令行,在linux16后添加参数init=/bin/bash实现:

    linux16 ... init=/bin/bash
    

    这样同样不需要修改密码就可进入 Bash Shell。这样启动的系统,该 Bash Shell 为 PID 1。它的 PATH 仅仅是/bin,所以指令下的必须使用绝对路径。没有 systemd 或 init,所以无法使用/sbin/reboot重启,只能按下 reset 或强制关机后才能再次开机。

    通过此方法也能解决忘记 root 密码问题,步骤与上述类似,但不需要切换根目录:

    mount -o remount,rw /
    echo 'new_pwd' | passwd --stdin root
    touch /.autorelabel
    
  • 如果因文件系统出错而无法开机,一般系统会提示输入 root 密码进入救援模式。进入后重新将/挂载为可读写后进行后续处理(mount -o remount,rw /)。

    比如/etc/fstab设置错误,则需要修改该文件。

    比如制作的 EXT3 分区格式的/dev/md0的软件磁盘阵列在 fsck 出错,那么使用fsck.ext3对其进行修复,在出现“clear”是输入“yes”。如果是 XFS 系统则使用xfs_repairfsck.extNxfs_repair在前面介绍过,可能造成原数据文件损坏。

8.系统设置与备份策略

8.1.系统基本设置

  • nmcli,设置网络参数。nmcli是通过“连线代号”来设置网络参数,“连线代号”通常与“网卡代号”相同。

    nmcli connection show
    #NAME   UUID                                  TYPE      DEVICE 
    #ens33  901e1757-fe5a-4ff2-bda3-a2a54d947fbd  ethernet  ens33
    #连线代号                                       网卡类型   网卡代号
    
    nmcli connection show ens33 # 查看 ens33 的设置
    #...
    #connection.autoconnect:                 yes  # 开机是否启动该连线
    #ipv4.method:                            auto # 自动还是手动设置网络参数
    #ipv4.dns:                               --   # DNS 的 IP 地址
    #ipv4.addresses:                         --   # IP 与 netmask 的集合
    #ipv4.gateway:                           --   # 网关的 IP 地址
    
    nmcli connection modify ens33
    >connection.autoconnect yes \
    >ipv4.method manual \
    >ipv4.dns 172.16.200.254 \
    >ipv4.addresses 172.16.1.1/16 \
    >ipv4.gateway 172.16.200.254
    nmcli connection up ens33
    nmcli connection show ens33
    
    nmcli connection modify ens33
    >connection.autoconnect yes \
    >ipv4.method auto
    nmcli connection up ens33
    nmcli connection show ens33
    
  • hostnamectl [set-hostname 主机名],查看、修改主机名。/etc/hostname配置了主机名。

  • 时间设置:

    timedatectl [command]
    

    command 可以是:

    list-timezone,列出系统上所有支持的时区名称。

    set-timezone,设置时区位置。

    set-time,设置时间。

    set-ntp,设置网络校时系统。

    如:

    timedatectl
    timedatectl list-timezones | grep -i new
    timedatectl set-timezone "America/New_York"
    timedatectl
    timedatectl set-timezone "Asia/Shanghai"
    timedatectl set-time "2015-09-01 12:02"
    

    校对时间:

    ntpdate tock.stdtime.gov.tw # 以台湾标志时间校对
    hwclock -w                  # 将时间写入 BIOS
    
  • 语系设置:

    系统语系的配置文件为/etc/locale.conf,可通过localectl查看、设置。而软件的语系(比如使用的 Bash Shell)使用locale指令。

    localectl
    localectl set-locale LANG=en_US.utf8
    systemctl isolate multi-user.target
    systemctl isolate graphical.target
    

    如果其他语系未设置,LANG/LC_ALL被设置,其他语系将被替代。Linux 目前保有的语系文件位于/usr/lib/locale/下。

    对于 Bash Shell 软件的语系,修改 LC_ALL 后,还需要export将其变为环境变量。如export LC_ALL = en_US.utf-8

8.2.服务器硬件数据的收集

  • 系统自带的dmidecode软件,可解析 CPU 型号、主板型号、内存相关型号等。

    dmidecode -t type
    

    type指定为:

    • 1,详细的系统数据,含主板的型号与硬件的基础数据等。
    • 4,CPU 相关数据。
    • 9,系统相关的插槽格式,包括 PCI、PCI-E 等等的插槽规格说明。
    • 17,每个内存插槽的规格,若内有内存,则列出该内存的容量与型号。
  • lspci [-vvn]
    lsusb [-t]
    iostat [-c|-d] [-k|-m] [-t] [间隔秒数] [侦测次数]
    
  • 磁盘支持 SMART 的协定话,可使用 smartd 服务来了解磁盘的健康状态:

    smartctl -a /dev/sda		# 用 smartctl 来显示完整的 /dev/sda 信息
    # 命令磁盘进行一次自我检测的动作,然后再次观察磁盘状态
    smartctl -t short /dev/sda
    smartctl -a /dev/sda
    

    注意不建议在系统繁忙时进行,因为进行磁盘自我检查时,可能 I/O 状态较频繁。

8.3.备份

  • Linux 具有备份意义的数据:

    • 操作系统本身需要备份的文件:/etc//home//var/spool/mail/var/spool/{at|cron}/boot//root/,如果自行安装过其他的软件,那么/usr/local//opt也最好备份一下。
    • 网络服务的数据库方面
      • 软件本身的设置文件,如/etc//usr/local/
      • 软件服务提供的数据,如 WWW 数据有/var/www整个目录或/srv/www整个目录以及系统使用者主文件夹;Mariadb有/var/lib/mysql整个目录。
      • 其他在 Linux 主机上面提供的服务之数据库文件。
    • 推荐需要备份的目录:/etc/home/root/var/spool/mail//var/spool/cron//var/spool/at//var/lib
    • 不需要备份的目录:/dev/proc/sys/run/mnt/media/tmp
  • 备份可以分为积累备份和差异备份:

    • 积累备份:除第一次备份为完整备份后,此后备份都是备份与前一次有差异的文件。常用的工具有ddcpioxfsdump/xfsrestore等。可以通过tar来完整备份。
    • 差异备份:每次备份都是与原始的完整备份比较的结果。可以通过rsync来镜像备份。

杂项

  • 安装时所选的项目,包括 root 密码等等,通通会被记录到/root/anaconda-ks.cfg这个文件。

  • info page 类似 manual page,它以节点方式组织。任何页面可按h来看一些基本按键功能的介绍。把光标移动到*上按 <enter> 进入该节点,按 <tab> 可快速移动。

  • 主机前使用终端机(tty1-tty7)来登录系统时,不论以什么身份都能够关机,若使用远程管理工具(如 ssh),只有 root 可以。

  • /dev/null可以吃掉任何导向这个设备的信息。

  • cp会复制执行者的属性和权限。

  • echo-n参数可以不断行继续在同一行显示。

  • Linux 支持休眠模式的话,运行中的程序会被记录到 swap 中。

  • ls的 total 是该目录下文件占用的 block 大小,与文件本身大小有区别。

posted @ 2024-01-29 02:53  MeYokYang  阅读(33)  评论(0编辑  收藏  举报