鸟哥私房菜整理(二)

较高阶的硬件通常会向下兼容旧有的软件,但较高阶的软件可能无法在旧机器上面安装


vim学习:【文件夹中有关于三种模式的图片更直观】
所有的 Unix Like 系统都会内建 vi 文书编辑器,其他的文书编辑器则不一定会存在;
很多个别软件的编辑接口都会主动呼叫 vi (例如未来会谈到的 crontab, visudo, edquota 等指令);
vim 具有程序编辑的能力,可以主动的以字体颜色辨别语法的正确性,方便程序设计;
因为程序简单,编辑速度相当快速。
vim分为3种编辑模式: 一般模式、编辑模式、指令列模式
一般模式:
以 vi 打开一个档案就直接进入一般模式了(这是默认的模式)。在这个模式中, 你可以使用『上下左右 』按键来移动光标,你可以使用『删除字符』或『删除整行』来处理档案内容, 也可以使用『复制、 贴上』来处理你的文件数据。


编辑模式:
在一般模式中可以进行删除、复制、贴上等等的动作,但是却无法编辑文件内容的! 要等到你按下『i, I, o, O, a, A, r, R』等任何一个字母之后才会进入编辑模式。注意了!通常在 Linux 中,按下这些按键时,在画面的左下方会出现『 INSERT 或 REPLACE 』的字样,此时才可以进行编辑。而如果要回到 一般模式时, 则必须要按下『Esc』这个按键即可退出编辑模式。


指令列命令模式:
在一般模式当中,输入『 : / ? 』三个中的任何一个按钮,就可以将光标移动到最底下那一行。在这个 模式当中, 可以提供你『搜寻资料』的动作,而读取、存盘、大量取代字符、离开 vi 、显示行号等等 的动作则是在此模式中达成的!


vim 的暂存档、救援回复与开启时的警告讯息 P340(.filename.swap文档即为暂存当)
区块选择(Visual Block) P343
多档案编辑 P345
多窗口功能 P345
vim环境设定与编辑 以写入在 ~/.vimrc 档案中 P347 可以修改备注啊 是否显示行号啊什么的  挺重要的
预设环境,保证每次使用vim的设置都是自己想要的
中文编码的问题 P349
DOS 与 Linux 的断行字符 P348
可以发现在 DOS 使用的断行字符为 ^M$ ,我们称为 CR 与 LF 两个符号。 而在 Linux 底下,则是仅有 LF ($) 这个断行符号
使用 unix2dos 或 dos2unix 来转换一下断行格式啊
语系编码转换 P350
















第十一章 SHELL


Shell
我们必须要透过『 Shell 』将我们输入的命令与 Kernel 沟通,好让 Kernel 可以控制硬件来正确无误的工作
关于Bash shell
命令编修能力
在命令列按『上下键』就可以找到前/后一个输入的命令
命令与文件补全功能
[Tab] 接在一串命令的第一个字的后面,则为命令补全;
[Tab] 接在一串命令的第二个字以后时,则为『文件补齐』!
命令别名配置功能
例如   以 lm 这个自定义的命令来取代ls -al alias lm='ls -al'
工作控制、前景背景控制
程序化脚本
通配符
例如: 使用:『 ls -l /usr/bin/X* 』就能够知道 /usr/bin 底下有多少以 X 为开头的文件
type ⑴ 查看命令是否内建于bash ⑵ 主要在找出『运行档』而不是一般文件档名(有时候类似which)
那为什么会有内建于bash的指令呢?
① shell内建命令是指bash(或其它版本)工具集中的命令。一般都会有一个与之同名的系统命令,比如bash中的echo命令与/bin/echo是两个不同的命令,尽管他们行为大体相仿。当在bash中键入一个命令时系统会先看他是否是一个内建命令,如果不是才会查看是否是系统命令或第三方工具。所以在bash中上执行bash工具集中的bash命令也就是内建命令,而不是/bin/echo这个系统命令。
② 内建命令要比系统论命令有比较高的执行效率。外部命令执行时往往需要fork出(产生出)一个子进程,而内建命令一般不用


Shell的变量:
变量就是以一组文字或符号等,来取代一些配置或者是一串保留的数据
echo: 取用变量(变量在被取用时,前面必须要加上钱字号『 $ 』才行)
一些关于Bash变量的配置守则 在c2/c/linux文件夹中 或者 P363
env: 是列出来所有的环境变量 P366
set: 含环境变量与自定义变量(基本上,在 Linux 默认的情况中,使用{大写的字母}来配置的变量一般为系统内定需要的变量) P368
(PS1 就厉害了。这个是命令提示字符,也就是我们常见的 [root@www ~]# 或 [Ben ~]$ 的配置值啦!可以更动的)
PS1: 命令提示符
$: 关于shell的PID
?: 关于上个运行命令的回传值
export: P370
env 与 set : 两者之间的区别 『 该变量是否会被子程序所继续引用』
当你登陆 Linux 并取得一个 bash 之后,你的 bash 就是一个独立的程序,被称为 PID 的就是。 接下来你在这个 bash 底下所下达的任何命令都是由这个 bash 所衍生出来的,那些被下达的命令就被称为子程序了;因为子程序仅会继承父程序的环境变量, 子程序不会继承父程序的自定义变量 所以需要使用export来使得父程序的自定义变量在子程序中也能被使用


影响显示结果的语系变量(即可能产生乱码) 
有配置 LANG 或者是 LC_ALL 时,则其他的语系变量就会被这两个变量所取代! 这也是为什么我们在 Linux 当中,通常说明仅配置 LANG 这个变量而已,因为他是最主要的配置变量
locale 查看语系编码变量


变量的有效范围
环境变量=全局变量
自定义变量=局部变量
当启动一个 shell,操作系统会分配一记忆区块给 shell 使用,此内存内之变量可让子程序取用,若在父程序利用 export 功能,可以让自定义变量的内容写到上述的记忆区块当中(环境变量);当加载另一个 shell 时 (亦即启动子程序,而离开原本的父程序了),子 shell 可以将父 shell 的环境变量所在的记忆区块导入自己的环境变量区块当中。


read 读取来自键盘输入的变量 P373


declare / typeset 宣告变量的类型


ulimit 限制用户的某些系统资源(包括可以开启的文件数量, 可以使用的 CPU 时间,可以使用的内存总量等等) 375


变量内容的删除与取代
范例一:先让小写的 path 自定义变量配置的与 PATH 内容相同 (不懂看P376)
[root@www ~]# path=${PATH}
[root@www ~]# echo $path
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin


范例二:假设我不喜欢 kerberos,所以要将前两个目录删除掉,如何显示?
[root@www ~]# echo ${path#/*kerberos/bin:}
显示结果:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
(指令解读:${} 为系统默认必须   path为变量  #代表『从变量内容的最前面开始向右删除』,且仅删除最短的那个  #之后的/指的是变量最开始的/【意味着从/开始,当然这也要结合后面的*来看 】  之后的*指的是从最开始的/ 一直到 kerberos/bin: 这一部分都删除)
【【【【
${变量#关键词} 若变量内容从头开始的数据符合『关键词』,则将符合的最短数据删除
${变量##关键词} 若变量内容从头开始的数据符合『关键词』,则将符合的最长数据删除
${变量%关键词} 若变量内容从尾向前的数据符合『关键词』,则将符合的最短数据删除
${变量%%关键词} 若变量内容从尾向前的数据符合『关键词』,则将符合的最长数据删除
${变量/旧字符串/新字符串} 若变量内容符合『旧字符串』则『第一个旧字符串会被新字符串取代』
${变量//旧字符串/新字符串} 若变量内容符合『旧字符串』则『全部的旧字符串会被新字符串取代』
】】】】重要!!!!!!!!!!!P378


变量的测试与内容替换 P379
在某些时刻我们常常需要『判断』某个变量是否存在,若变量存在则使用既有的配置,若变量不存在则给予一个常用的配置
变量配置方式 str 没有配置 str 为空字符串 str 已配置非为空字符串
var=${str-expr} var=expr var= var=$str
var=${str:-expr} var=expr var=expr var=$str
var=${str+expr} var= var=expr var=expr
var=${str:+expr} var= var= var=expr
var=${str=expr} str=expr str不变 str不变
var=expr var= var=$str
var=${str:=expr} str=expr str=expr str不变
var=expr var=expr var=$str
var=${str?expr} expr 输出至 stderr var= var=$str
var=${str:?expr} expr 输出至 stderr expr 输出至 stderr var=$str


alias, unalias 【命令别名】是一个很有趣的东西,特别是你的惯用命令特别长的时候
可以通过直接输入alias 命令查看被起别名的命令


history 查询我们曾经下达过的命令
当我们以 bash 登陆 Linux 主机之后,系统会主动的由家目录的 ~/.bash_history 读取以前曾经下过的命令,那么 ~/.bash_history 会记录几笔数据呢?这就与你 bash 的 HISTFILESIZE 这个变量配置值有关了!
假设我这次登陆主机后,共下达过 100 次命令,『等我注销时, 系统就会将 101~1100 这总共 1000 笔历史命令升级到 ~/.bash_history 当中。』 也就是说,历史命令在我注销时,会将最近的 HISTFILESIZE 笔记录到我的纪录文件当中啦!
当然,也可以用 history -w 强制立刻写入的!那为何用『升级』两个字呢? 因为 ~/.bash_history 记录的笔数永远都是 HISTFILESIZE 那么多,旧的信息会被主动的拿掉! 仅保留最新的!
一些与history 的指令
[root@www ~]# history
    66  man rm
  67  alias
    68  man history
  69  history 
[root@www ~]# !66  <==运行第 66 笔命令
[root@www ~]# !!   <==运行上一个命令,本例中亦即 !66 
[root@www ~]# !al  <==运行最近以 al 为开头的命令(上头列出的第 67 个)


系统中有许多相同命令的指令,那么执行的顺序是什么呢?
1、以相对/绝对路径运行命令,例如『 /bin/ls 』或『 ./ls 』;
2、由 alias 找到该命令来运行;(透过alias 来指定别名的指令)
3、由 bash 内建的 (builtin) 命令来运行;
4、透过 $PATH 这个变量的顺序搜寻到的第一个命令来运行。


/etc/issue 可以通过修改这个文档的内容修改开机信息(什么时候的欢迎信息呢?就是在切换到或者刚进入文字接口的时候显示的几行东西  可以修复的哦)
/etc/motd 这个是在用户登录(输入用户名密码成功进入后)显示出的信息  可以修改这个文档类来给使用这个系统的用户一些提示或警告(比如什么时候会维修啊什么的)


bash的环境配置文件
为什么我们已进入linux系统就拥有很多有用的变量呢?是因为系统会取得bash
但是不同的登入状态所取得的bash不同:
那分为哪两种登录状态呢?分别读取的文档又分别是什么呢?
login bash: 取得 bash 时需要完整的登陆流程的就称为ligin bash   例如:要由 tty1 ~ tty6 登陆,需要输入用户的账号与密码,此时取得的 bash 就 称为『 login shell 』
login bash 读取的文档:
① /etc/profile : 配置整体环境(主要内容见P387)
同时会调用其他三个文档/etc/inputrc、/etc/profile.d/*.sh、/etc/sysconfig/i18n
② ~/.bash_profile 或 ~/.bash_login 或 ~/.profile: (主要见P388)
属于使用者个人配置,你要改自己的数据,就写入这里
:三个文档只读一个且只要存在一个则其他不读取(优先级按当前顺序)
non-login bash:取得 bash 接口的方法不需要重复登陆的举动   例如:(1) 你以 X window 登陆 Linux 后, 再以 X 的图形化接口启动终端机,此时那个终端接口并 没 有需要再次的输入账号与密码,那个 bash 的环境就称为 non-login shell了。(2) 你在原本的 bash 环境下再次下达 bash 这个命令,同样的也没有输入 账号密码, 那第二个 bash (子程序) 也是 non-login shell 。
non-login bash读取的文档:
~/.bashrc P389
见过一些配置文档后,如果想要修改,并要现改现用的话 就要用到source指令(否则的话就要注销再登录才用得到喔)
source(或小数点“ . ”): 读入环境配置文件的命令
还有一些文档会影响bash操作[【详见P390】
① /etc/man.config :这的文件的内容『规范了使用 man 的时候, man page 的路径到哪里去寻找』
如果你是以 tarball 的方式来安装你的数据,那么你的 man page 可能会放置在 /usr/local/softpackage/man 里头,那个 softpackage 是你的套件名称, 这个时候你就得以手动的方式将该路径加到 /etc/man.config 里头,否则使用 man 的时候就会找不到相关的说明档
② ~/.bash_history
历史命令就记录在这里
③ ~/.bash_logout
这个文件则记录了『当我注销 bash 后,系统再帮我做完什么动作后才离开』


终端机的环境设定:找出 /etc/ 底下文件名含有数字的文件名
stty -a可以看见所有终端机按键内容
例如:
ctrl+D : eof    End of file 的意思,代表『结束输入』。
ctrl+?  : erase  向后删除字符,
ctrl+C : intr   送出一个 interrupt (中断) 的讯号给目前正在 run 的程序;
ctrl+U : kill   删除在目前命令列上的所有文字;
调用[root@www ~]# stty erase ^h 那么以后删除字符就得要使用 [ctrl]+h 
set 在之前学到可以显示环境和自定义变量  在这里也可以进行环境的配置(自己man set看)


接下来看一些linux下的通配符与特殊符号 (还有许多未列出来 详细见P393
* 代表『 0 个到无穷多个』任意字符
[root@www ~]# ll -d /etc/cron*     找出 /etc/ 底下以 cron 为开头的档名 加上 -d 是为了仅显示目录而已


? 代表『一定有一个』任意字符
[root@www ~]# ll -d /etc/????? 找出 /etc/ 底下文件名『刚好是五个字母』的文件名


[ ] 同样代表『一定有一个在括号内』的字符(非任意字符)。例如 [abcd] 代表『一定有一个字符, 可能是 a, b, c, d 这四个任何一个』


[ - ] 若有减号在中括号内时,代表『在编码顺序内的所有字符』。例如 [0-9] 代表 0 到 9 之间的所有数字,因为数字的语系编码是连续的!
[root@www ~]# ll -d /etc/*[0-9]* 找出 /etc/ 底下文件名含有数字的文件名 记得中括号左右两边均需 *


[^ ] 若中括号内的第一个字符为指数符号 (^) ,那表示『反向选择』,例如 [^abc] 代表 一定有一个字符,只要是非 a, b, c 的其他字符就接受的意思。
[root@www ~]# ll -d /etc/[^a-z]* 找出 /etc/ 底下,档名开头非为小写字母的文件名;注意中括号左边没有 *




数据流重导向 P394
数据流重导向就是将某个命令运行后应该要出现在屏幕上的数据, 给他传输到其他的地方,例如文件或者是装置 (例如打印机之类的)
一个命令执行结果有两种:分别为standard output 与 standard error output (分别代表『标准输出』与『标准错误输出』)
标准输入  (stdin) :代码为 0 ,使用 < 或 << ;
标准输出  (stdout):代码为 1 ,使用 > 或 >> ;
标准错误输出(stderr):代码为 2 ,使用 2> 或 2>> ;


<    : 『将原本需要由键盘输入的数据,改由文件内容来取代』 P396
<<  :【
[root@www ~]# cat > catfile << "eof"
> This is a test.
> OK now stop
> eof  <==输入这关键词,立刻就结束而不需要输入 [ctrl]+d
       】
1> :以覆盖的方法将『正确的数据』输出到指定的文件或装置上;
1>>:以累加的方法将『正确的数据』输出到指定的文件或装置上;
2> :以覆盖的方法将『错误的数据』输出到指定的文件或装置上;
2>>:以累加的方法将『错误的数据』输出到指定的文件或装置上;


不过当我有错误信息不希望输出到文件或装置上呢 那就输出到/dev/null 上(相当于垃圾桶、黑洞哦)
当我想把正确信息和错误信息同时输出到同一个地方呢?
[dmtsai@www ~]$ find /home -name .bashrc > list 2>&1
[dmtsai@www ~]$ find /home -name .bashrc &> list 
什么时候用得到这个导向呢?
① 屏幕输出的信息很重要,而且我们需要将他存下来的时候;
② 背景运行中的程序,不希望他干扰屏幕正常的输出结果时;
③ 一些系统的例行命令 (例如写在 /etc/crontab 中的文件) 的运行结果,希望他可以存下来时;
④ 一些运行命令的可能已知错误信息时,想以『 2> /dev/null 』将他丢掉时;
⑤ 错误信息与正确信息需要分别输出时。


命令运行的判断依据:
“;”  :   cmd ; cmd (不考虑命令相关性的连续命令下达)


与 &&  :  cmd1 && cmd2 1. 若 cmd1 运行完毕且正确运行($?=0),则开始运行 cmd2。
2. 若 cmd1 运行完毕且为错误 ($?≠0),则 cmd2 不运行。


或 || cmd1 || cmd2 1. 若 cmd1 运行完毕且正确运行($?=0),则 cmd2 不运行。
2. 若 cmd1 运行完毕且为错误 ($?≠0),则开始运行 cmd2。


管线命令: “ | ” P400
如果数据必需要经过几道手续之后才能得到我们所想要的格式,此时就要用到管线命令
注意
管线命令仅会处理 standard output,对于 standard error output 会予以忽略
管线命令必须要能够接受来自前一个命令的数据成为 standard input 继续处理才行
管线命令下的指令:
cut:将一段信息的某一段给他『切』出来。主要的用途在于将『同一行里面的数据进行分解!』最常使用在分析一些数据或文字数据的时候
grep: 分析一行信息, 若当中有我们所需要的信息,就将该行拿出来
sort:进行排序,而且可以依据不同的数据型态来排序
uniq:将重复的数据仅列出一个显示
wc:计算输出的信息的多少字?多少行?多少字符
tee:双向重导向  会将数据流整个传送给文件或装置 同时 输出到屏幕
字符转换命令: P405
tr:可以用来删除一段信息当中的文字,或者是进行文字信息的替换
col:① 将 [tab] 按键取代成为空格键 ② 常被利用于将 man page 转存为纯文本文件以方便查阅的功能(不用col存的话会有许多怪异字符)
join:两个文件当中,有 "相同数据"【这里的相同数据指的是A文档中的C部分数据 与 B文档的D部分数据 相同】 的那一行,才将他加在一起』
paste:paste 就直接『将两行贴在一起,且中间以 [tab] 键隔开』而已
expand:将 [tab] 按键转成空格键
split: 可以帮你将一个大文件,依据文件大小或行数来分割,就可以将大文件分割成为小文件了 P409
减号 -: 在管线命令当中,常常会使用到前一个命令的 stdout 作为这次的 stdin , 某些命令需要用到文件名 (例如 tar) 来进行处理时,该 stdin 与 stdout 可以利用减号 "-" 来替代, 举例来说:
[root@www ~]# tar -cvf - /home | tar -xvf -
上面这个例子是说:『我将 /home 里面的文件给他打包,但打包的数据不是纪录到文件,而是传送到 stdout; 经过管线后,将 tar -cvf - /home 传送给后面的 tar -xvf - 』。后面的这个 - 则是取用前一个命令的 stdout, 因此,我们就不需要使用 file 了!












第十二章        正规表示法与文件格式化处理
为什么正规表示法的时候提倡LANG=C呢?
因为:
LANG=C     时: 0 1 2 3 4 ... A B C D ... Z a b c d ...z
LANG=zh_TW 时: 0 1 2 3 4 ... a A b B c C d D ... z Z
如果你想要撷取大写字节而使用 [A-Z] 时, 会发现 LANG=C 确实可以仅捉到大写字节 (因为是连续的) ,但是如果 LANG=zh_TW.big5 时,就会发现到, 连同小写的 b-z 也会被撷取出来
[: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:] 代表标点符号 (punctuation symbol),亦即:" ' ? ! ; : # $...
[:upper:] 代表大写字节,亦即 A-Z
[:space:] 任何会产生空白的字节,包括空白键, [Tab], CR 等等
[:xdigit:] 代表 16 进位的数字类型,因此包括: 0-9, A-F, a-f 的数字与字节


grep: grep 在数据中查寻一个字串时,是以 "整行" 为单位来进行数据的撷取的 P420 许多关于正规表示法的练习
① 搜寻特定字串(或是反向选择 即列出没有该特定字符串的行)
② 利用中括号 [] 来搜寻集合字节([] 里面不论有几个字节,他都谨代表某『一个』字节)  即[]里面的字节为或的关系
③ 行首与行尾字节 ^ $
④ 任意一个字节 . 与重复字节 *
. (小数点):代表『一定有一个任意字节』的意思; (与bash中的?差不多)
* (星星号):代表『重复前一个字节, 0 到无穷多次』的意思,为组合形态 (与bash中的*不同) 这句话的意思是*前面的字节可能没有,也可能有未知个
⑤ 限定连续 RE 字符范围 {} (注意:因为 ‘ { ’ 与 ‘ } ’ 的符号在 shell 是有特殊意义的,因此, 我们必须要使用跳脱字符 \ 来让他失去特殊意义才行)


sed工具 P428
注意:sed后面如果接两个或两个以上的动作时,则每个动作前面要加上一个 -e
以行为单位的新增/删除功能 (sed '[n1[,n2]]function') P429
以行为单位的取代与显示功能
部分数据的搜寻并取代的功能
直接修改文件内容(危险动作)


延伸正规表示法 P432
若要使用延伸正规表示法 那么就不能继续用grep了  而是要用egrep 了。
+ 意义:重复『一个或一个以上』的前一个 RE 字符
范例:搜寻 (god) (good) (goood)... 等等的字串。 那个 o+ 代表『一个以上的 o 』所以,底下的运行成果会将第 1, 9, 13 行列出来。
egrep -n 'go+d' regular_express.txt
? 意义:『零个或一个』的前一个 RE 字符
范例:搜寻 (gd) (god) 这两个字串。 那个 o? 代表『空的或 1 个 o 』所以,上面的运行成果会将第 13, 14 行列出来。 有没有发现到,这两个案例( 'go+d' 与 'go?d' ) 的结果集合与 'go*d' 相同? 想想看,这是为什么喔! ^_^
egrep -n 'go?d' regular_express.txt
| 意义:用或( or )的方式找出数个字串
范例:搜寻 gd 或 good 这两个字串,注意,是『或』! 所以,第 1,9,14 这三行都可以被列印出来喔!那如果还想要找出 dog 呢?
egrep -n 'gd|good' regular_express.txt
egrep -n 'gd|good|dog' regular_express.txt
() 意义:找出『群组』字串
范例:搜寻 (glad) 或 (good) 这两个字串,因为 g 与 d 是重复的,所以, 我就可以将 la 与 oo 列於 ( ) 当中,并以 | 来分隔开来,就可以啦!
egrep -n 'g(la|oo)d' regular_express.txt
()+ 意义:多个重复群组的判别
范例:将『AxyzxyzxyzxyzC』用 echo 叫出,然后再使用如下的方法搜寻一下!
echo 'AxyzxyzxyzxyzC' | egrep 'A(xyz)+C'
上面的例子意思是说,我要找开头是 A 结尾是 C ,中间有一个以上的 "xyz" 字串的意思~


格式化列印: printf P434


awk:好用的数据处理工具 P435
awk 是『以行为一次处理的单位』, 而『以栏位为最小的处理单位』
(相较於 sed 常常作用於一整个行的处理, awk 则比较倾向於一行当中分成数个『栏位』来处理,awk 主要是处理『每一行的栏位内的数据』,而默认的『栏位的分隔符号为 "空白键" 或 "[tab]键" 』)
每一行的每个栏位都是有变量名称的,那就是 $1, $2... 等变量名称
整个 awk 的处理流程是:
① 读入第一行,并将第一行的数据填入 $0, $1, $2.... 等变量当中;
② 依据 "条件类型" 的限制,判断是否需要进行后面的 "动作";
③ 做完所有的动作与条件类型;
④ 若还有后续的『行』的数据,则重复上面 1~3 的步骤,直到所有的数据都读完为止。
awk实例: P438 重要!!!(自己在写的时候注意加上分号)
与 bash shell 的变量不同,在 awk 当中,变量可以直接使用,不需加上 $ 符号。
格式化输出时,在 printf 的格式配置当中,务必加上 \n ,才能进行分行!
逻辑运算当中,如果是『等於』的情况,则务必使用两个等号『==』!
如果有需要多个命令辅助时,可利用分号『;』间隔


diff 通常是用在同一的文件(或软件)的新旧版本差异上 P439
得到的结果很详细 哪里不同 哪里被删掉这些信息都有
cmp cmp 主要也是在比对两个文件,他主要利用『位组』单位去比对, 因此,当然也可以比对 binary file 
注意:diff 主要是以『行』为单位比对, cmp 则是以『位组』为单位去比对


pr P441
标题中会有『文件时间』、『文件档名』及『页码』三大项目。 更多的 pr 使用,请参考 pr 的说明












第十三章、学习 Shell Scripts




shell script 是利用 shell 的功能所写的一个『程序 (program)』,这个程序是使用纯文字档,将一些 shell 的语法与命令(含外部命令)写在里面, 搭配正规表示法、管线命令与数据流重导向等功能,以达到我们所想要的处理目的。 P445

注意事项:
命令的运行是从上而下、从左而右的分析与运行;
命令的下达就如同第五章内提到的: 命令、选项与参数间的多个空白都会被忽略掉;
空白行也将被忽略掉,并且 [tab] 按键所推开的空白同样视为空白键;
如果读取到一个 Enter 符号 (CR) ,就尝试开始运行该行 (或该串) 命令;
至於如果一行的内容太多,则可以使用『 \[Enter] 』来延伸至下一行;
『 # 』可做为注解!任何加在 # 后面的数据将全部被视为注解文字而被忽略!


如何运行文件:
直接命令下达: shell.sh 文件必须要具备可读与可运行 (rx) 的权限,然后:
绝对路径:使用 /home/dmtsai/shell.sh 来下达命令;
相对路径:假设工作目录在 /home/dmtsai/ ,则使用 ./shell.sh 来运行
变量『PATH』功能:将 shell.sh 放在 PATH 指定的目录内,例如: ~/bin/
以 bash 程序来运行:透过『 bash shell.sh 』或『 sh shell.sh 』来运行


文件内容:
① 第一行 #!/bin/bash 在宣告这个 script 使用的 shell 名称
必须要以『 #!/bin/bash 』来宣告这个文件内的语法使用 bash 的语法,在很多状况中,如果没有配置好这一行, 那么该程序很可能会无法运行,因为系统可能无法判断该程序需要使用什么 shell 来运行啊
② 程序内容的说明
③ 主要环境变量的宣告
④ 主要程序部分
⑤ 运行成果告知(即exit 0或其他)


撰写第一支 script P447
对谈式脚本:变量内容由使用者决定 P450
随日期变化:利用 date 进行文件的创建
数值运算:简单的加减乘除


直接运行script 与 利用source 来运行script 是不一样的
直接运行: 当子程序完成后,在子程序内的各项变量或动作将会结束而不会传回到父程序中
source运行:在script中的变量在父程序中依旧可以使用


test 检测系统上面某些文件或者是相关的属性 P453 在linux下的 /root/scripts/sh05文档


[ ] 进行数据的判断 P455 在linux下的 /root/scripts/sh06文档


Shell script 的默认变量($0, $1...) 这个十分重要 就好像函数的参数一样!!!!


参数(还有shift) P457 在linux下的 /root/scripts/sh07文档 和 在linux下的 /root/scripts/sh08文档


if .... then...fi P459 在linux下的 /root/scripts/sh06-2文档 和 在linux下的 /root/scripts/sh06-3文档
if...elif...else...fi


case....esac P464
相当于C语言中的switch case只是格式上需要注意一些


function 函数功能 P466
因为 shell script 的运行方式是由上而下,由左而右, 因此在 shell script 当中的 function 的配置一定要在程序的最前面
function 也是拥有内建变量的~他的内建变量与 shell script 很类似, 函数名称代表示 $0 ,而后续接的变量也是以 $1, $2... 来取代的
因此『 function fname() { 程序段 } 』内的 $0, $1... 等等与 shell script 的 $0 是不同的


回圈 (loop) 468
① while do done, until do done (不定回圈)
while:『当 condition 条件成立时,就进行回圈,直到 condition 的条件不成立才停止』
until:『当 condition 条件成立时,就终止回圈, 否则就持续进行回圈的程序段。』
② for...do...done (固定回圈) P470
for var in con1 con2 con3 ...   例如:for animal in dog cat elephant 是指从dog开始一次一次执行for内容直到pig
for (( 初始值; 限制值; 运行步阶 )) 例如:for (( i=1; i<=$nu; i=i+1 ))


shell script 的追踪与 debug P473
[root@www ~]# sh [-nvx] scripts.sh
选项与参数:
-n  :不要运行 script,仅查询语法的问题;
-v  :再运行 sccript 前,先将 scripts 的内容输出到萤幕上;
-x  :将使用到的 script 内容显示到萤幕上,即将命令运行过程也显示出来, 如此使用者可以判断程序码运行到哪一段时会出现相关的资讯
















第十四章、Linux 账号管理与 ACL 权限配置


每个登陆的使用者至少都会取得两个 ID ,一个是使用者 ID (User ID ,简称 UID)、一个是群组 ID (Group ID ,简称 GID)。


输入账号口令后,系统处理了什么呢?
① 先找寻 /etc/passwd 里面是否有你输入的账号?如果没有则跳出,如果有的话则将该账号对应的 UID 与 GID (在 /etc/group 中) 读出来,另外,该账号的家目录与 shell 配置也一并读出;
② 再来则是核对口令表啦!这时 Linux 会进入 /etc/shadow 里面找出对应的账号与 UID,然后核对一下你刚刚输入的口令与里头的口令是否相符?
③ 如果一切都 OK 的话,就进入 Shell 控管的阶段


一些重要的相关文档:
/etc/passwd    +   /etc/shadow
⑴ /etc/passwd 文件结构 ,每一行使用『:』分隔开,共有七个咚咚: P479
① 账号名称: 用来对应 UID 的。例如 root 的 UID 对应就是 0 (第三字段)
② 口令 将这个字段的口令数据给他改放到 /etc/shadow 中了。所以这里你会看到一个『 x 』
③ UID 使用者标识符
④ GID 与 /etc/group 有关
⑤ 用户信息说明栏 解释这个账号的意义,如果提供使用 finger 的功能时, 这个字段可以提供很多的信息
⑥ 家目录 用户的家目录
⑦ Shell 指定使用的bash
⑵ /etc/shadow 文件结构,以『:』作为分隔符,共有九个字段 P481
① 账号名称
② 口令
③ 最近更动口令的日期 这是真正的口令,经过编码的口令 (加密) 
④ 口令不可被更动的天数(与第 3 字段相比) 这个账号的口令在最近一次被更改后需要经过几天才可以再被变更你
⑤ 口令需要重新变更的天数(与第 3 字段相比) 必须要在这个天数内重新配置你的口令,否则这个账号的口令将会『变为过期特性』
⑥ 口令需要变更期限前的警告天数(与第 5 字段相比) 再过 n 天你的口令就要过期了,请尽快重新配置你的口令
⑦ 口令过期后的账号宽限时间(与第 5 字段相比) 如果口令过期了, 那当你登陆系统时,系统会强制要求你必须要重新配置口令才能登陆继续使用喔,这就是口令过期特性。
⑧ 账号失效日期 这个账号在此字段规定的日期之后,将无法再使用
⑨ 保留 最后一个字段是保留的,看以后有没有新功能加入。

⑶ /etc/group 文件结构 P484
① 组名
② 群组密码
③ GID
④ 群组支持的用户名称
什么是初始群组(initial group)? P485
GID 就是所谓的『初始群组 (initial group) 』!也就是说,当用户一登入系统,立刻就拥有这个群组的相关权限。非 initial group 的其他群组可就不同了,需要手动在该群组中添加用户
什么是有效群组
利用指令  groups :观察有效与支持群组。  观察结果中第一个即为有效群组。
有效群组有什么用? 
在我们新建文档等的时候,文档所属的群组即为有效群组。
那怎么更改有效群组呢?
newgrp指令。  不过注意该指令 可以变更目前用户的有效群组, 而且是另外以一个 shell 来提供这个功能的!!!注意了!  需要以exit来退出这个shell
⑷ /etc/gshadow P496
① 组名
② 口令栏,同样的,开头为 ! 表示无合法口令,所以无群组管理员
③ 群组管理员的账号 (相关信息在 gpasswd 中介绍)
④ 该群组的所属账号 (与 /etc/group 内容相同!)
gshadow 最大的功能就是创建群组管理员


账号管理------------:
useradd:新增用户 P487
在使用useradd时候,参数大多是使用的是默认的
比如:::
在 /etc/passwd 里面创建一行与账号相关的数据,包括创建 UID/GID/家目录等;
在 /etc/shadow 里面将此账号的口令相关参数填入,但是尚未有口令;
在 /etc/group 里面加入一个与账号名称一模一样的组名;
在 /home 底下创建一个与账号同名的目录作为用户家目录,且权限为 700
也可以在创建时候自定义而非采用默认 如修改UID 、不创建同名的群组、 创建系统帐号(默认不建家目录)
useradd -D 可以呼出默认值
在使用useradd的同时会更改不少地方:
用户账号与口令参数方面的文件:/etc/passwd, /etc/shadow
使用者群组相关方面的文件:/etc/group, /etc/gshadow
用户的家目录:/home/账号名称
useradd 参考档: P489


passwd:更改密码 P491
root可不需要通过用户键盘输入直接给普通用户指定密码 如:(好处是方便处理,缺点是这个口令会保留在命令中, 未来若系统被攻破,人家可以在 /root/.bash_history 找到这个口令呢) :[root@www ~]# echo "abc543CC" | passwd --stdin Ben  可用于批量新建帐号
也可以对账户做出限制:
要求用户每n天修改一次密码,密码过期m天后失效。
令某帐号失效
显示帐号信息
等等。。。


chage:更详细的口令参数显示功能 P494
查看帐号详细参数
限制第一次登录的账户必须修改密码后才能使用


usermod:账号相关数据的微调 P495
设置失效日期
为系统账户创建家目录


userdel:
-r  :连同用户的家目录也一起删除

用户功能:
finger:可以查阅很多用户相关的信息 P497
创建自己的计划档
找出目前在系统上面登陆的用户与登陆时间

chfn: P498
自己更改一下自己的相关信息


chsh:用 Ben1 的身份列出系统上所有合法的 shell,并且指定 csh 为自己的 shell P499


id:查阅账户相关的信息 P499


新增与移除群组:
groupadd:添加群组
groupdel:删除群组(必须要确认 /etc/passwd 内的账号没有任何人使用该群组作为 initial group 』)
gpasswd:添加某群组的管理员 用来 执行该群组的用户加入删除 P502


账号管理实例: 这里有两个实例
① 新增几个用户,同时设立群组 并赋予密码(用到useradd、groupadd、passwd)
② 新增几个用户,需要在一个文件夹工作(用到groupadd、useradd、passwd、chgrp、chmod、SGID)
注意的是:这里为什么使用到SUID呢?  这里回顾以下SGID:
① 使用者若对於此目录具有 r 与 x 的权限时,该使用者能够进入此目录;
② 使用者在此目录下的有效群组(effective group)将会变成该目录的群组;
③ 用途:若使用者在此目录下具有 w 的权限(可以新建文件),则使用者所创建的新文件,该新文件的群组与此目录的群组相同。
重点是第二点。在这个例子里,我们将文件夹的group改为工作群组,几个用户也添加进群组后,每个人在这个文件夹所创建的文档等都是属于自己的初始群组的(因为默认的有效群组是初始群组,所创建的文档也属于默认群组,每个用户的初始群组是不一样的),这样一来,某用户创建的文档其他组员也不能修改。解决办法是通过修改文件夹的群组权限为 rws 而不是之前的 rwx ,即赋予SGID权限,这样每个用户进来之后有效群组会自动改为当前目录群组,这样一来,每个用户可以随意修改每个文档了,因为每个文档的所属群组和是一样的。
注意:不同群组(owner的初始群组)的文档即使其owner在同一个群组(非默认群组),也不具备群组(所在的同一群组但不是默认群组)的权限。因此,文档只有在其群组和用户的群组相同且 group的权限可以w的情况下才能相互修改

ACL:用来规范特定的个人或群组的权限 P504
什么是ACL:使用者 (user):可以针对使用者来配置权限;
  群组 (group):针对群组为对象来配置其权限;
  默认属性 (mask):还可以针对在该目录下在创建新文件/目录时,规范新数据的默认权限;
如何启动ACL(可能不支持) P504
setfacl:配置某个目录/文件的 ACL 规范 P505
为单一使用者配置某文档或文件夹的权限(一旦被配置,权限部分就会多出一个 + 号)
getfacl:取得某个文件/目录的 ACL 配置项目
这里面显示的mask是什么呢?
使用者或群组所配置的权限必须要存在于 mask 的权限配置范围内才会生效,此即『有效权限 (effective permission)』【即最终权限是两权限集合中的相交部分】
ACL 的权限配置图和被次目录所『继承?』: 配置规范:『 d:[ug]:使用者列表:[rwx] 』 P508
『 setfacl -b 檔名 』:让 ACL 的属性全部消失


使用者身份切换: P509
su:   su 和 su - 是不一样的。有没有加上那个减号『 - 』差很多! 因为涉及 login-shell 与 non-login shell 的变量读取方法。单纯使用 - 如『 su - 』代表使用 login-shell 的变量文件读取方式来登陆系统; 若使用者名称没有加上去,则代表切换为 root 的身份。
单纯使用『 su 』切换成为 root 的身份,读取的变量配置方式为 non-login shell 的方式,这种方式很多原本的变量不会被改变, 尤其是我们之前谈过很多次的 PATH 这个变量,由于没有改变成为 root 的环境 (一堆 /sbin, /usr/sbin 等目录都没有被包含进来), 因此很多 root 惯用的命令就只能使用绝对路径来运行咯。其他的还有 MAIL 这个变量,你输入 mail 时, 收到的邮件竟然还是 Ben1 的,而不是 root 本身的邮件!是否觉得很奇怪啊!所以切换身份时,请务必使用 su - 用户名
若此时Ben 想要运行『 head -n 3 /etc/shadow 』一次,且已知 root 口令:
只需要 [Ben@www ~]$ su - -c "head -n 3 /etc/shadow"   结束后并没有切换用户为root依旧是Ben
总结注意:
若要完整的切换到新使用者的环境,必须要使用『 su - username 』或『 su -l username 』, 才会连同 PATH/USER/MAIL 等变量都转成新用户的环境;
如果仅想要运行一次 root 的命令,可以利用『 su - -c "命令串" 』的方式来处理;
使用 root 切换成为任何使用者时,并不需要输入新用户的口令;
使用su的缺陷是如果想要使用root则必须知道root的口令,这样容易导致口令的泄漏,因此sudo更安全。

sudo: P511
并非所有人都能够运行 sudo , 而是仅有规范到 /etc/sudoers 内的用户才能够运行 sudo 这个命令
如果想要以 sshd 的身份在 /tmp 底下创建一个名为 mysshd 的文件,该如何创建呢?【注意,sshd为系统账户,且运行的shell为nologin,因此无法登入系统,那么这时候就需要用到sudo了】   即 [root@www ~]# sudo -u sshd touch /tmp/mysshd 【-u  :后面可以接欲切换的使用者,若无此项则代表切换身份为 root 。】
sudo运行流程:
当用户运行 sudo 时,系统于 /etc/sudoers 文件中搜寻该使用者是否有运行 sudo 的权限;
若使用者具有可运行 sudo 的权限后,便让使用者『输入用户自己的口令』来确认;
若口令输入成功,便开始进行 sudo 后续接的命令(但 root 运行 sudo 时,不需要输入口令);
若欲切换的身份与运行者身份相同,那也不需要输入口令。
因此,『能否使用 sudo 必须要看 /etc/sudoers 的配置值, 而可使用 sudo 者是透过输入用户自己的口令来运行后续的命令串』。
除了 root 之外的其他账号,若想要使用 sudo 运行属于 root 的权限命令,则 root 需要先使用 visudo 去修改 /etc/sudoers ,让该账号能够使用全部或部分的 root 命令功能
修改要求:
① 单一用户可进行 root 所有命令,与 sudoers 文件语法。 P512
② 利用群组以及免口令的功能处理 visudo【意味着一个群组里的用户都能拥有权限】 P513
③ 有限制的命令操作【意味着拥有特定的命令的执行权】 P514
④ 透过别名建置 visudo【这样子的话就可以用一个别名代表许多账户,一个别名代替许多想分配的指令权限】
⑤ sudo 的时间间隔问题【在一段时间内如果普通用户使用过sudo,那这段时间内就不需要再次输入口令】
⑥ sudo 搭配 su 的使用方式【一口气将身份转为root且输入自己的口令】 P515


特殊的 shell, /sbin/nologin: P516
一般系统帐号都是使用的nologin shel,因此无法通过口令登陆主机。但是只是指『这个使用者无法使用 bash 或其他 shell 来登陆系统』而已, 并不是说这个账号就无法使用其他的系统资源。
举例来说,各个系统账号,打印作业由 lp 这个账号在管理, WWW 服务由 apache 这个账号在管理, 他们都可以进行系统程序的工作,但是『就是无法登陆主机』而已。
另外,如果我想让nologin shell 的账户知道为什么他们不能登录主机时,我们可以创建『 /etc/nologin.txt 』这个文件, 并且在这个文件内说明不能登陆的原因。这样一来,在他们尝试登录时,就会显示txt中的内容而非默认的内容。


PAM 模块简介 P517
PAM 可以说是一套应用程序编程接口 (Application Programming Interface, API),他提供了一连串的验证机制,只要使用者将验证阶段的需求告知 PAM 后, PAM 就能够回报使用者验证的结果 (成功或失败)。
举例来说:当你运行 passwd 后,这支程序呼叫 PAM 的流程是 P518
① 用户开始运行 /usr/bin/passwd 这支程序,并输入口令;
② passwd 呼叫 PAM 模块进行验证;
③ PAM 模块会到 /etc/pam.d/ 找寻与程序 (passwd) 同名的配置文件;
④ 依据 /etc/pam.d/passwd 内的配置,引用相关的 PAM 模块逐步进行验证分析;
⑤ 将验证结果 (成功、失败以及其他信息) 回传给 passwd 这支程序;
⑥ passwd 这支程序会根据 PAM 回传的结果决定下一个动作 (重新输入新口令或者通过验证!)
接着让我们来查看使用到的 /etc/pam.d/passwd文档,分别是验证类别(type)、控制标准(flag)、PAM的模块与该模块的参数。
第一个字段:验证类别 (Type)
验证类别主要分为四种:
① auth:检验使用者的身份验证
② account : 检验使用者是否具有正确的权限, 举例来说,当你使用一个过期的口令来登陆时,当然就无法正确的登陆了
③ session:是使用者在这次登陆 (或使用这个命令) 期间,PAM 所给予的环境配置
④ password : 这种类别主要在提供验证的修订工作,举例来说,就是修改/变更口令
第二个字段:验证的控制旗标 (control flag)
主要也分为四种控制方式:
① required:不论成功或失败都会继续后续的验证流程
② requisite:若验证失败则立刻回报原程序 failure 的标志,并终止后续的验证流程
③ sufficient:若验证成功则立刻回传 success 给原程序,并终止后续的验证流程;若验证失败则带有 failure 标志并继续后续的验证流程
④ optional:这个模块控件目大多是在显示信息而已,并不是用在验证方面的。
程序运行过程中遇到验证时才会去呼叫 PAM ,而 PAM 验证又分很多类型与控制,不同的控制旗标所回报的信息并不相同


一些常用模块的简介 P520
pam_securetty.so:限制系统管理员 (root) 只能够从安全的 (secure) 终端机登陆。那什么是终端机?例如 tty1, tty2 等就是传统的终端机装置名称。那么安全的终端机配置呢? 就写在 /etc/securetty 这个文件中。你可以查阅一下该文件, 就知道为什么 root 可以从 tty1~tty7 登陆,但却无法透过 telnet 登陆 Linux 主机了
pam_nologin.so:限制一般用户是否能够登陆主机之用
pam_selinux.so:针对程序来进行细部管理权限的功能
pam_console.so:当系统出现某些问题,或者是某些时刻你需要使用特殊的终端接口 (例如 RS232 之类的终端联机设备) 登陆主机时, 这个模块可以帮助处理一些文件权限的问题,让使用者可以透过特殊终端接口 (console) 顺利的登陆系统
pam_loginuid.so:系统账号与一般账号的 UID 的限制
pam_env.so:用来配置环境变量的一个模块
pam_unix.so:
pam_cracklib.so:可以用来检验口令的强度
pam_limits.so:口令ulimit,就是这个模块的能力
P521 写下了login的 PAM 验证机制流程!!!

其他相关文档:
limits.conf: P522
规范创建文档大小
规定某个群组同时登录账户最大个数



Linux 主机上的用户信息传递: P523
查询使用者
w:目前已登陆在系统上面的用户
who:目前已登陆在系统上面的用户
lastlog:每个账号的最近登陆的时间
last:所有登陆者信息
使用者对谈: P524
write:给在线的某个用户发送信息。
例如:[root@www ~]# write Ben pts/0 pts/0是什么意思呢?指的是打开的一个终端。再打开一个的的话就是pts1了。可以透过who来查询。 如果正在忙于某事,不希望接受信息则可以 输入 mesg n。否则 打开的话 mesg y。用来查询此时的状态直接则输入mesg 但是root的信息不能阻挡
wall:对所有系统上面的用户传送简讯 (广播)
mail:(可在离线的时候发送)


手动新增使用者:
以前我们都是使用useradd来新增账户的,现在我要自己动手新建一个账户。
首先我们必须知道一些检查工具 P527
pwck:检查我的创建是否正确
pwconv:将 /etc/passwd 内的账号与口令,移动到 /etc/shadow 当中
pwunconv:将 /etc/shadow 内的口令栏数据写回 /etc/passwd 当中, 并且删除 /etc/shadow 文件
chpasswd:读入未加密前的口令,并且经过加密后, 将加密后的口令写入 /etc/shadow 当中
特殊账号,如纯数字账号的手工创建(不建议使用纯数字的账号了!因为很多时候,系统会搞不清楚那组数字是『账号』还是『 UID 』,因为某些时候指令同时允许输入UID或是帐号名,这样以来会搞混的)
整个动作是这样: P529
① 先创建所需要的群组 ( vi /etc/group );
② 将 /etc/group 与 /etc/gshadow 同步化 ( grpconv );
③ 创建账号的各个属性 ( vi /etc/passwd );
④ 将 /etc/passwd 与 /etc/shadow 同步化 ( pwconv );
⑤ 创建该账号的口令 ( passwd accountname );
⑥ 创建用户家目录 ( cp -a /etc/skel /home/accountname );
⑦ 更改用户家目录的属性 ( chown -R accountname.group /home/accountname )。
大量建置账号范本(适用 passwd --stdin 选项) P530
这里的口令是默认的
大量建置账号的范例(适用于连续数字,如学号) P531
尚未看懂












第十五章、磁碟配额(Quota)与进阶文件系统管理
Quota 的一般用途: P538
针对 WWW server ,例如:每个人的网页空间的容量限制!
针对 mail server,例如:每个人的邮件空间限制。
针对 file server,例如:每个人最大的可用网络磁盘空间 (教学环境中最常见!)
限制某一群组所能使用的最大磁碟配额 (使用群组限制)
限制某一使用者的最大磁碟配额 (使用使用者限制)
以 Link 的方式,来使邮件可以作为限制的配额 (更改 /var/spool/mail 这个路径)


Quota 的使用限制:
仅能针对整个 filesystem
核心必须支持 quota
Quota 的记录档
只对一般身份使用者有效,例如 root 就不能配置 quota【UID 只有 0 与非为 0 两种,非为 0 则为一般账号。一般账号又分为系统账号 (1~499) 即可登陆者账号 (大于 500)】


Quota 的规范配置项目:
容量限制或文件数量限制 (block 或 inode)
限制 inode 用量:可以管理使用者可以创建的『文件数量』;
限制 block 用量:管理使用者磁碟容量的限制,较常见为这种方式。
不管是 inode/block ,限制值都有两个,分别是 soft 与 hard。通常 hard 限制值要比 soft 要高。举例来说,若限制项目为 block ,可以限制 hard 为 500MBytes 而 soft 为 400MBytes。若用户使用量高于400但低于500 ,系统会发出提示信息,警告,并且有会倒数计时的宽限时间。如果没有在宽限时间内删除文件等将容量降低于400,系统会封锁,不能在新增文件;若超过500,系统立刻封锁。
不能针对『某个目录』来进行 Quota 的设计,但你可以针对『某个文件系统 (filesystem) 』来配置


Quota示例: P540
对已有的【账户】和【群组】进行【block(容量)】或【inode(文件数量)】的限制。
整个步骤中需要注意的几点是:
① 检查文件系统是否支持。因为一个系统可以分为好几个文件系统,且quota是针对一个完整的文件系统的,所以需要看该文件系统是否支持此功能。
第一步:检查你要处理的目录是否为独立的文件系统   如 df -h /home
第二部:查看文件系统信息是否支持quota  如 mount | grep home  看mount信息中的/home是否支持  不支持看      P540 提供了两种方式,一是当前系统支持quota下次启动则不再支持 另一种写入文档  每次启动都支持
② 创建 quota 记录档 P542
第一步:为什么要建这个记录当啊?
Quota 是透过分析整个文件系统中,每个使用者(群组)拥有的文件总数与总容量, 再将这些数据记录在该文件系统的最顶层目录,然后在该记录档中再使用每个帐号(或群组)的限制值去规范磁碟使用量。因此,建立这个档案对quota是必不可少的
第二部:quotacheck:扫瞄文件系统并创建 Quota 的记录档
③ Quota 启动、 关闭与限制值配置 P543
quotaon :启动 quota 的服务
quotaoff :关闭 quota 的服务
edquota :编辑帐号/群组的限值与宽限时间。里面共分为七个栏位, 七个栏位分别的意义为:
第一栏:文件系统 (filesystem):说明该限制值是针对哪个文件系统 (或 partition);
第二栏:磁碟容量 (blocks):这个数值是 quota 自己算出来的,单位为 Kbytes,请不要更动他;
第三栏:soft:磁碟容量 (block) 的 soft 限制值,单位亦为 KB
第一四栏:hard:block 的 hard 限制值,单位 KB;
第五栏:文件数量 (inodes):这是 quota 自己算出来的,单位为个数,请不要更动他;
第六栏:soft:inode 的 soft 限制值;
第七栏:hard:inode 的 hard 限制值;
我们通过修改其中一些参数来实现quota的限制
④ Quota 限制值的报表 P545
quota :单一用户的 quota 报表
repquota :针对文件系统的限额做报表
⑤ 测试与管理 P547
warnquota :对超过限额者发出警告信
setquota :直接於命令中配置 quota 限额,不同於 edquota 是呼叫 vi 来进行配置,setquota 直接由命令输入所必须要的各项限制值
不更动既有系统的 quota 实例: P550
这里是指如果账户的一些使用(比如邮箱)也想要被限制使用的大小,我们说过quota适用于完整的文件系统,由於 /home 及 /var/spool/mail 根本不可能是同一个 filesystem (除非是都不分割,使用根目录,才有可能整合在一起), 所以,该如何进行这样的 quota 限制呢?
假设你又已经有 /home 这个独立的分割槽了, 那么你只要:
将 /var/spool/mail 这个目录完整的移动到 /home 底下;
利用 ln -s /home/mail /var/spool/mail 来创建连结数据;
将 /home 进行 quota 限额配置




软件磁盘阵列 (Software RAID): P551
什么是 RAID: RAID 可以透过一个技术(软件或硬件),将多个较小的磁碟整合成为一个较大的磁碟装置; 而这个较大的磁碟功能可不止是储存而已,他还具有数据保护的功能。
RAID可以分为几个等级:
RAID-0 (等量模式, stripe):效能最佳
优点:当你有 100MB 的数据要写入时,每个磁碟会各被分配到 50MB 的储存量。这种模式的 RAID 会将磁碟先切出等量的区块 (举例来说, 4KB), 然后 当一个文件要写入 RAID 时,该文件会依据区块的大小切割好,之后再依序放到各个磁碟里面去。越多颗磁碟组成的 RAID-0 效能会越好,因为 每颗负责的数据量就更低。
缺点:RAID-0 只要有任何一颗磁碟损毁,在 RAID 上面的所有数据都会遗失而无法读取
RAID-1 (映射模式, mirror):完整备份
优点:让同一份数据,完整的保存在两颗磁碟上头。如果我有一个 100MB 的文件,且我仅有两颗磁碟组成 RAID-1 时, 那么这两颗磁碟将会同步写入 100MB 到他们的储存空间去。 因此,整体 RAID 的容量几乎少了 50%,最大的优点大概就在於数据的备份吧
缺点:写入效能不佳,且容量有一半用在备份
RAID 0+1,RAID 1+0:所谓的 RAID 0+1 就是: (1)先让两颗磁碟组成 RAID 0,并且这样的配置共有两组; (2)将这两组 RAID 0 再组成一组 RAID 1。这就是 RAID 0+1 罗!反过来说,RAID 1+0 就是先组成 RAID-1 再组成 RAID-0 的意思。
由於具有 RAID 0 的优点,所以效能得以提升,由於具有 RAID 1 的优点,所以数据得以备份。 但是也由於 RAID 1 的缺点,所以总容量会少一半用来做为 备份喔!
RAID 5:效能与数据备份的均衡考量
至少需要三颗以上的磁碟才能够组成这种类型的磁盘阵列。这种磁盘阵列的数据写入有点类似 RAID-0 , 不过每个循环的写入过程中,在每颗磁碟还加入一 个同位检查数据 (Parity) ,这个数据会记录其他磁碟的备份数据, 用於当有磁碟损毁时的救援,因此支持(仅支持)一颗磁碟的损毁
Spare Disk:预备磁碟的功能:
是一颗或多颗没有包含在原本磁盘阵列等级中的磁碟,这颗磁碟平时并不会被磁盘阵列所使用, 当磁盘阵列有任何磁碟损毁时,则这颗 spare disk 会被主 动的拉进磁盘阵列中,并将坏掉的那颗硬盘移出磁盘阵列
磁盘阵列的优点:
数据安全与可靠性:指的并非资讯安全,而是当硬件 (指磁碟) 损毁时,数据是否还能够安全的救援或使用之意;
读写效能:例如 RAID 0 可以加强读写效能,让你的系统 I/O 部分得以改善;
容量:可以让多颗磁碟组合起来,故单一文件系统可以有相当大的容量。 P553
software RAID与 hardware RAID
硬件磁盘阵列 (hardware RAID) :透过磁盘阵列卡来达成阵列的目的。 磁盘阵列卡上面有一块专门的芯片在处理 RAID 的任务,因此在效能方面会比较好。在很多任务 (例如 RAID 5 的同位检查码计算) 磁盘阵列并不会重复消耗原本系统的 I/O 汇流排,理论上效能会较佳。此外目前一般的中高阶磁盘阵列卡都支持热拔插, 亦即在不关机的情况下抽换损坏的磁碟,对於系统的复原与数据的可靠性方面非常的好用。但是,很贵。
软件磁盘阵列 (software RAID):透过软件来模拟阵列的任务, 以partition 或 disk 为磁碟的单位。软件磁盘阵列则是系统模拟的,因此使用的装置档名是系统的装置档, 档名为 /dev/md0, /dev/md1...
【【【如何配置software RAID呢?】】】
mdadm:配置software raid的主要指令。
选项与参数:
--create :为创建 RAID 的选项;
--auto=yes :决定创建后面接的软件磁盘阵列装置,亦即 /dev/md0, /dev/md1...
--raid-devices=N :使用几个磁碟 (partition) 作为磁盘阵列的装置
--spare-devices=N :使用几个磁碟作为备用 (spare) 装置
--level=[015] :配置这组磁盘阵列的等级。支持很多,不过建议只要用 0, 1, 5 即可
--detail :后面所接的那个磁盘阵列装置的详细资讯
想要建置的目标环境:
利用 4 个 partition 组成 RAID 5;
每个 partition 约为 1GB 大小,需确定每个 partition 一样大较佳;
利用 1 个 partition 配置为 spare disk
这个 spare disk 的大小与其他 RAID 所需 partition 一样大!
将此 RAID 5 装置挂载到 /mnt/raid 目录下
步骤:
① 建立5个1G的分隔槽(使用fdisk /dev/sda 之前有讲过) P556
② 透过 mdadm 来创建磁盘阵列  主要通过:[root@www ~]# mdadm --create --auto=yes /dev/md0 --level=5 --raid-devices=4 --spare-devices=1 /dev/hda{6,7,8,9,10} level=5即为RAID 5 ;接下来分配4个组成名字为md0的RAID(名字也有讲究)外加一个用作spare 
③ 通过查看mdadm --detail /dev/md0或者cat /proc/mdstat  查询现在的使用情况
接下来模拟 RAID 错误的救援模式 P559
① 配置磁碟为错误 (fault)
② 将出错的磁碟移除并加入新磁碟
最后启动自动启动 RAID 并自动挂载 P560
① 配置 mdadm.conf
[root@www ~]# vi /etc/mdadm.conf  加入下面的一段字符串:
ARRAY /dev/md0 UUID=7c60c049:57d60814:bd9a77f1:57e49c5b
② 配置 root@www ~]# vi /etc/fstab 加入下面字符串
/dev/md0    /mnt/raid    ext3    defaults     1 2
关闭软件RAID(如果确定不再需要使用了) 【这里不要看书上的,那里是不正确的!】
1、umount卸载RAID设备
[root@yufei ~]# umount /dev/md5
2、停止RAID设备
[root@yufei ~]# mdadm -S /dev/md5
mdadm: stopped /dev/md5
这里顺便给大家讲一下设备停止后如何开启,算是插曲啊。
 
[root@yufei ~]# mdadm -A -s /dev/md5
mdadm: /dev/md5 has been started with 3 drives and 1 spare.
在停止前,你要用再查看一下RAID里面的硬盘信息,因为后面会用到这个,很关键哦!
 
[root@yufei ~]# mdadm -D /dev/md5
   Number   Major   Minor   RaidDevice State
      3       8       64        0      active sync   /dev/sde
       1       8       32        1      active sync   /dev/sdc
      4       8       48        2      active sync   /dev/sdd
 
      5       8       80        -      spare   /dev/sdf
OK,现在再停止一次
 
[root@yufei ~]# mdadm -S /dev/md5
mdadm: stopped /dev/md5
3、移除RAID里面的磁盘(这是关键的一步,而很多教程上都没有写)
 
删除RAID里面的所有磁盘
 
这一步,一定要把RAID停止后才能执行,否则会出现下面的错误提示
 
mdadm: Couldn’t open /dev/sde for write – not zeroing
 
[root@yufei ~]# mdadm --misc --zero-superblock /dev/sde
[root@yufei ~]# mdadm --misc --zero-superblock /dev/sdc
[root@yufei ~]# mdadm --misc --zero-superblock /dev/sdd
[root@yufei ~]# mdadm --misc --zero-superblock /dev/sdf
OK,这时候就把RAID里面的所有磁盘删除掉了。
 
4、删除相关配置文件里面的RAID信息
[root@yufei ~]# vim /etc/mdadm.conf
把我们增加的这一行删除
 
ARRAY /dev/md5 metadata=1.2 spares=1 name=yufei:5 UUID=69443d97:7e32415d:7f3843c5:4d5015cf
[root@yufei ~]# vim /etc/fstab
把我们增加的这一行删除
/dev/md5                /mnt                    ext4    defaults        0 0
经过这四步就完全删除RIAD了。重新启动,也不会有raid的相关内容了。








逻辑卷轴管理员: P562
想像一个情况,你在当初规划主机的时候将 /home 只给他 50G ,等到使用者众多之后导致这个 filesystem 不够大, 此时你能怎么作?
可以弹性的调整 filesystem 的容量!!!
LVM 可以整合多个实体 partition 在一起, 让这些 partitions 看起来就像是一个磁碟一样!而且,还可以在未来新增或移除其他的实体 partition 到这个 LVM 管理的磁碟当中
要了解LVM必须先知道以下几个关键字的意义:
PV:实体卷轴
我们实际的 partition 需要调整系统识别码 (system ID) 成为 8e (LVM 的识别码),然后再经过 pvcreate 的命令将他转成 LVM 最底层的实体卷轴 (PV) ,之后才能够将这些 PV 加以利用(如何调?fdisk啊 然后看帮助)
VG:卷轴群组
所谓的 LVM 大磁碟就是将许多 PV 整合成这个 VG 的东西,最大容量与PE的大小和数量有关
PE:实体延伸区块
PE 是整个 LVM 的最小储存单位,其实我们的文件数据都是藉由写入 PE 来处理的。简单的说,这个 PE 就有点像文件系统里面的 block 大小。调整PE大小会影响到VG的大小,因为VG中包含的PE数量是有限的。
LV:逻辑卷轴
最终的 VG 还会被切成 LV,这个 LV 就是最后可以被格式化使用的类似分割槽的咚咚了
因此,总的来说,建立LVM的过程就是:先建立PV,然后组成VG,最后分隔出可以使用的LV,最最后将利用 LV 这个玩意儿来进行系统的挂载。
那么我的数据写入这个 LV 时,到底他是怎么写入硬盘当中的?
第一种方式:线性模式 (linear):假如我将 /dev/hda1, /dev/hdb1 这两个 partition 加入到 VG 当中,并且整个 VG 只有一个 LV 时,那么所谓的线性模式就是:当 /dev/hda1 的容量用完之后,/dev/hdb1 的硬盘才会被使用到, 这也是我们所建议的模式。
第二种方式:交错模式 (triped):那什么是交错模式?很简单啊,就是我将一笔数据拆成两部分,分别写入 /dev/hda1 与 /dev/hdb1 的意思,感觉上有点像 RAID 0 啦!如此一来,一份数据用两颗硬盘来写入,理论上,读写的效能会比较好。
OK,接下来LVM 实作流程,我们的目标是:
先分割出 4 个 partition ,每个 partition 的容量均为 1.5GB 左右,且 system ID 需要为 8e;
全部的 partition 整合成为一个 VG,VG 名称配置为 Benvg;且 PE 的大小为 16MB;
全部的 VG 容量都丢给 LV ,LV 的名称配置为 Benlv;
最终这个 LV 格式化为 ext4 的文件系统,且挂载在 /mnt/lvm 中
步骤:
① 建立4个1G的分隔槽,并且将 system ID 改为 8e(使用fdisk /dev/sda 之前有讲过)
② PV 阶段
pvcreate :将实体 partition 创建成为 PV ;
pvscan :搜寻目前系统里面任何具有 PV 的磁碟;
pvdisplay :显示出目前系统上面的 PV 状态;
pvremove :将 PV 属性移除,让该 partition 不具有 PV 属性。
[root@www ~]# pvcreate /dev/hda{6,7,8,9}
③ VG 阶段
vgcreate :就是主要创建 VG 的命令啦!他的参数比较多,等一下介绍。
vgscan :搜寻系统上面是否有 VG 存在?
vgdisplay :显示目前系统上面的 VG 状态;
vgextend :在 VG 内添加额外的 PV ;
vgreduce :在 VG 内移除 PV;
vgchange :配置 VG 是否启动 (active);
vgremove :删除一个 VG 啊!
VG 的名称是自订的
[root@www ~]# vgcreate -s 16M Benvg /dev/hda{6,7,8}
这样就创建一个 VG 了!假设我们要添加这个 VG 的容量,因为我们还有 /dev/hda9 嘛!此时你可以这样做:
[root@www ~]# vgextend Benvg /dev/hda9
④ LV 阶段
lvcreate :创建 LV 啦!
lvscan :查询系统上面的 LV ;
lvdisplay :显示系统上面的 LV 状态啊!
lvextend :在 LV 里面添加容量!
lvreduce :在 LV 里面减少容量;
lvremove :删除一个 LV !
lvresize :对 LV 进行容量大小的调整!
如:[root@www ~]# lvcreate -l 356 -n Benlv Benvg
VG 的名称为 Benvg , 但是 LV 的名称必须使用全名!亦即是 /dev/Benvg/Benlv 才对
⑤ 文件系统阶段
[root@www ~]# mkfs -t ext3 /dev/Benvg/Benlv <==注意 LV 全名!
[root@www ~]# mkdir /mnt/lvm
[root@www ~]# mount /dev/Benvg/Benlv /mnt/lvm
可以调用df 查看
接下来我们谈谈如何放大 LV 容量: P569
① 用 fdisk 配置新的具有 8e system ID 的 partition
② 利用 pvcreate 建置 PV
③ 利用 vgextend 将 PV 加入我们的 Benvg
④ 利用 lvresize 将新加入的 PV 内的 PE 加入 Benlv 中
⑤ 透过 resize2fs 将文件系统的容量确实添加!
为什么我使用lvresize之后还要使用resize2fs呢?
整个文件系统在最初格式化的时候就创建了 inode/block/superblock 等资讯,要改变这些资讯是很难的! 不过因为文件系统格式化的时候建置的是多个 block group ,因此我们可以透过在文件系统当中添加 block group 的方式来增减文件系统的量!而增减 block group 就是利用 resize2fs 啦!所以最后一步是针对文件系统来处理的, 前面几步则是针对 LVM 的实际容量大小!
接着缩小 LV 容量: P572
①  先找出 /dev/hda6 的容量大小,并尝试计算文件系统需缩小到多少
②  就直接降低文件系统的容量  利用[root@www ~]# resize2fs /dev/Benvg/Benlv 6900M
这里使用resize2fs和lvresize的顺序和放大LV容量的顺序是不一样的
③ 降低 LV 的容量  
④  先确认 /dev/hda6 是否将 PE 都移除了(利用pvdisplay 查看/dev/sda6中free的PE是否为sda6拥有PE的总数,free的意思的是否空闲,若free为0说明sda6还不能移除) 发现sda6的free不为总数,那么[root@www ~]# pvmove /dev/hda6 /dev/hda10 移出去到别的sda中
⑤  将 /dev/hda6 移出 Benvg 中
[root@www ~]# vgreduce Benvg /dev/hda6


LVM还有一个重要的功能是快照(备份、测试) P575
快照区与被快照的 LV 必须要在同一个 VG 上头
快照就是将当时的系统资讯记录下来,就好像照相记录一般! 未来若有任何数据更动了,则原始数据会被搬移到快照区,没有被更动的区域则由快照区与文件系统共享
最初建置系统快照区的状况:快照区与系统区共享所有的 PE 数据, 因此你会看到快照区的内容与文件系统是一模一样的,等到系统运行一阵子后,假设 A 区域的数据被更动了 (上面右图所示),则更动前系统会将该区域的数据移动到快照区。
快照区的创建:
① 先观察 VG 还剩下多少剩余容量(将非LV的部分用于创建快照区)
② 利用 lvcreate 创建系统快照区
③ 然后创建文件夹然后挂载利用df会发现与LV完全一样
那我们如何利用快照区进行复原呢?
首先要注意,快照区向来是比较小的,因此你要复原的数据量不能够高於快照区所能负载的实际容量
经过一段时间的使用后,快照区已经产生了一些变化
①  利用快照区将快照区中原本的 filesystem 备份
②  然后将LV格式化
③  然后将压缩包解压在LV中
************************************************************************P578*****************************************************************************************************************
快照区单单是用来备份就太可惜了,还有一个重要用法:::::【利用快照区进行各项练习与测试的任务,再以原系统还原快照】
快照是如何来的呢?是通过LV复制得来的。在一些教育活动中,学生可以在快照区进行“乱搞”,然后将快照区删除,之后在通过复制LV得到一个新的快照区。
********************************************************************************************************************************************************************************************


如何关闭快照区呢? P580
先卸载系统上面的 LVM 文件系统 (包括快照与所有 LV);
使用 lvremove 移除 LV ;
使用 vgchange -a n VGname 让 VGname 这个 VG 不具有 Active 的标志;
使用 vgremove 移除 VG:
使用 pvremove 移除 PV;
最后,使用 fdisk 修改 ID 回来啊!














第十六章、例行性工作排程 (crontab)
Linux 工作排程的种类:
at: at 是个可以处理仅运行一次就结束排程的命令,不过要运行 at 时, 必须要有 atd 这个服务 (第十八章) 的支持才行。在某些新版的 distributions 中,atd 可能默认并没有启动,那么 at 这个命令就会失效呢
crontab: crontab 这个命令所配置的工作将会循环的一直进行下去! 可循环的时间为分钟、小时、每周、每月或每年等。crontab 除了可以使用命令运行外,亦可编辑 /etc/crontab 来支持。至於让 crontab 可以生效的服务则是 crond 这个服务。
Linux 上常见的例行性工作及其简要分析: P586
⑴ 进行登录档的轮替 (log rotate):Linux 会主动的将系统所发生的各种资讯都记录下来
⑵ 登录档分析 logwatch 的任务:如果系统发生了软件问题、硬件错误、资安问题等,绝大部分的错误资讯都会被记录到登录档中, 因此系统管理员的重要任务之一就是分析登录档
⑶ 创建 locate 的数据库:系统会主动的进行 updatedb 
⑷ whatis 数据库的创建:whatis 数据库,而这个数据库也是透过系统的例行性工作排程来自动运行的
⑸ RPM 软件登录档的创建:RPM 是一种软件管理的机制。由於系统可能会常常变更软件, 包括软件的新安装、非经常性升级等,都会造成软件档名的差异
⑹ 移除缓存档:有些缓存档则有时间性,如果超过一段时间后,这个缓存档就没有效用了,此时移除这些缓存档就是一件重要的工作
⑺ 与网络服务有关的分析行为:如果你有安装类似 WWW 服务器软件 (一个名为 apache 的软件),那么你的 Linux 系统通常就会主动的分析该软件的登录档。 同时某些凭证与认证的网络资讯是否过期的问题,我们的 Linux 系统也会很亲和的帮你进行自动检查
下面详细介绍at和crontab:
【仅运行一次的工作排程(单一工作排程)】: P587
atd 的启动与 at 运行的方式
要使用单一工作排程时,我们的 Linux 系统上面必须要有负责这个排程的服务,那就是 atd 这个玩意儿!
如何激活呢? ① [root@www ~]# /etc/init.d/atd restart     [root@www ~]# chkconfig atd on
at 的运行方式
我们使用 at 这个命令来产生所要运行的工作,并将这个工作以文字档的方式写入 /var/spool/at/ 目录内,该工作便能等待 atd 这个服务的取用与运行了
at的管理:
① 先找寻 /etc/at.allow 这个文件,写在这个文件中的使用者才能使用 at ,没有在这个文件中的使用者则不能使用 at (即使没有写在 at.deny 当中)
② 如果 /etc/at.allow 不存在,就寻找 /etc/at.deny 这个文件,若写在这个 at.deny 的使用者则不能使用 at ,而没有在这个 at.deny 文件中的使用者,就可以使用 at 
③ 如果两个文件都不存在,那么只有 root 可以使用 at 这个命令。
at指令(单一工作排程)的实施方法: P588
比如: ① 
再过五分钟后,将 /root/.bashrc 寄给 root 自己
[root@www ~]# at now + 5 minutes  <==记得单位要加 s 喔!
② 再比如:
查看第n项单一工作排程任务
[root@www ~]# at -c 4
③ 再再比如:
由於机房预计於 2009/03/18 停电,我想要在 2009/03/17 23:00 关机?
[root@www ~]# at 23:00 2009-03-17
at> /bin/sync
at> /bin/sync
at> /sbin/shutdown -h now
at>
【建议你最好使用绝对路径来下达你的命令,比较不会有问题】


、at 有另外一个很棒的优点,那就是『背景运行』的功能: P589
离线继续工作的任务
由於 at 工作排程的使用上,系统会将该项 at 工作独立出你的 bash 环境中, 直接交给系统的 atd 程序来接管,因此,当你下达了 at 的工作之后就可以立刻离线了, 剩下的工作就完全交给 Linux 管理即可


at 工作的管理: P590
atq:查询现有的单一工作排程
atrm:移除某项排程
batch:系统有空时才进行背景任务( batch 也是使用 atq/atrm 来管理的) P590


【循环运行的例行性工作排程:】 P591
如何重新启动 crond 这个服务呢 ? 『/etc/init.d/crond restart』
循环运行的例行性工作排程则是由 cron (crond) 这个系统服务来控制的
和at相同的是:
/etc/cron.allow:
将可以使用 crontab 的帐号写入其中,若不在这个文件内的使用者则不可使用 crontab;
/etc/cron.deny:
将不可以使用 crontab 的帐号写入其中,若未记录到这个文件当中的使用者,就可以使用 crontab 
当使用者使用 crontab 这个命令来创建工作排程之后,该项工作就会被纪录到 /var/spool/cron/ 里面去了,而且是以帐号来作为判别的
如何使用crontab呢?
直接下达『 crontab -e 』去编辑自己的例行性命令,每项工作 (每行) 的格式都是具有六个栏位,具体见P592
分钟    +      小时      +     日期      +     月份      +     周      +     命令
周的数字为 0 或 7 时,都代表『星期天』
一些辅助的字符:
*(星号):代表任何时刻都接受的意思!举例来说,范例一内那个日、月、周都是 * , 就代表著『不论何月、何日的礼拜几的 12:00 都运行后续命令』的意思!
,(逗号):代表分隔时段的意思。举例来说,如果要下达的工作是 3:00 与 6:00 时,就会是:0 3,6 * * * command    时间参数还是有五栏,不过第二栏是 3,6 ,代表 3 与 6 都适用!
-(减号):代表一段时间范围内,举例来说, 8 点到 12 点之间的每小时的 20 分都进行一项工作:  20 8-12 * * * command    
仔细看到第二栏变成 8-12 喔!代表 8,9,10,11,12 都适用的意思!
/n(斜线):那个 n 代表数字,亦即是『每隔 n 单位间隔』的意思,例如每五分钟进行一次,则  */5 * * * * command   很简单吧!用 * 与 /5 来搭配,也可以写成 0-59/5 ,相同意思!
配套的一些练习: P592
『如果只是要删除某个 crontab 的工作项目,那么请使用 crontab -e 来重新编辑即可!』如果使用 -r 的参数,是会将所有的 crontab 数据内容都删掉的!
系统的配置档: /etc/crontab: P593
这个『 crontab -e 』是针对使用者的 cron 来设计的,如果是『系统的例行性任务』时, 该怎么办呢?是否还是需要以 crontab -e 来管理你的例行性工作排程呢?当然不需要,你只要编辑 /etc/crontab 这个文件就可以啦
ron 这个服务的最低侦测限制是『分钟』,所以『 cron 会每分钟去读取一次 /etc/crontab 与 /var/spool/cron 里面的数据内容 』
/etc/crontab 配置分为七栏,『分、时、日、月、周、运行者、命令』为其配置依据;


在使用排程的时候,我们需要注意些什么呢?
问题① 资源分配不均的问题: P595
举例来说,如果我们有四个工作都是五分钟要进行一次的,那么是否这四个动作全部都在同一个时间点进行? 如果同时进行,该四个动作又很耗系统资源,如此一来,每五分钟不是会让系统忙得要死?
问题② 取消不要的输出项目:
当有运行成果或者是运行的项目中有输出的数据时,该数据将会 mail 给 MAILTO 配置的帐号 』,好啦,那么当有一个排程一直出错(例如 DNS 的侦测系统当中,若 DNS 上一级主机挂掉,那么你就会一直收到错误信息!)怎么办
问题③ 安全的检验
很多时候被植入木马都是以例行命令的方式植入的,所以可以藉由检查 /var/log/cron 的内容来视察是否有『非您配置的 cron 被运行了?』这个时候就需要小心一点罗!
问题④ 周与日月不可同时并存
本来你以为九月十一号且为星期五才会进行这项工作,无奈的是,系统可能会判定每个星期五作一次,或每年的 9 月 11 号分别进行,如此一来与你当初的规划就不一样了






【可唤醒停机期间的工作任务】 P596(这一部分没有搞懂,且实际运行情况与书中不同)
什么是 anacron?   anacron指的是比如系统规定在20:00进行某项进程,但是那时候正好是关机状态,当你再次开机时候, anacron就会出现将未在之前规定时间执行的进程拿出来执行一遍,所以 anacron 其实也是透过 crontab 来运行的!因此 anacron 运行的时间通常有两个,一个是系统启动期间运行,一个是写入 crontab 的排程中
anacron 与 /etc/anacrontab
anacron 若下达『 anacron -s cron.daily 』时,他会这样运行的:
① 由 /etc/anacrontab 分析到 cron.daily 这项工作名称的天数为 1 天;
② 由 /var/spool/anacron/cron.daily 取出最近一次运行 anacron 的时间戳记;
③ 由上个步骤与目前的时间比较,若差异天数为 1 天以上 (含 1 天),就准备进行命令;
④ 若准备进行命令,根据 /etc/anacrontab 的配置,将延迟 65 分钟
⑤ 延迟时间过后,开始运行后续命令,亦即『 run-parts /etc/cron.daily 』这串命令;
⑥ 运行完毕后, anacron 程序结束。
现在你知道为什么隔了一阵子才将 CentOS 启动,启动过后约 1 小时左右系统会有一小段时间的忙碌!而且硬盘会跑个不停!那就是因为 anacron 正在运行过去 crontab 未进行的各项工作排程啦















第十七章、程序管理与 SELinux 初探
什么是程序 (process): P600
    『触发任何一个事件时,系统都会将他定义成为一个程序,并且给予这个程序一个 ID ,称为 PID,同时依据启发这个程序的使用者与相关属性关系,给予这个 PID 一组有效的权限配置。』
    程序与程序 (process & program): P601
        我们如何产生一个程序呢? 就是『运行一个程序或命令』就可以触发一个事件而取得一个 PID
        『不同的使用者身份运行这个 program 时,系统给予的权限也都不相同!』
        举例来说,我们可以利用 touch 来创建一个空的文件,当 root 运行这个 touch 命令时,他取得的是 UID/GID = 0/0 的权限,而当 dmtsai (UID/GID=501/501) 运行这个 touch 时,他的权    限            就跟 root 不同啦
        不同的身份登录主机的时候获得的bash的PID也是不同的,这个 PID 就是依据登陆者的 UID/GID (/etc/passwd) 来的
        衍生出来的其他程序在一般状态下,也会沿用这个程序的相关权限
        所以,总的来说:
            程序 (program):通常为 binary program ,放置在储存媒体中 (如硬盘、光盘、软盘、磁带等), 为实体文件的型态存在;
                程序 (process):程序被触发后,运行者的权限与属性、程序的程序码与所需数据等都会被加载内存中, 操作系统并给予这个内存内的单元一个识别码 (PID),可以说,程序就是一个正在运行中的程序。
        子程序与父程序:
            连续运行两个 bash 后,第二个 bash 的父程序就是前一个 bash。因为每个程序都有一个 PID
            ps -l :观察程序相关的输出资讯    【 PPID :(Parent PID)】
        fork and exec:程序呼叫的流程:
            在 Linux 的程序呼叫通常称为 fork-and-exec 的流程 (注1)!程序都会藉由父程序以复制 (fork) 的方式产生一个一模一样的子程序, 然后被复制出来的子程序再以 exec 的方式来运行实际要进行的程序,最终就成为一个子程序的存在
        系统或网络服务:常驻在内存的程序
            crond 这个程序所管理的,我们将他启动在背景当中一直持续不断的运行, 套句以前 DOS 年代常常说的一句话,那就是『常驻在内存当中的程序』
            常驻在内存当中的程序通常都是负责一些系统所提供的功能以服务使用者各项任务,因此这些常驻程序就会被我们称为:服务 (daemon)
    Linux 的多人多工环境: p603
        多人环境:
            每个人进入 Linux 的环境配置都可以随著每个人的喜好来配置 (还记得我们在第十一章 BASH 提过的 ~/.bashrc 吧?)
        多工行为;
        多重登陆环境的七个基本终端窗口:
            在 Linux 当中,默认提供了六个文字界面登陆窗口,以及一个图形界面,你可以使用 [Alt]+[F1].....[F7] 来切换不同的终端机界面
        特殊的程序管理行为:
            Linux 几乎可以说绝对不会死机的!因为他可以在任何时候, 将某个被困住的程序杀掉,然后再重新运行该程序而不用重新启动!够炫吧!那么如果我在 Linux 下以文字界面登陆,在萤幕当中显示错误信息后就挂了~动都不能动,该如何是好!? 这个时候那默认的七个窗口就帮上忙啦!你可以随意的再按 [Alt]+[F1].....[F7] 来切换到其他的终端机界面,然后以 ps -aux 找出刚刚的错误程序,然后给他 kill 一下,哈哈,回到刚刚的终端机界面!恩~棒!又回复正常罗
        bash 环境下的工作管理 (job control):
            在这个单一的 bash 介面下,我可不可以进行多个工作啊? 当然可以啦!可以『同时』进行;比如  
                [root@www ~]# cp file1 file2 &
                在这一串命令中,重点在那个 & 的功能,他表示将 file1 这个文件复制为 file2 ,且放置於背景中运行, 也就是说运行这一个命令之后,在这一个终端介面仍然可以做其他的工作!而当这一个命令 (cp file1 file2) 运行完毕之后,系统将会在你的终端介面显示完成的消息
        多人多工的系统资源分配问题考虑:
            CPU 的运算与 RAM 的大小可能就会不敷使用!


工作管理 (job control): P605
    『当我们登陆系统取得 bash shell 之后,在【单一终端机介面】下同时进行多个工作的行为管理 』
    什么是工作管理:
        『进行工作管理的行为中, 其实每个工作都是目前 bash 的子程序,亦即彼此之间是有相关性的。 我们无法以 job control 的方式由 tty1 的环境去管理 tty2 的 bash !』
        既然我可以在六个终端介面登陆,那何必使用 job control 呢???
            不要忘记了呢,我们可以在 /etc/security/limits.conf (第十四章) 里面配置使用者同时可以登陆的连线数,在这样的情况下,某些使用者可能仅能以一个连线来工作呢!
            可以出现提示字节让你操作的环境就称为【前景 (foreground)】,
            至於其他工作就可以让你放入【背景 (background)】 
                【暂停】或【运行】
        进行 bash 的 job control 必须要注意到的限制是:
                   这些工作所触发的程序必须来自於你 shell 的子程序(只管理自己的 bash);
                    前景:你可以控制与下达命令的这个环境称为前景的工作 (foreground);
                    背景:可以自行运行的工作,你无法使用 [ctrl]+c 终止他,可使用 bg/fg 呼叫该工作;
                    背景中『运行』的程序不能等待 terminal/shell 的输入(input)
    ok,下面进入job control 的管理:
        直接将命令丢到背景中『运行』的 &
            在只有一个 bash 的环境下,如果想要同时进行多个工作, 那么可以将某些工作直接丢到背景环境当中,让我们可以继续操作前景的工作!
            & 代表:『将工作丢到背景中去运行』喔! 注意到那个『运行』的字眼!此外,这样的情况最大的好处是: 不怕被 [ctrl]+c 中断的啦! 
            但是,我们需要注意的是背景中的一些输出
                在背景当中运行的命令,如果有 stdout 及 stderr 时,他的数据依旧是输出到萤幕上面的
                    所以:最佳的状况就是利用数据流重导向, 将输出数据传送至某个文件中
        将『目前』的工作丢到背景中『暂停』:[ctrl]-z
            在默认的情况下,使用 [ctrl]-z 丢到背景当中的工作都是『暂停』的状态喔!
        观察目前的背景工作状态: 
            jobs:    -l  :除了列出 job number 与命令串之外,同时列出 PID 的号码;
                -r  :仅列出正在背景 run 的工作;
                -s  :仅列出正在背景当中暂停 (stop) 的工作。
            + 代表最近被放到背景的工作号码, - 代表最近最后第二个被放置到背景中的工作号码。 而超过最后第三个以后的工作,就不会有 +/- 符号存在了!
        将背景工作拿到前景来处理:
            fg:    %jobnumber :jobnumber 为工作号码(数字)。注意,那个 % 是可有可无的!(如果没有%,默认为取出+号的job)
        让工作在背景下的状态变成运行中:
            bg:    %jobnumber :jobnumber 为工作号码(数字)
        管理背景当中的工作:
            kill:
                 -1 :重新读取一次参数的配置档 (类似 reload);
                 -2 :代表与由键盘输入 [ctrl]-c 同样的动作;
                 -9 :立刻强制删除一个工作;
                 -15:以正常的程序方式终止一项工作。与 -9 是不一样的。
    以上的背景需要注意的是:
        工作管理的背景依旧与终端机有关啦! 在这样的情况下,如果你是以远程连线方式连接到你的 Linux 主机,并且将工作以 & 的方式放到背景去, 请问,在工作尚未结束的情况下你离线了,该工作还会继续进行吗?答案是『否』!不会继续进行,而是会被中断掉。
    离线管理问题: P609
        nohup:可以让你在离线或注销系统后,还能够让工作继续进行
        需要注意的是, nohup 并不支持 bash 内建的命令,因此你的命令必须要是外部命令才行。




程序管理: P610
    程序的观察:
        ps :将某个时间点的程序运行情况撷取下来
            ps -l:仅观察自己的 bash 相关程序
            ps aux:观察系统所有程序
            ps -lA:以ps -l的形式,显示出所有的程序
            ps axjf:列出类似程序树的程序显示
            如果你发现在某个程序的 CMD 后面还接上 时,就代表该程序是僵尸程序
            事实上,通常僵尸程序都已经无法控管,而直接是交给 init 这支程序来负责了,偏偏 init 是系统第一支运行的程序, 他是所有程序的父程序!我们无法杀掉该程序的 (杀掉他,系统就死掉了!),所以罗,如果产生僵尸程序, 而系统过一阵子还没有办法透过核心非经常性的特殊处理来将该程序删除时,那你只好透过 reboot 的方式来将该程序抹去了
        top:动态观察程序的变化(对於 ps 是撷取一个时间点的程序状态, top 则可以持续侦测程序运行的状态) P613
            每一行显示的内容分别是:
                第一行(top...):目前的时间 + 启动到目前为止所经过的时间 + 已经登陆系统的使用者人数 + 系统在 1, 5, 15 分钟的平均工作负载
                第二行(Tasks...):显示的是目前程序的总量与个别程序在什么状态
                第三行(Cpus...):示的是 CPU 的整体负载
                第四行与第五行:表示目前的实体内存与虚拟内存 (Mem/Swap) 的使用情况
                第六行:这个是当在 top 程序当中输入命令时,显示状态的地方
                top 下半部分的画面,则是每个 process 使用的资源情况
            如果你想要观察的程序 CPU 与内存使用率都很低,我们找不到怎么办?
                我们可以仅观察单一程序,我们自己的 bash PID 可由 $$ 变量取得,请使用 top 持续观察该 PID
                例如:    
                    [root@www ~]# echo $$
                    13639  <==就是这个数字!他是我们 bash 的 PID
                    [root@www ~]# top -d 2 -p 13639
            如何修改一个程序的NICE呢(NICE越小系统越快执行)
                在top下执行输入r,然后输入想要修改的程序的PID 然后修改
            如何强制按照cpu使用率大小来显示呢?
                在top下输入 P (大写)
        pstree: P616
            列出目前系统上的程序树的相关性
            如果要找程序之间的相关性,这个 pstree 真是好用到不行
            仔细看第一个就是init,为什么呢?
                所有的程序都是依附在 init 这支程序底下的! 仔细看一下,这支程序的 PID 是一号喔!因为他是由 Linux 核心所主动呼叫的第一支程序!所以 PID 就是一号了


 程序的管理: P617
        程序是如何互相管理的呢?其实是透过给予该程序一个讯号 (signal) 去告知该程序你想要让她作什么!
        kill -signal 【某个工作(%jobnumber)】 或者是 【某个 PID (直接输入数字)】     (注意输入jobnumber时需要加上%,不然就是PID)
        killall:利用『下达命令的名称』来给予讯号
        总之,要删除某个程序,我们可以使用 PID 或者是启动该程序的命令名称;
         而如果要删除某个服务呢?最简单的方法就是利用 killall 
    关於程序的运行顺序: P619
        CPU 排程与例行性工作排程并不一样。 CPU 排程指的是每支程序被 CPU 运行的演算守则, 而例行性工作排程则是将某支程序安排在某个时间再交由系统运行。 CPU 排程与操作系统较具有相关性! 
        Priority 与 Nice 值:
            Linux 给予程序一个所谓的『优先运行序 (priority, PRI)』, 这个 PRI 值越低代表越优先的意思。不过这个 PRI 值是由核心动态调整的, 使用者无法直接调整 PRI 值的
            不过,PRI(new) = PRI(old) + nice
            那如果你想要调整程序的优先运行序时,就得要透过 Nice 值了:当 nice 值为负值时,那么该程序就会降低 PRI 值,亦即会变的较优先被处理
            但是要注意:
                nice 值可调整的范围为 -20 ~ 19 ;
                    root 可随意调整自己或他人程序的 Nice 值,且范围为 -20 ~ 19 ;
                   一般使用者仅可调整自己程序的 Nice 值,且范围仅为 0 ~ 19 (避免一般用户抢占系统资源);
                   一般使用者仅可将 nice 值越调越高,例如本来 nice 为 5 ,则未来仅能调整到大於 5;
            调整nice值的方式:
                一开始运行程序就立即给予一个特定的 nice 值:用 nice 命令;
                    调整某个已经存在的 PID 的 nice 值:用 renice 命令。
        【一】:nice :新运行的命令即给予新的 nice 值(通常什么时候要将 nice 值调大呢?举例来说,系统的背景工作中, 某些比较不重要的程序之进行:例如备份工作!由於备份工作相当的耗系统资源, 这个时候就可以将备份的命令之 nice 值调大一些,可以使系统的资源分配的更为公平)
        【二】:renice :已存在程序的 nice 重新调整
        【三】:之前在top中也提及过可以修改NICE值
    系统资源的观察: P621
        free :观察内存使用情况
            为什么我的内存快要被用光了呢?至少有 30MB 用在缓冲记忆 (buffers) 工作, 350MB 则用在缓存 (cached) 工作,也就是说,系统是『很有效率的将所有的内存用光光』, 目的是为了让系统的存取效能加速
        uname:查阅系统与核心相关资讯
        uptime:观察系统启动时间与工作负载
        netstat :追踪网络或插槽档                【跳过,没看】
        dmesg :分析核心产生的信息
        vmstat :侦测系统资源变化
            内存栏位 (procs) 的项目分别为:r :等待运行中的程序数量;b:不可被唤醒的程序数量
            内存栏位 (memory) 项目分别为:swpd:虚拟内存被使用的容量; free:未被使用的内存容量; buff:用於缓冲内存; cache:用於高速缓存
            内存置换空间 (swap) 的项目分别为:si:由磁碟中将程序取出的量; so:由於内存不足而将没用到的程序写入到磁碟的 swap 的容量
            磁碟读写 (io) 的项目分别为:bi:由磁碟写入的区块数量; bo:写入到磁碟去的区块数量
            系统 (system) 的项目分别为:in:每秒被中断的程序次数; cs:每秒钟进行的事件切换次数
            CPU 的项目分别为:us:非核心层的 CPU 使用状态; sy:核心层所使用的 CPU 状态; id:闲置的状态; wa:等待 I/O 所耗费的 CPU 状态; st:被虚拟机器 (virtual machine) 所盗用的 CPU 使用状态 
        数值越大表示越忙碌。




特殊文件与程序: P626
    为啥运行了 passwd 后你就具有 root 的权限呢?
        因为你在触发 passwd 后,会取得一个新的程序与 PID,该 PID 产生时透过 SUID 来给予该 PID 特殊的权限配置
    /proc/* 代表的意义:
        内存当中的数据又都是写入到 /proc/* 这个目录下的
    查询已开启文件或已运行程序开启之文件:
        fuser:藉由文件(或文件系统)找出正在使用该文件的程序(透过这个 fuser 我们可以找出使用该文件、目录的程序,藉以观察)
            选项与参数:
                -u  :除了程序的 PID 之外,同时列出该程序的拥有者;
                -m  :后面接的那个档名会主动的上提到该文件系统的最顶层,对 umount 不成功很有效!
                -v  :可以列出每个文件与程序还有命令的完整相关性!
                -k  :找出使用该文件/目录的 PID ,并试图以 SIGKILL 这个讯号给予该 PID;
                -i  :必须与 -k 配合,在删除 PID 之前会先询问使用者意愿!
                -signal:例如 -1 -15 等等,若不加的话,默认是 SIGKILL (-9) 罗!
             Access部分:
             c :此程序在当前的目录下(非次目录);
                 e :可被触发为运行状态;
                f :是一个被开启的文件;
               r :代表顶层目录 (root directory);
                F :该文件被开启了,不过在等待回应中;
                m :可能为分享的动态函式库;
            查阅某个文件系统底下有多少程序正在占用该文件系统时:  
                例如:找到所有使用到 /proc 这个文件系统的程序吧!
                    [root@www ~]# fuser -uv /proc
            也可以针对单个文件进行查看
            将某个正在使用该文件的程序kill掉
                [root@www ~]# fuser -ki /var/gdm/.gdmfifo
        lsof :列出被程序所开启的文件档名
            选项与参数:
                -a  :多项数据需要『同时成立』才显示出结果时! (使用 lsof -u root -U 及 lsof -u root -a -U 都不同,因为-a 的用途就是在解决同时需要两个项目都成立时)
                -U  :仅列出 Unix like 系统的 socket 文件类型;
                -u  :后面接 username,列出该使用者相关程序所开启的文件;
                +d  :后面接目录,亦即找出某个目录底下已经被开启的文件!
        pidof :找出某支正在运行的程序的 PID
            选项与参数:
                -s  :仅列出一个 PID 而不列出所有的 PID
                -x  :同时列出该 program name 可能的 PPID 那个程序的 PID


SELinux 初探: P632
    什么是 SELinux:
        (一)当初设计的目标:避免资源的误用,很多企业界发现, 通常系统出现问题的原因大部分都在於『内部员工的资源误用』所导致的,实际由外部发动的攻击反而没有这么严重。
            其实 SELinux 是在进行程序、文件等细部权限配置依据的一个核心模块! 由於启动网络服务的也是程序,因此刚好也能够控制网络服务能否存取系统资源的一道关卡
        (二)DAC(自主式存取控制):传统的文件权限与帐号关系
            就是依据程序的拥有者与文件资源的 rwx 权限来决定有无存取的能力
            缺陷:
                第一:root 具有最高的权限:如果不小心某支程序被有心人士取得, 且该程序属於 root 的权限,那么这支程序就可以在系统上进行任何资源的存取!
                第二:使用者可以取得程序来变更文件资源的存取权限:如果你不小心将某个目录的权限配置为 777 ,由於对任何人的权限会变成 rwx ,因此该目录就会被任何人所任意存取
        (三)MAC(委任式存取控制):以政策守则订定特定程序读取特定文件
            可以针对特定的程序与特定的文件资源来进行权限的控管


SELinux 的运行模式: P633
    重要回顾:SELinux 是透过 MAC 的方式来控管程序,他控制的主体是程序, 而目标则是该程序能否读取的『文件资源』
    主体 (Subject,即程序,process) + 目标 (Object,即文件系统) + 政策 (Policy) + 安全性本文 (security context)
        主体能不能存取目标除了政策指定之外,主体与目标的安全性本文必须一致才能够顺利存取
    安全性本文 (Security Context):安全性本文你就将他想成 SELinux 内必备的 rwx 就是了 P634
        安全性本文是放置到文件的 inode 内的
        利用 ls -Z 观察安全性文本,观察到的安全性文本主要有3栏:
            Identify:除了 root 之外,其他的识别后面都会加上『 _u 』的字样
            Role:最后面使用『 _r 』来结尾
            Type(类型):    type:在文件资源 (Object) 上面称为类型 (Type);
                        domain:在主体程序 (Subject) 则称为领域 (domain) 了!


    程序与文件 SELinux Type(类型) 栏位的相关性
            主要看例子。
SELinux 的启动、关闭与观察: P636
    目前 SELinux 支持三种模式:
            enforcing:强制模式,代表 SELinux 运行中,且已经正确的开始限制 domain/type 了;
                permissive:宽容模式:代表 SELinux 运行中,不过仅会有警告信息并不会实际限制 domain/type 的存取。这种模式可以运来作为 SELinux 的 debug 之用;
                disabled:关闭,SELinux 并没有实际运行。
        getenforce:知道目前的 SELinux 模式
        sestatus:知道 SELinux 的政策 (Policy) 为何
        /etc/selinux/config : SELinux 的配置档文件(可以通过这个文档修改Selinux的模式和政策)
    SELinux 的启动与关闭:
        注意 :  如果改变了政策则需要重新启动
            如果由 enforcing 或 permissive 改成 disabled ,或由 disabled 改成其他两个,那也必须要重新启动;
            只可以在 SELinux 运行下切换成为强制 (enforcing) 或宽容 (permissive) 模式


(一般服务启动的脚本会在 /etc/init.d/ 底下)
SELinux 网络服务运行范例: P638
    为什么用这个范例呢?
        targeted 这个政策,主要是在管理网络服务
    该范例展示了错误的安全性文本(Security context)会导致的一些问题
    chcon:修改文件的安全性文本
    restorecon:使用默认的安全先文本还原该文件的安全性文本
SELinux 所需的服务:
    setroubleshoot P641
    auditd :详细数据写入 /var/log/audit/audit.log,将 SELinux 发生的错误资讯写入 /var/log/audit/audit.log 中
SELinux 的政策与守则管理: P643
    现在我们知道,一个主体程序能否读取到目标文件资源的重点在於 SELinux 的政策以及政策内的各项守则, 然后再透过该守则的定义去处理各目标文件的安全性本文,尤其是『类型』的部分
    seinfo:查询政策提供的相关守则
    sesearch:用于查询详细的守则
    布林值的查询与修改: P645
        getsebool :列出目前系统上面的所有布林值条款配置为开启或关闭值
        如果查询到某个布林值,并且以 sesearch 知道该布林值的用途后,想要关闭或启动他,又该如何处置?
        setsebool :修改布林值
    默认目录的安全性本文查询与修改: P646
        semanage:查询文件的默认安全性本文
    添加某些自订的目录的安全性本文
    












第十八章、认识系统服务 (daemons)
什么是 daemon 与服务 (service): P652
达成某个 service 的程序我们就称呼他为 daemon。
(你不必去区分什么是 daemon 与 service !事实上,你可以将这两者视为相同!因为达成某个服务是需要一支 daemon 在背景中运行, 没有这支 daemon 就不会有 service !所以不需要分的太清楚)
daemon 的主要分类: P653
(一)stand alone: 此 daemon 可以自行单独启动服务
① 可以自行启动而不必透过其他机制的管理; ② 启动并加载到内存后就一直占用内存与系统资源
   优点:  响应速度较快
(二)super daemon: 一支特殊的 daemon 来统一管理
  特点: 当没有客户端的要求时,各项服务都是未启动的情况,等到有来自客户端的要求时, super daemon 才唤醒相对应的服务,当客户端的要求结束后,被唤醒的这个服务也会关闭并释放系统资源。
  优点:    ① 以具有安全控管的机制,就是类似网络防火墙的功能
② 由于服务在客户端的联机结束后就关闭,因此不会一直占用系统资源
  缺点:    服务的反应时间会比较慢一些
daemon 工作形态的类型
(一)signal-control : 
这种 daemon 是透过讯号来管理的,只要有任何客户端的需求进来,他就会立即启动去处理!例如打印机的服务 (cupsd)。 
(二)interval-control:
这种 daemon 则主要是『每隔一段时间就主动的去运行某项工作』,所以,你要作的是在配置文件指定服务要进行的时间与工作, 该服务在指定的时间才会去完成工作。我们在第十六章提到的 atd 与 crond 就属于这种类型的 daemon 啦 (每分钟侦测一次配置文件)
daemon 的命名守则
许多程序名字后面都有个 d ,比如atd、crond、vsftpd等等,这里的d指的是daemon
服务与埠口的对应: P655
IP代表主机在网络上面的【门牌号码】,但是我们的主机可以提供不止一项的服务,但我们只有一个IP,当用户端连线過來我們的主機时, 我們主机是如何分辨不同的服务要求呢?那就是透过埠号 (port number) 
/etc/servies:服务与埠号对应在一起
第一栏为 daemon 的名称;
第二栏为该 daemon 所使用的端口号与网络数据封包协议
daemon 的启动脚本与启动方式 p656
daemon 虽然只是一支程序而已,但是这支 daemon 的启动还是需要执行档、设定档、执行环境等等。要启动一支 daemon 考虑的事情很多,并非单纯执行一支程序就够了。
通常 distribution 会给我们一个简单的 shell script 来进行启动的功能
① /etc/init.d/* :启动脚本放置处(系统上几乎所有的服务启动脚本都放置在这里)
② /etc/sysconfig/* :各服务的初始化环境设定檔
③ /etc/xinetd.conf, /etc/xinetd.d/* :super daemon 设定檔
④ /etc/* :各服务各自的设定檔
⑤ /var/lib/* :各服务产生的数据库(一些会产生数据的服务都会将他的数据写入到 /var/lib/ 目录中)
⑥ /var/run/* :各服务的程序之 PID 记录处


Stand alone 的 /etc/init.d/* 启动 P657
利用 /etc/init.d/* 来启动、关闭与观察
service:仅是一支 script,可 以分析你下达的 service 后面的参数,然后根据你的参数再到 /etc/init.d/ 去取得正确的服务来 start 或 stop 
Super daemon 的启动方式
Super daemon 本身也是一支 stand alone 的服务
如何取消或开启一个服务呢?
先修改设定档成为启动的模样(透过vim /etc/xinetd.d/rsync)
重新启动 xinetd 这个服务(/etc/init.d/xinetd restart)
观察启动的埠口(grep 'rsync' /etc/services)


解析 super daemon 的配置文件: P659
super daemon 是 xinetd 这一支程序所达成的—— xinetd 可以进行安全性或者是其他管理机制的控管——可以让我们的某些服务更为安全, 资源管理更为合理——因此一些对客户端开放较多权限的服务 (例如 telnet), 或者本身不具有管理机制或防火墙机制的服务,就可以透过 xinetd 来管理。
默认值配置文件:xinetd.conf (P659)
如果你有启动某个 super daemon 管理的服务, 但是该服务的配置值并没有指定上述的那些项目,那么该服务的配置值就以上述的默认值为主
例如:一个服务只能有n个同时联机、每秒钟发起的「新」联机最多仅能有 m 条
【所有的服务参数档都在/etc/xinetd.d 里面】
= : 表示后面的配置参数就是这样啦!
+= : 表示后面的配置为『在原来的配置里头加入新的参数』
-= : 表示后面的配置为『在原来的参数舍弃这里输入的参数!』


我们知道透过 super daemon 控管的服务可以多一层管理的手续来达成类似防火墙的机制, 那么该如何仔细的配置这些类似防火墙机制的配置参数呢?
一个简单的 rsync 范例配置 P662
rsync:可以让两部主机上面的某个目录一模一样,在远程异地备援系统上面是挺好用的一个机制
可以通过vim /etc/xinetd.d/rsync  来进行对不同接口进行不同的权限配置


服务的防火墙管理 xinetd, TCP Wrappers: P664
/etc/hosts.allow + /etc/hosts.deny 管理
任何以 xinetd 管理的服务,都可以透过 /etc/hosts.allow, /etc/hosts.deny 来配置防火墙
那么什么是防火墙啊?
就是针对来源 IP 或网域进行允许或拒绝的配置, 以决定该联机是否能够成功达成连接的一种方式就是了
【【【【【基本上只要一个服务受到 xinetd 管理,或者是该服务的程序支持 TCP Wrappers 函式的功能时,那么该服务的防火墙方面的配置就能够以 /etc/hosts.{allow,deny} 来处理啰。换个方式来说,只要不支持 TCP Wrappers 函式功能的软件程序就无法使用 /etc/hosts.{allow,deny} 的配置值】】】】】
如何得知一个服务的程序有没有支持 TCP Wrappers 呢?
透过   [root@www ~]# ldd $(which sshd httpd)  来查看是否支持
那我如何在这两个文件中进行配置呢?
看P665

TCP Wrappers 特殊功能: P666
spawn (action):
可以利用后续接的 shell 来进行额外的工作,且具有变量功能,主要的变量内容为: %h (hostname), %a (address), %d (daemon)等等;
twist (action):
立刻以后续的命令进行,且运行完后终止该次联机的要求 (DENY)
我们可以透过此功能抵挡我们拒绝的主机,整个的流程是:
① 利用 safe_finger 去追踪出对方主机的信息 (包括主机名、用户相关信息等);
② 将该追踪到的结果以 email 的方式寄给我们本机的 root ;
③ 在对方屏幕上面显示不可登陆且警告他已经被记录的信息
系统开启的服务: P667
找出目前系统开启的『网络服务』有哪些?
[root@www ~]# netstat -tulp
找出所有的有监听网络的服务 (包含 socket 状态):
[root@www ~]# netstat -lnp
观察所有的服务状态
[root@www ~]# service --status-all
配置启动后立即启动服务的方法: P668
chkconfig: 管理系统服务默认启动启动与否(透过 chkconfig 来管理 super daemon 的服务,但是,chkconfig 仅是配置启动时默认会启动的服务而已, 所以该服务目前的状态如何是不知道的) P669
我们仅是配置启动时启动而已啊!  因此在使用chkconfig后,需要重启xinetd(为什么不是重启我们的指定的那个服务呢?因为是同一归super daemon管的啊)来即使改变状态。
ntsysv: 类图形接口管理模式(除了chkconfig还有这个可以用于管理) P670


总结一下:
① stand alone daemon 启动的脚本放置到 /etc/init.d/ 这个目录中,super daemon 的配置文件在 /etc/xinetd.d/* 内, 而启动的方式则为 /etc/init.d/xinetd restart
② 如何找出启动port为3306端口的服务为啥? 透过搜寻 /etc/services 内容,得到 port 3306 为 mysql 所启动的端口喔!
③ 你可以透过哪些命令查询到目前系统默认启动会启动的服务? 本章提到的 chkconfig 以及 ntsysv 都可以查阅的到!
④ tcp wrappers 软件功能与 xinetd 的功能中,可以使用哪两个文件进行网络防火墙的控管? /etc/hosts.{allow,deny}
⑤ 如何区分程序是stand alone 还是 super daemon 呢?
利用chkconfig 查看后,只有 on 或 off 者为 super daemon。通过/etc/xinetd.d/*启动












                                    第十九章、认识与分析登录文件
什么是登录文件: P679
    记录系统活动资讯的几个文件, 例如:何时、何地 (来源 IP)、何人 (什么服务名称)、做了什么动作 (信息登录罗)。 换句话说就是:记录系统在什么时候由哪个程序做了什么样的行为时,发生了何种的事件等等
    登录文件的重要性:
      解决系统方面的错误
      解决网络服务的问题
      过往事件记录簿
    Linux 常见的登录文件档名: P680
    /var/log/cron:关于工作排程
    /var/log/dmesg:记录系统在启动的时候核心侦测过程所产生的各项资讯
/var/log/lastlog:可以记录系统上面所有的帐号最近一次登陆系统时的相关资讯(命令lastlog)
/var/log/maillog 或 /var/log/mail/*:记录邮件的往来资讯,其实主要是记录 sendmail (SMTP 协议提供者) 与 dovecot (POP3 协议提供者) 所产生的信息
/var/log/messages:几乎系统发生的错误信息 (或者是重要的资讯) 都会记录在这个文件中; 如果系统发生莫名的错误时,这个文件是一定要查阅的登录文件一
/var/log/secure:只要牵涉到『需要输入帐号口令』的软件,那么当登陆时 (不管登陆正确或错误) 都会被记录在此文件中
/var/log/wtmp, /var/log/faillog:记录正确登陆系统者的帐号资讯 (wtmp) 与错误登陆时所使用的帐号资讯 (faillog) 
/var/log/httpd/*, /var/log/news/*, /var/log/samba/*:不同的网络服务会使用它们自己的登录文件来记载它们自己产生的各项信息
登录文件所需相关服务 (daemon) 与程序 P681
        登录文件所需的服务主要就是 rsyslogd 与 klogd 这两者
rsyslogd:主要登录系统与网络等服务的信息;
klogd:主要登录核心产生的各项资讯;
透过 logrotate (登录文件轮替) 来自动化处理登录文件容量与升级的问题    
logrotate:主要在进行登录文件的轮替功能。


rsyslogd :记录登录文件的服务
首先通过ps aux 或是 chkconfig 来确认服务是否已经开启
登录文件内容的一般格式
事件发生的日期与时间;
发生此事件的主机名称;
启动此事件的服务名称 (如 samba, xinetd 等) 或函式名称 (如 libpam ..);
该信息的实际数据内容。
发生底下几种情况时要常常去『巡视』登录文件的内容:
当你觉得系统似乎不太正常时;
某个 daemon 老是无法正常启动时;
某个使用者老是无法登陆时;
某个 daemon 运行过程老是不顺畅时;
rsyslog 的配置档:/etc/rsyslog.conf: P683
(1)什么服务 : rsyslog 本身有规范一些服务,你可以透过这些服务来储存系统的信息
(2)信息等级 : (由不重要排列到重要信息等级)
在信息等级之前还有 [.=!] 的连结符号喔!他代表的意思是这样的:
. :代表『比后面还要高的等级 (含该等级) 都被记录下来』的意思,例如: mail.info 代表只要是 mail 的资讯,而且该资讯等级高於 info (含 info 本身)时,就会被记录下来的意思。
.=:代表所需要的等级就是后面接的等级而已, 其他的不要!
.!:代表不等於, 亦即是除了该等级外的其他等级都记录。
(3)需要被记录在哪里(装置或文件)』
文件的绝对路径:通常就是放在 /var/log 里头的文件啦!
打印机或其他:例如 /dev/lp0 这个打印机装置
使用者名称:显示给使用者罗!
                远程主机:例如 @www.vbird.tsai 当然啦,要对方主机也能支持才行!
               *:代表『目前在线上的所有人』,类似 wall 这个命令的意义!
那么我们自己来配置一下rsyslog 的配置档吧 P685
问题一:如果我要将我的 mail 相关的数据给他写入 /var/log/maillog 当中
mail.info   /var/log/maillog
问题二:要将新闻群组数据 (news) 及例行性工作排程 (cron) 的信息都写入到一个称为 /var/log/cronnews 的文件中,但是这两个程序的警告信息则额外的记录在 /var/log/cronnews.warn 中
news.*;cron.*     /var/log/cronnews
news.=warn;cron.=warn /var/log/cronnews.warn
问题三:我的 messages 这个文件需要记录所有的资讯,但是就是不想要记录 cron, mail 及 news 的资讯
*.*;news,cron,mail.none      /var/log/messages
*.*;news.none;cron.none;mail.none /var/log/messages
CentOS 5.x 默认的 rsyslog.conf 内容中:
在记录的文件 /var/log/maillog 前面还有个减号『 - 』是干嘛用的?由於邮件所产生的信息比较多,因此我们希望邮件产生的信息先储存在速度较快的内存中 (buffer) ,等到数据量够大了才一次性的将所有数据都填入磁碟内
登录文件的安全性配置:【【【隐藏属性】】】
chattr:    使某文件不能删除不能新增
使某文件不能删除只能新增
lsattr: 显示隐藏属性


登录文件服务器的配置: P688
为什么要配置文件服务器?
你的办公室内有十部 Linux 主机,每一部负责一个网络服务, 你为了要了解每部主机的状态,因此,你常常需要登陆这十部主机去查阅你的登录文件~ 哇!光用想的,每天要进入十部主机去查数据,想到就烦~没关系~这个时候我们可以让某一部主机当成 『登录文件服务器』,用他来记录所有的十部 linux 主机的资讯,嘿嘿!这样我就直接进入一部主机就可以了
如何配置呢?
通过修改rsyslog的配置档rsyslog.conf来实现


登录文件的轮替(logrotate): P689
rsyslog 利用的是 daemon 的方式来启动的, 当有需求的时候立刻就会被运行的,但是 logrotate 却是在规定的时间到了之后才来进行登录文件的轮替, 所以这个 logrotate 程序当然就是挂在 cron 底下进行的呦!
logrotate 的配置档:
/etc/logrotate.conf
/etc/logrotate.d/
logrotate 的主要功能就是将旧的登录文件移动成旧档, 并且重新创建一个新的空的文件来记录
当第一次运行完 rotate 之后,原本的 messages 会变成 messages.1 而且会制造一个空的 messages 给系统来储存登录文件。而第二次运行之后,则 messages.1 会变成 messages.2 而 messages 会变成 messages.1 ,又造成一个空的 messages 来储存登录文件!那么如果我们仅配置保留三个登录文件而已的话,那么运行第四次时,则 messages.3 这个文件就会被删除,并由后面的较新的保存登录文件所取代
那么多久进行一次这样的 logrotate 工作呢?
这些都记录在 logrotate.conf 里面:cat /etc/logrotate.conf解读部分自己看书
如果你的系统的空间够大,并且担心除错以及黑客的问题,那么可以:
将 rotate 4 改成 rotate 9 左右,以保存较多的备份文件;
大部分的登录文件不需要 compress 罗!但是空间太小就需要 compress !尤其是很占磁盘空间的 httpd 更需要 compress 的!
接下来我们再以 /etc/logrotate.d/syslog 这个轮替 syslog 服务的文件,来看看该如何配置他的 rotate :
cat /etc/logrotate.d/syslog
档名:被处理的登录文件绝对路径档名写在前面,可以使用空白字节分隔多个登录文件;
参数:上述档名进行轮替的参数使用 { } 包括起来;
运行脚本:可呼叫外部命令来进行额外的命令下达,这个配置需与 sharedscripts .... endscript 配置合用才行。至於可用的环境为:
prerotate:在启动 logrotate 之前进行的命令,例如修改登录文件的属性等动作;【*****比如说在文档之前配置了chattr为不能删除不能修改,那么如何实现轮替呢?  这时候prerotate就起到作用了,prerotate指的是在轮替之前的行为,我们可以在prerotate下写下将chattr去除,然后再在postrotate下重新赋予这种属性  这样就可以实现修改了。*****】】】】)
postrotate:在做完 logrotate 之后启动的命令,例如重新启动 (kill -HUP) 某个服务!
(Prerotate 与 postrotate 对於已加上特殊属性的文件处理上面,是相当重要的运行程序!)
结合Rotata的默认配置档,最终整个文档的论题功能就变成了:
该配置只对 /var/log/ 内的 messages, secure, maillog, spooler, boot.log, cron 有效;
登录文件轮替每周一次、保留四个、且轮替下来的登录文件不进行压缩(未更改默认值);
轮替完毕后 (postrotate) 取得 syslog 的 PID 后,以 kill -HUP 重新启动 syslogd


自订登录文件的轮替功能:
实例:自己创建一个可以进行轮替的文件


分析登录文件: P694
logwatch:会每天分析一次登录文件
鸟哥自制的查询档案软件
总结: ① syslogd 的配置档在 /etc/syslog.conf ,内容语法为:『 服务.等级 记载装置或文件』
② logrotate 程序利用 crontab 来进行登录文件的轮替功能;
③ syslogd 为 stand alone daemon 的机制;






    



第二十章、启动流程、模块管理与 Loader
系统启动的经过可以汇整成底下的流程的: P701
① 加载 BIOS 的硬件资讯与进行自我测试,并依据配置取得第一个可启动的装置;
② 读取并运行第一个启动装置内 MBR 的 boot Loader (亦即是 grub, spfdisk 等程序);
③ 依据 boot loader 的配置加载 Kernel ,Kernel 会开始侦测硬件与加载驱动程序;
④ 在硬件驱动成功后,Kernel 会主动呼叫 init 程序,而 init 会取得 run-level 资讯;
⑤ init 运行 /etc/rc.d/rc.sysinit 文件来准备软件运行的作业环境 (如网络、时区等);
⑥ init 运行 run-level 的各个服务之启动 (script 方式);
⑦ init 运行 /etc/rc.d/rc.local 文件;
⑧ init 运行终端机模拟程序 mingetty 来启动 login 程序,最后就等待使用者登陆啦;


BIOS, 启动自我测试与 MBR P702
透过 BIOS 程序去加载 CMOS 的资讯,并且藉由 CMOS 内的配置值取得主机的各项硬件配置, 例如 CPU 与周边设备的沟通时脉啊、启动装置的搜寻顺序啊、硬盘的大小与类型啊、 系统时间啊、 各周边设备的 I/O 位址啊、以及与 CPU 沟通的 IRQ 岔断等等的资讯。
取得这些资讯后,BIOS 还会进行启动自我测试。
然后开始运行硬件侦测的初始化,并配置 PnP 装置,之后再定义出可启动的装置顺序
接下来就MBR 相关的任务开始


Boot Loader:启动管理程序
安装在启动装置的第一个磁区 (sector) 内,也就是我们一直谈到的 MBR (Master Boot Record, 主要启动记录区)。
既然核心文件需要 loader 来读取,那每个操作系统的 loader 都不相同, 这样的话 BIOS 又是如何读取 MBR 内的 loader 呢?
只要 BIOS 能够侦测的到你的磁碟 (不论该磁碟是 SATA 还是 IDE 介面),那他就有办法透过 INT 13 这条通道来读取该磁碟的第一个磁区内的 MBR 啦!(注2) 这样 boot loader 也就能够被运行
我们常常讲的『系统的 MBR』其实指的是 第一个启动装置的 MBR 


Boot Loader 的功能:
对于不同的操作系统
(1)必须要使用自己的 loader 才能够加载属於自己的操作系统核心
(2)系统的 MBR 只有一个,那你怎么会有办法同时在一部主机上面安装 Windows 与 Linux 呢?
其实每个文件系统 (filesystem, 或者是 partition) 都会保留一块启动磁区 (boot sector) 提供操作系统安装 boot loader,而通常操作系统默认都会安装一份 loader 到他根目录所在的文件系统的 boot sector 上。
在 Linux 系统安装时,你可以选择将 boot loader 安装到 MBR 去,也可以选择不安装。 如果选择安装到 MBR 的话,那理论上你在 MBR 与 boot sector 都会保有一份 boot loader 程序的。 至於 Windows 安装时,他默认会主动的将 MBR 与 boot sector 都装上一份 boot loader!所以啦, 你会发现安装多重操作系统时,你的 MBR 常常会被不同的操作系统的 boot loader 所覆盖啦! ^_^
功能为:
① 提供菜单:使用者可以选择不同的启动项目,这也是多重启动的重要功能!
② 加载核心文件:直接指向可启动的程序区段来开始操作系统;
③ 转交其他 loader:将启动管理功能转交给其他 loader 负责。
个人理解:【【【但是但是, Windows 的 loader 默认不具有控制权转交的功能,因此你不能使用 Windows 的 loader 来加载 Linux 的 loader 。所以如果先安装了linux,之后安装windows,MBR被windows覆盖,且该boot loader不具备loader转交功能,那么以后使用就无法切换至linux启动。然而若后来装linux,且将其boot loader装至MBR,那么就可以实现双系统之间的转换。】】】


加载核心侦测硬件与 initrd 的功能: P703
Linux 核心会以自己的功能重新侦测一次硬件,而不一定会使用 BIOS 侦测到的硬件资讯喔!也就是说,核心此时才开始接管 BIOS 后的工作了
Linux 核心是可以透过动态加载核心模块的,这些核心模块就放置在 /lib/modules/ 目录内。 由於模块放置到磁碟根目录内 (要记得 /lib 不可以与 / 分别放在不同的 partition !), 因此在启动的过程中核心必须要挂载根目录,这样才能够读取核心模块提供加载驱动程序的功能
现在来思考一种情况,假设你的 linux 是安装在 SATA 磁碟上面的,你可以透过 BIOS 的 INT 13 取得 boot loader 与 kernel 文件来启动,然后 kernel 会开始接管系统并且侦测硬件及尝试挂载根目录来取得额外的驱动程序。
问题是,核心根本不认识 SATA 磁碟,所以需要加载 SATA 磁碟的驱动程序, 否则根本就无法挂载根目录。但是 SATA 的驱动程序在 /lib/modules 内,你根本无法挂载根目录又怎么读取到 /lib/modules/ 内的驱动程序? 这时候就要用到  虚拟文件系统 (Initial RAM Disk) (一般使用的档名为 /boot/initrd) 了
透过该程序来加载启动过程中所最需要的核心模块, 通常这些模块就是 U盘, RAID, LVM, SCSI 等文件系统与磁碟介面的驱动程序
我们通过一步步分解initrd文件发现,initrd 有加载模块并且尝试挂载了虚拟文件系统
boot loader 可以加载 kernel 与 initrd ,在内存中让 initrd 解压缩成为根目录, kernel 就能够藉此加载适当的驱动程序,最终释放虚拟文件系统,并挂载实际的根目录文件系统, 就能够开始后续的正常启动流程
① 是否没有 initrd 就无法顺利启动?② 什么时候使用initrd呢?
解① 如果你的 Linux 是安装在 IDE 介面的磁碟上,并且使用默认的 ext2/ext3 文件系统, 那么不需要 initrd 也能够顺利的启动进入 Linux 的!
解② 需要 initrd 最重要的原因是,当启动时无法挂载根目录的情况下, 此时就一定需要 initrd ,例如你的根目录在特殊的磁碟介面 (U盘, SATA, SCSI) , 或者是你的文件系统较为特殊 (LVM, RAID) 等等,才会需要 initrd。


第一支程序 init 及配置档 /etc/inittab 与 runlevel P705
在核心加载完毕、进行完硬件侦测与驱动程序加载后,此时你的主机硬件应该已经准备就绪了 (ready) , 此时核心会主动的呼叫第一支程序,那就是 /sbin/init 
Run level:运行等级有哪些?
0 - halt (系统直接关机)
1 - single user mode (单人维护模式,用在系统出问题时的维护)
2 - Multi-user, without NFS (类似底下的 runlevel 3,但无 NFS 服务)
3 - Full multi-user mode (完整含有网络功能的纯文字模式)
4 - unused (系统保留功能)
5 - X11 (与 runlevel 3 类似,但加载使用 X Window)
6 - reboot (重新启动)
init 的处理流程:(我在自己装的linux上面看到的全是注释,但是注释中的说明和书上所说的内容相差无几,只不过是放在不同的文件中去了罢了)p707
① 先取得 runlevel 亦即默认运行等级的相关等级 (以鸟哥的测试机为例,为 5 号);
② 使用 /etc/rc.d/rc.sysinit 进行系统初始化
③ 由於 runlevel 是 5 ,因此只进行『l5:5:wait:/etc/rc.d/rc 5』,其他行则略过
④ 配置好 [ctrl]+[alt]+[del] 这组的组合键功能
⑤ 配置不断电系统的 pf, pr 两种机制;
⑥ 启动 mingetty 的六个终端机 (tty1 ~ tty6)
⑦ 最终以 /etc/X11/perfdm -nodaemon 启动图形介面啦!
init 处理系统初始化流程 (文件主要根据/etc/inittab中所说的),可以发现他主要的工作大抵有这几项: P708
测试与挂载内存装置 /proc 及 U盘 装置 /sys
决定是否启动 SELinux :
配置显示於启动过程中的欢迎画面 (text banner);
配置系统时间 (clock) 与时区配置:需读入 /etc/sysconfig/clock 配置值
周边设备的侦测与 Plug and Play (PnP) 参数的测试:
初始化软件磁盘阵列:主要是透过 /etc/mdadm.conf 来配置好的。
初始化 LVM 的文件系统功能
以 fsck 检验磁碟文件系统:会进行 filesystem check
进行磁碟配额 quota 的转换 (非必要):
重新以可读写模式挂载系统磁碟:
启动 quota 功能:所以我们不需要自订 quotaon 的动作
启动系统虚拟乱数产生器 (pseudo-random):
清除启动过程当中的缓存文件:
将启动相关资讯加载 /var/log/dmesg 文件中。
启动系统服务与相关启动配置档 (/etc/rc.d/rc N & /etc/sysconfig)(拿自动启动图形界面举例) P709
透过外部第一号参数 ($1) 来取得想要运行的脚本目录。亦即由 /etc/rc.d/rc 5 可以取得 /etc/rc5.d/ 这个目录来准备处理相关的脚本程序;
找到 /etc/rc5.d/K??* 开头的文件,并进行『 /etc/rc5.d/K??* stop 』的动作;
找到 /etc/rc5.d/S??* 开头的文件,并进行『 /etc/rc5.d/S??* start 』的动作;
我们发现:
档名全部以 Sxx 或 Kxx ,其中 xx 为数字,且这些数字在文件之间是有相关性的!
全部是连结档,连结到 stand alone 服务启动的目录 /etc/init.d/ 去
S 或者是 K 后面接的数字是啥意思?
那就是运行的顺序,数字越大越晚执行


使用者自订启动启动程序 (/etc/rc.d/rc.local) P710
我有任何想要在启动时就进行的工作时,直接将他写入 /etc/rc.d/rc.local , 那么该工作就会在启动的时候自动被加载


启动过程会用到的主要配置档: P711
modprobe.d:,如果系统捉到错误的驱动程序,或者是你想要使用升级的驱动程序来对应相关的硬件配备时, 你就得要自行手动的处理一下这个文件
/etc/sysconfig/*:整个启动的过程当中,读取的一些服务的相关配置档都是记录在 /etc/sysconfig 目录下的

Run level 的切换: P712
如果我们从一个runlevel切换至另一个runlevel,那么是怎样一个过程呢?比如从run level 5切换到run level 3
先比对 /etc/rc3.d/ 及 /etc/rc5.d 内的 K 与 S 开头的文件;
在新的 runlevel 亦即是 /etc/rc3.d/ 内有多的 K 开头文件,则予以关闭;
在新的 runlevel 亦即是 /etc/rc3.d/ 内有多的 S 开头文件,则予以启动;


核心与核心模块: P713
为了应付日新月异的硬件,目前的核心都是具有『可读取模块化驱动程序』的功能, 亦即是所谓的『 modules (模块化)』的功能
模块化可将他想成是一个『外挂程序』, 该外挂程序可能由硬件开发厂商提供,也有可能我们的核心本来就支持~不过,较新的硬件, 通常都要硬件开发商提供驱动程序模块
核心与核心模块放在哪?
核心: /boot/vmlinuz 或 /boot/vmlinuz-version;
核心解压缩所需 RAM Disk: /boot/initrd (/boot/initrd-version);
核心模块: /lib/modules/version/kernel 或 /lib/modules/$(uname -r)/kernel;
核心原始码: /usr/src/linux 或 /usr/src/kernels/ (要安装才会有,默认不安装)
如果该核心被顺利的加载系统当中了,那么就会有几个资讯纪录下来:
核心版本: /proc/version
系统核心功能: /proc/sys/kernel
如果我有个新的硬件,偏偏我的操作系统不支持,该怎么办?
重新编译核心,并加入最新的硬件驱动程序原始码;
将该硬件的驱动程序编译成为模块,在启动时加载该模块
核心模块与相依性 P714
/lib/modules/$(uname -r)/modules.dep:记录了在核心支持的模块的各项相依性
什么是相依性?就是启动某项模块时需要提前启动另一项才行,有启动的先后顺序
核心模块的观察: P715
lsmod:查看目前核心加载了多少的模块
模块名称(Module);
模块的大小(size);
此模块是否被其他模块所使用 (Used by)。
modinfo:查阅在核心内的模块
检查『某个模块文件』
核心模块的加载与移除: P716
insmod与remod:用于加载移除模块;但是需要使用者自行找到模块的完整档名才行,且万一模块有相依属性的问题时,你将无法直接加载或移除该模块
modprobe: 用于加载移除模块;会主动的去搜寻 modules.dep 的内容,先克服了模块的相依性后, 才决定需要加载的模块有哪些,因此更加方便
核心模块的额外参数配置: /etc/modprobe.conf P717


Boot Loader: Grub
boot loader 的两个 stage: P717
MBR 是整个硬盘的第一个 sector 内的一个区块,充其量整个大小也才 446 bytes 而已,
所以 Linux 将 boot loader 的程序码运行与配置值加载分成两个阶段 (stage) 来运行:
① Stage 1:运行 boot loader 主程序
② Stage 2:主程序加载配置档(在/boo下)
grub 的配置档 /boot/grub/menu.lst 与菜单类型: P718
grub优点:
认识与支持较多的文件系统,并且可以使用 grub 的主程序直接在文件系统中搜寻核心档名;
启动的时候,可以『自行编辑与修改启动配置项目』,类似 bash 的命令模式;
可以动态搜寻配置档,而不需要在修改配置档后重新安装 grub 。亦即是我们只要修改完 /boot/grub/menu.lst 里头的配置后,下次启动就生效了!
硬盘与分割槽在 grub 中的代号:(在 grub 里面,他开始的数字是 0 而不是 1)
以『搜寻顺序』做为硬盘的编号,而不是依照硬盘排线的排序!(这个重要!)
第一个搜寻到的硬盘为 0 号,第二个为 1 号,以此类推;
每颗硬盘的第一个 partition 代号为 0 ,依序类推。
那么是不是说 /dev/hda 就是 (hd0)呢?
· 不一定哦,要看你的 BIOS 配置值才行!有的主板 BIOS 可以调整启动的硬盘搜寻顺序,那么就要注意了,因为 grub 的硬盘代号可能会跟著改变
/boot/grub/menu.lst 配置档: 9 P719
default=0:这个必须要与 title 作为对照,在配置档里面有几个 title ,启动的时候就会有几个菜单可以选择。如果在读秒时间结束前都没有动到键盘, grub 默认使用此 title 项目 (在此为 0 号) 来启动。
timeout=5:如果在 5 秒钟内没有按下任何按键,就会使用上面提到的 default 后面接的那个 title 项目来启动
splashimage=(hd0,0)/grub/splash.xpm.gz:这个文件提供的背景图示为CentOS 在启动的时候背景
hiddenmenu:启动时是否要显示菜单
title部分(启动时可以有多重选择):
(1) 直接指定核心文件启动
root :代表的是『核心文件放置的那个 partition 而不是根目录』
kernel :核心的档名、核心的参数; root=LABEL=/1 指的是『Linux 的根目录在哪个 partition 』
问题:
我的系统分割是: /dev/hda1 (/), /dev/hda2 (swap) 而已,且我的核心文件为 /boot/vmlinuz,请问 grub 的 menu.lst 内该如何撰写核心文件位置?
kernel (hd0,0)/boot/vmlinuz root=/dev/hda1 ...
同上,只是我的分割情况变成: /dev/sda1 (/boot), /dev/sda5 (/) 时?
kernel (hd0,0)/vmlinuz root=/dev/sda5 ...
(2) 利用 chain loader 的方式转交控制权
他只是将 boot 的控制权交给下一个 boot sector 或 MBR 内的 boot loader 而已
具体内容见书


initrd 的重要性与创建新 initrd 文件: P722
需要 initrd 的时刻为:
根目录所在磁碟为 SATA、U盘 或 SCSI 等连接介面;
根目录所在文件系统为 LVM, RAID 等特殊格式;
根目录所在文件系统为非传统 Linux 认识的文件系统时;
其他必须要在核心加载时提供的模块。
mkinitrd:如果你有特殊需要所以想重制 initrd 文件的话
测试与安装 grub: P724
如何安装grub呢?
注意boot loader 有两个 stage ,而配置档得要放置到适当的地方
第一步:::grub-install:安装 grub 相关的文件 (例如文件系统定义档) 到你的装置上面去等待在启动时被读取,但还需要配置好配置档 (menu.lst) 后,再以 grub shell 来安装 grub 主程序到 MBR 或者是 boot sector 上面去
第二步:::配置/boot/grub/menu.lst文档
示例:
我预计启动时要直接显示菜单,且菜单倒数为 30 秒。另外,在原本的 menu.lst 当中新增三个启动菜单,分别如下说明:
① 假设 /dev/hda1 内含有 boot loader ,此 loader 如何取得控制权?
② 如何重新读取 MBR 内的 loader ?
③ 利用你原本的系统核心文件,创建一个可强制进入单人维护模式的菜单
那么 /boot/grub/menu.lst修改为:
title CentOS (2.6.18-92.el5) //title后面的文字即为开机时候显示的内容 四个title显示4行
        root (hd0,0) //代表核心文件放在那个 partition 当中
        kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet
        initrd /initrd-2.6.18-92.el5.img
title /dev/hda1 boot sector  <==本例中的第一个新增菜单
        root (hd0,0)
        chainloader +1
title MBR loader             <==新增的第二个菜单
        root (hd0)           <==MBR 为整颗磁碟的第一个磁区,所以用整颗磁碟的代号
        chainloader +1
title single user mode       <==新增的第三个菜单(其实由原本的title复制来的)
        root (hd0,0)
        kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet single //加入了single
        initrd /initrd-2.6.18-92.el5.img
第三步:::grub:安装那个 stage1
使用grub进入grub shell 安装到某个partition的boot loader 或者 MBR中去


最后总结一下:
① 如果是从其他 boot loader 转成 grub 时,得先使用 grub-install 安装 grub 配置档;
② 开始编辑 menu.lst 这个重要的配置档;
③ 透过 grub 来将主程序安装到系统中,如 MBR 的 (hd0) 或 boot sector 的 (hd0,0) 等等。


关於核心功能当中的 vga 配置: P728
调整解析度、分辨率
在 /boot/grub/menu.lst中修改


BIOS 无法读取大硬盘的问题: P729
BIOS 无法读取大容量磁碟内的 kernel 与 initrd 文件,那如何让 kernel 与 initrd 放置到整颗硬盘的最前面呢?简单的要命吧!就创建 /boot 独立分割槽,并将 /boot 放置到最前面即可
那如果在安装完成后发生了这种问题怎么办呢?
Solu① :最简单的做法,就是直接重灌,并且制作出 /boot 挂载的 partition ,同时确认该 partition 是在 1024 cylinder 之前才行。
Solu② :如果实在不想重灌,没有关系,利用我们刚刚上头提到的 grub 功能,额外创建一个可启动软盘, 或者是直接以光驱启动,然后以 grub 的编写能力进入 Linux 。
Solu③ :另外的办法其实是骗过 BIOS ,直接将硬盘的 cylinder, head, sector 等等资讯直接写到 BIOS 当中去,如此一来你的 BIOS 可能就可以读得到与支持的到你的大硬盘了。

为个别菜单加上口令: P730
grub-md5-crypt:输入口令后会得到md5(或其他)码
注意:password 这个项目一定要在 title 底下的第一行
不过,此项功能还是可能被破解的:
使用者可以透过编辑模式 (e) 进入菜单,并删除口令栏位并按下 b 就能够进行启动流程了
不过,可以使用另外的方法,将password放在title前面
除非你输入正确的口令,否则第一个菜单是无法被加载运行的。 另外,这个项目也能够避免你的 menu.lst 在启动的过程中被乱改,是具有保密 menu.lst 的功能
启动过程的问题解决: P731
忘记 root 口令:我们知道,在以root的身份登录的情况下,我们可以直接使用passwd来修改密码且不需要知道以前的密码,但是我们想要以root的身份登录时,却不知道密码,那怎么办呢?
① 重新启动!一定要重新启动!怎么重开都没关系;
② 在启动进入 grub 菜单后, (1)在你要进入的菜单上面点 'e' 进入详细配置; (2)将光棒移动到 kernel 上方并点 'e' 进入编辑画面; (3)然后出现如下画面来处理:
grub edit> kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/ rhgb quiet single
③ 重点就是那个特殊字体的咚咚啦!按下 [enter] 再按下 b 就能够启动进入单人维护模式了。
④ 进入单人维护模式后,系统会以 root 的权限直接给你一个 shell ,此时你就能够运行『 passwd 』这个命令来重建 root 的口令啦!然后直接『 init 5 』就可以切换成为 X 窗口介面罗!就是这么简单。
init 配置档错误:
告诉核心不要运行 init ,改呼叫 bash 
BIOS 磁碟对应的问题 (device.map):
利用两个磁盘所引发的开机问题
因文件系统错误而无法启动:


利用救援光盘来处理系统的错误导致无法启动的问题。 P734












第二十一章、系统配置工具(网络与打印机)与硬件侦测








第二十二章、软件安装:原始码与 Tarball 
开放源码的软件安装与升级简介: P774
Linux 上面的软件几乎都是经过 GPL 的授权
什么是开放源码、编译器与可运行档:
Linux 系统上真正认识的可运行档其实是二进位文件
程序码文件其实就是一般的纯文字档,需要『编译器』来动作, 经过编译器的编译与连结之后,就会产生一支可以运行的 binary program 
总之:
开放源码:就是程序码,写给人类看的程序语言,但机器并不认识,所以无法运行;
编译器:将程序码转译成为机器看的懂得语言,就类似翻译者的角色;
可运行档:经过编译器变成二进位程序后,机器看的懂所以可以运行的文件。
什么是 make 与 configure: P776
make 是一支程序,会去找 Makefile ,那 Makefile 怎么写? 通常软件开发商都会写一支侦测程序来侦测使用者的作业环境, 以及该作业环境是否有软件开发商所需要的其他功能,该侦测程序侦测完毕后,就会主动的创建这个 Makefile 的守则文件
通常这支侦测程序的档名为 configure 或者是 config 
一般来说,侦测程序会侦测的数据大约有底下这些:
是否有适合的编译器可以编译本软件的程序码;
是否已经存在本软件所需要的函式库,或其他需要的相依软件;
操作系统平台是否适合本软件,包括 Linux 的核心版本;
核心的表头定义档 (header include) 是否存在 (驱动程序必须要的侦测)。
什么是 Tarball 的软件: P777
Tarball 是一个软件包, 你将他解压缩之后,里面的文件通常就会有:
原始程序码文件;
侦测程序文件 (可能是 configure 或 config 等档名);
本软件的简易说明与安装说明 (INSTALL 或 README)。
如何安装与升级软件:
将 Tarball 由厂商的网页下载下来;
将 Tarball 解开,产生很多的原始码文件;
开始以 gcc 进行原始码的编译 (会产生目标档 object files);
然后以 gcc 进行函式库、主、副程序的连结,以形成主要的 binary file;
将上述的 binary file 以及相关的配置档安装至自己的主机上面。


使用传统程序语言进行编译的简单范例: P778
GCC使用总结: P782
# 仅将原始码编译成为目标档,并不制作连结等功能:
[root@www ~]# gcc -c hello.c
# 会自动的产生 hello.o 这个文件,但是并不会产生 binary 运行档。


# 在编译的时候,依据作业环境给予最佳化运行速度
[root@www ~]# gcc -O hello.c -c
# 会自动的产生 hello.o 这个文件,并且进行最佳化喔!


# 在进行 binary file 制作时,将连结的函式库与相关的路径填入
[root@www ~]# gcc sin.c -lm -L/usr/lib -I/usr/include
# 这个命令较常下达在最终连结成 binary file 的时候,
# -lm 指的是 libm.so 或 libm.a 这个函式库文件;
# -L 后面接的路径是刚刚上面那个函式库的搜寻目录;
# -I 后面接的是原始码内的 include 文件之所在目录。


# 将编译的结果输出成某个特定档名
[root@www ~]# gcc -o hello hello.c
# -o 后面接的是要输出的 binary file 档名


# 在编译的时候,输出较多的信息说明
[root@www ~]# gcc -o hello hello.c -Wall
# 加入 -Wall 之后,程序的编译会变的较为严谨一点,
# 所以警告信息也会显示出来!


用 make 进行巨集编译:(步骤) P783
首先,编辑 makefile 这个守则档,内容只要作出 main 这个运行档
root@www ~]# vim makefile
main: main.o haha.o sin_value.o cos_value.o(这里是指出所需要的目标档,且该目标档不一样要存在,即使不存在,也会自动创建)
gcc -o main main.o haha.o sin_value.o cos_value.o -lm
# 注意:第二行的 gcc 之前是 按键产生的空格喔!
然后,使用 makefile 制订的守则进行编译的行为:
[root@www ~]# make(前提是没有目标档的存在)
最后测试, 在不删除任何文件的情况下,重新运行一次编译的动作:
[root@www ~]# make
make: `main' is up to date.
# 看到了吧!是否很方便呢!只会进行升级 (update) 的动作而已。
 
make 有这些好处:
简化编译时所需要下达的命令;
若在编译完成之后,修改了某个原始码文件,则 make 仅会针对被修改了的文件进行编译,其他的 object file 不会被更动;
最后可以依照相依性来升级 (update) 运行档。


makefile 的基本语法与变量: P784
标的(target): 目标档1 目标档2
  gcc -o 欲创建的运行档 目标档1 目标档2
如果我想要有两个以上的运行动作时,只需要在makefile中写入内容,然后敲入 make 动作名称就可以了

我们还可以在makefile中使用变量:
不过要注意:
变量与变量内容以『=』隔开,同时两边可以具有空格;
变量左边不可以有 ,例如上面范例的第一行 LIBS 左边不可以是
变量与变量内容在『=』两边不能具有『:』;
在习惯上,变量最好是以『大写字母』为主;
运用变量时,以 ${变量} 或 $(变量) 使用;
在该 shell 的环境变量是可以被套用的,例如提到的 CFLAGS 这个变量!
在命令列模式也可以给予变量。


那如果到处都是同样名字的变量呢?优先级是怎样的呢?
环境变量取用的守则是这样的:
make 命令列后面加上的环境变量为优先;
makefile 里面指定的环境变量第二;
shell 原本具有的环境变量第三。
此外: $@:代表目前的标的(target)


Tarball 的管理与建议: P787
使用原始码管理软件所需要的基础软件:
要制作一个 binary program 需要包括底下这些基础的软件:
gcc 或 cc 等 C 语言编译器 (compiler);
make 及 autoconfig 等软件
需要 Kernel 提供的 Library 以及相关的 Include 文件
在 CentOS 当中,如果你已经有网络可以连上 Internet 的话,那么就可以使用下一章会谈到的 yum 罗! 透过 yum 的软件群组安装功能,你可以这样做:
如果是要安装 gcc 等软件发展工具,请使用『 yum groupinstall "Development Tools" 』
若待安装的软件需要图形介面支持,一般还需要『 yum groupinstall "X Software Development" 』
若安装的软件较旧,可能需要『 yum groupinstall "Legacy Software Development" 』


Tarball 安装的基本步骤,整个安装的基础动作大多是这样的: P788
① 取得原始档:将 tarball 文件在 /usr/local/src 目录下解压缩;
② 取得步骤流程:进入新创建的目录底下,去查阅 INSTALL 与 README 等相关文件内容 (很重要的步骤!);
③ 相依属性软件安装:根据 INSTALL/README 的内容察看并安装好一些相依的软件 (非必要);
④ 创建 makefile:以自动侦测程序 (configure 或 config) 侦测作业环境,并创建 Makefile 这个文件;
⑤ 编译:以 make 这个程序并使用该目录下的 Makefile 做为他的参数配置档,来进行 make (编译或其他) 的动作;
⑥ 安装:以 make 这个程序,并以 Makefile 这个参数配置档,依据 install 这个标的 (target) 的指定来安装到正确的路径!
大部分的 tarball 软件之安装的命令下达方式:
./configure:
通常程序开发者会写一支 scripts 来检查你的 Linux 系统、相关的软件属性等等
make clean:
可以去除目标文件
make:
将原始码编译成为可以被运行的可运行档,而这个可运行档会放置在目前所在的目录之下, 尚未被安装到预定安装的目录中
make install:
通常这就是最后的安装步骤了,make 会依据 Makefile 这个文件里面关於 install 的项目,将上一个步骤所编译完成的数据给他安装到预定的目录中,就完成安装啦
不过请注意,其中只要一个步骤无法成功,那么后续的步骤就完全没有办法进行的


一般 Tarball 软件安装的建议事项 (如何移除?升级?) P789
一软件的文件都在同一个目录之下,那么要移除该软件就简单的多了! 只要将该目录移除即可视为该软件已经被移除罗
为了方便 Tarball 的管理,通常鸟哥会这样建议使用者:
① 最好将 tarball 的原始数据解压缩到 /usr/local/src 当中;
② 安装时,最好安装到 /usr/local 这个默认路径下;
③ 考虑未来的反安装步骤,最好可以将每个软件单独的安装在 /usr/local 底下;
④ 为安装到单独目录的软件之 man page 加入 man path 搜寻:
⑤ 如果你安装的软件放置到 /usr/local/software/ ,那么 man page 搜寻的配置中,可能就得要在 /etc/man.config 内的 40~50 行左右处,写入如下的一行:
MANPATH /usr/local/software/man
⑥ 这样才可以使用 man 来查询该软件的线上文件罗!


一个简单的tarball安装范例、利用 ntp 来示范 【P790】重要!!!
对这个软件的要求是这样的:
假设 ntp-4.2.4p7.tar.gz 这个文件放置在 /root 这个目录下;
原始码请解开在 /usr/local/src 底下;
我要安装到 /usr/local/ntp 这个目录中;
那么大致的步骤是这样的:
首先,解压缩下载的 tarball ,并参阅 README/INSTALL 文件
[root@www ~]# cd /usr/local/src   <==切换目录
[root@www src]# tar -zxvf /root/ntp-4.2.4p7.tar.gz  <==解压缩到此目录
ntp-4.2.4p7/         <==会创建这个目录喔!
ntp-4.2.4p7/libopts/
....(底下省略)....
[root@www src]# cd ntp-4.2.4p7/
[root@www ntp-4.2.4p7]# vi INSTALL  <==记得 README 也要看一下!
然后,检查 configure 支持参数,并实际建置 makefile 守则档
[root@www ntp*]# ./configure --prefix=/usr/local/ntp --enable-all-clocks --enable-parse-clocks  <==开始创建makefile
注意:::--prefix 后面接的路径就是『这个软件未来要安装到那个目录去?』
最后开始编译与安装噜!
[root@www ntp*]# make clean; make
[root@www ntp*]# make check
[root@www ntp*]# make install


利用 patch 升级原始码:(一个例子) P792,也是一个重要的例子
diff:用在比对两个文件之间的差异的,并且是以行为单位来比对的
patch: 这个命令与 diff 可是有密不可分的关系,『将旧的文件升级成为新的文件』
那么当我下达『 patch -p0 < patch_file 』时,则升级的文件是『 /home/guest/example/expatch.old 』,如果『 patch -p1 < patch_file』,则升级的文件为『home/guest/example/expatch.old』,如果『patch -p4 < patch_file』则升级『expatch.old』,也就是说, -pxx 那个 xx 代表『拿掉几个斜线(/)』的意思!


函式库管理: P794
静态函式库的特色:
扩展名:(扩展名为 .a)
这类的函式库通常扩展名为 libxxx.a 的类型;
编译行为:
这类函式库在编译的时候会直接整合到运行程序当中,所以利用静态函式库编译成的文件会比较大一些喔;
独立运行的状态:
这类函式库最大的优点,就是编译成功的可运行档可以独立运行,而不需要再向外部要求读取函式库的内容 (请参照动态函式库的说明)。
升级难易度:
虽然运行档可以独立运行,但因为函式库是直接整合到运行档中, 因此若函式库升级时,整个运行档必须要重新编译才能将新版的函式库整合到程序当中。 也就是说,在升级方面,只要函式库升级了,所有将此函式库纳入的程序都需要重新编译!
动态函式库的特色: P795
扩展名:(扩展名为 .so)
这类函式库通常扩展名为 libxxx.so 的类型;
编译行为:
动态函式库与静态函式库的编译行为差异挺大的。 与静态函式库被整个捉到程序中不同的,动态函式库在编译的时候,在程序里面只有一个『指向 (Pointer)』的位置而已。也就是说,动态函式库的内容并没有被整合到运行档当中,而是当运行档要使用到函式库的机制时, 程序才会去读取函式库来使用。由於运行档当中仅具有指向动态函式库所在的指标而已, 并不包含函式库的内容,所以他的文件会比较小一点。
独立运行的状态:
这类型的函式库所编译出来的程序不能被独立运行, 因为当我们使用到函式库的机制时,程序才会去读取函式库,所以函式库文件『必须要存在』才行,而且,函式库的『所在目录也不能改变』,因为我们的可运行档里面仅有『指标』亦即当要取用该动态函式库时, 程序会主动去某个路径下读取,呵呵!所以动态函式库可不能随意移动或删除,会影响很多相依的程序软件喔!
升级难易度:
虽然这类型的运行档无法独立运行,然而由於是具有指向的功能, 所以,当函式库升级后,运行档根本不需要进行重新编译的行为,因为运行档会直接指向新的函式库文件 (前提是函式库新旧版本的档名相同喔!)。


不过,目前的 Linux distribution 比较倾向於使用动态函式库,因为如同上面提到的最重要的一点, 就是函式库的升级方便
不同版本核心提供的函式库差异性挺大的,所以 kernel 2.4.xx 版本的系统不要想将核心换成 2.6.xx 喔! 很容易由於函式库的不同而导致很多原本可以运行的软件无法顺利运行呢


ldconfig 与 /etc/ld.so.conf P796
如果我们将常用到的动态函式库先加载内存当中 (缓存, cache),如此一来,当软件要取用动态函式库时,就不需要从头由硬盘里面读出罗! 这样不就可以增进动态函式库的读取速度了嘛
如何将动态函式库加载高速缓存当中呢?
首先,我们必须要在 /etc/ld.so.conf 里面写下『 想要读入高速缓存当中的动态函式库所在的目录』,注意喔, 是目录而不是文件;
接下来则是利用 ldconfig 这个运行档将 /etc/ld.so.conf 的数据读入缓存当中;
同时也将数据记录一份在 /etc/ld.so.cache 这个文件当中呐!
ldconfig:将 /etc/ld.so.conf 的数据读入缓存当中;判断动态函式库的连结资讯
ldd: 程序的动态函式库解析,视察『相依函式库』之间的相关性,比如调用了哪些函数库啊什么的 P797

检验软件正确性 P798
每个文件都具有独特的指纹验证数据
如果你下载了 文档 后,再以 md5sum 与 sha1sum 去检验这个文件时, 文件所回传的指纹码应该要与网站上面提供的文件指纹码相同才对
文档的内容一旦不同,所产生的指纹验证也就不同了
因此,你必须要在你的 Linux 系统上为你的许多重要的文件进行指纹数据库的创建 (好像在做户口调查!),如果你可以替这些文件创建指纹数据库 (就是使用 md5sum 检查一次,将该文件指纹记录下来,然后常常以 shell script 的方式由程序自行来检查指纹表是否不同了!),那么对於文件系统会比较安全啦
















第二十三章、软件安装: RPM, SRPM 与 YUM 功能
什么是 RPM 与 SRPM: P803
RPM 全名是『 RedHat Package Manager 』简称则为 RPM 
优点是:
① 由於已经编译完成并且打包完毕,所以软件传输与安装上很方便 (不需要再重新编译);
② 由於软件的资讯都已经记录在 Linux 主机的数据库上,很方便查询、升级与反安装
缺点是:
① 由於 RPM 文件是已经包装好的数据,也就是说, 里面的数据已经都『编译完成』了!所以,该软件文件几乎只能安装在原本默认的硬件与操作系统版本中
② 软件文件安装的环境必须与打包时的环境需求一致或相当;
③ 需要满足软件的相依属性需求;
④ 安装时需要特别小心,最底层的软件不可先移除,否则可能造成整个系统的问题!
SRPM 是 Source RPM 的意思,是这个 RPM 文件里面含有的原始码,所提供的软件内容『并没有经过编译』
要安装该软件时,你就必须要:
先将该软件以 RPM 管理的方式编译,此时 SRPM 会被编译成为 RPM 文件;
然后将编译完成的 RPM 文件安装到 Linux 系统当中
优点:
可以透过修改 SRPM 内的参数配置档,然后重新编译产生能适合我们 Linux 环境的 RPM 文件,如此一来,可以将该软件安装到我们的系统当中,不必与原作者打包的 Linux 环境相同了
总的来说------------------------------------------------------------------------------------------------------------------------------------------------------------------------
文件格式 档名格式 直接安装与否 内含程序类型 可否修改参数并编译
RPM xxx.rpm 已编译 不可
SRPM xxx.src.rpm 不可 未编译之原始码
------------------------------------------------------------------------------------------------------------------------------------------------------------------------


仔细谈谈RPM
RPM 的优点: P805
RPM 内含已经编译过的程序与配置档等数据,可以让使用者免除重新编译的困扰;
RPM 在被安装之前,会先检查系统的硬盘容量、操作系统版本等,可避免文件被错误安装;
RPM 文件本身提供软件版本资讯、相依属性软件名称、软件用途说明、软件所含文件等资讯,便於了解软件;
RPM 管理的方式使用数据库记录 RPM 文件的相关参数,便於升级、移除、查询与验证。


当你要安装某个以 RPM 型态提供的软件时,在安装的过程中, RPM 会去检验一下数据库里面是否已经存在相关的软件了, 如果数据库显示不存在,那么这个 RPM 文件『默认』就不能安装,这个就是 RPM 类型的文件最为人所诟病的『软件的属性相依』问题 P806
针对这个问题,那有没有办法解决啊? 那想一想,要是我将这些相依属性的软件先列表, 在有要安装软件需求的时候,先到这个列表去找,同时与系统内已安装的软件相比较,没安装到的相依软件就一口气同时安装起来, 那不就解决了相依属性的问题了吗?那就是 YUM 机制的由来

rpm: RPM 软件管理程序的指令
-i :install 的意思 P807
-v :察看更细部的安装资讯画面
-h :以安装资讯列显示安装进度
查询已安装软件的资讯: P809
-q  :仅查询,后面接的软件名称是否有安装;
-qa :列出所有的,已经安装在本机 Linux 系统上面的所有软件名称;
-qi :列出该软件的详细资讯 (information),包含开发商、版本与说明等;
-ql :列出该软件所有的文件与目录所在完整档名 (list);
-qc :列出该软件的所有配置档 (找出在 /etc/ 底下的档名而已)
-qd :列出该软件的所有说明档 (找出与 man 有关的文件而已)
-qR :列出与该软件有关的相依软件所含的文件 (Required 的意思)
-qf :由后面接的文件名称,找出该文件属於哪一个已安装的软件;
查询某个 RPM 文件内含有的资讯:
-qp[icdlR]:注意 -qp 后面接的所有参数以上面的说明一致。但用途仅在於找出
    某个 RPM 文件内的资讯,而非已安装的软件资讯!注意!
--nodeps:当发生软件属性相依问题而无法安装,但你执意安装时 P808
--replacefiles:如果在安装的过程当中出现了『某个文件已经被安装在你的系统上面』的资讯,又或许出现版本不合的信息 (confilcting files) 时,可以使用这个参数来直接覆盖文件。
--replacepkgs:重新安装某个已经安装过的软件!如果你要安装一堆 RPM 软件文件时,可以使用 rpm -ivh *.rpm ,但若某些软件已经安装过了, 此时系统会出现『某软件已安装』的资讯,导致无法继续安装。此时可使用这个选项来重复安装喔!
--force:这个参数其实就是 --replacefiles 与 --replacepkgs 的综合体!
--test: 想要测试一下该软件是否可以被安装到使用者的 Linux 环境当中,可找出是否有属性相依的问题。
--justdb: 由於 RPM 数据库破损或者是某些缘故产生错误时,可使用这个选项来升级软件在数据库内的相关资讯。
--nosignature: 想要略过数码签章的检查时,可以使用这个选项。
--prefix 新路径: 要将软件安装到其他非正规目录时。举例来说,你想要将某软件安装到 /usr/local 而非正规的 /bin, /etc 等目录, 就可以使用『 --prefix /usr/local 』来处理了。
--noscripts:不想让该软件在安装过程中自行运行某些系统命令。
RPM 升级与升级 (upgrade/freshen) P809
-Uvh 后面接的软件即使没有安装过,则系统将予以直接安装; 若后面接的软件有安装过旧版,则系统自动升级至新版;
-Fvh 如果后面接的软件并未安装到你的 Linux 系统上,则该软件不会被安装;亦即只有已安装至你 Linux 系统内的软件会被『升级』!
(在不晓得 yum 功能的情况下,你依旧可以到 CentOS 的映设站台下载 updates 数据,然后利用上述的方法来一口气升级)


RPM 默认安装的路径 P807
/var/lib/rpm/:软件相关的资讯就会被写入该目录下的数据库文件中;未来如果我们有任何软件升级的需求,版本之间的比较就是来自於这个数据库;如果你想要查询系统已经安装的软件,也是从这里查询

想要安装一个名为 pam-devel 的软件,你手边只有原版光盘,该如何是好? P808
挂载光盘,使用: mount /dev/cdrom /media
找出文件的实际路径:find /media -name 'pam-devel*'
测试此软件是否具有相依性: rpm -ivh pam-devel... --test
直接安装: rpm -ivh pam-devel...
卸载光盘: umount /dev/cdrom


我想要知道我的系统当中,以 c 开头的软件有几个,如何实做? P811
rpm -qa | grep ^c | wc -l
我的 WWW 服务器为 Apache ,我知道他使用的 RPM 软件档名为 httpd 。现在,我想要知道这个软件的所有配置档放置在何处,可以怎么作?
rpm -qc httpd
承上题,如果查出来的配置文件已经被我改过,但是我忘记了曾经修改过哪些地方,所以想要直接重新安装一次该软件,该如何作?
假设该软件在网络上的网址为:
http://web.site.name/path/httpd-x.x.xx.i386.rpm
则我可以这样做:
rpm -ivh http://web.site.name/path/httpd-x.x.xx.i386.rpm --replacepkgs
如果我误砍了某个重要文件,例如 /etc/crontab,偏偏不晓得他属於哪一个软件,该怎么办?
虽然已经没有这个文件了,不过没有关系,因为 RPM 有记录在 /var/lib/rpm 当中的数据库啊!所以直接下达:
rpm -qf /etc/crontab
就可以知道是那个软件罗!重新安装一次该软件即可!

RPM 验证与数码签章 (Verify/signature) P811
作用的方式是『使用 /var/lib/rpm 底下的数据库内容来比对目前 Linux 系统的环境下的所有软件文件 』
依旧是rpm指令:
-V  :后面加的是软件名称,若该软件所含的文件被更动过,才会列出来;
-Va :列出目前系统上面所有可能被更动过的文件;
-Vp :后面加的是文件名称,列出该软件内可能被更动过的文件;
-Vf :列出某个文件是否被更动过~
例如:查询一下,你的 /etc/crontab 是否有被更动过?
[root@www ~]# rpm -Vf /etc/crontab
显示结果为:S.5....T  c /etc/crontab
最前面的八个资讯是:
S :(file Size differs) 文件的容量大小是否被改变
M :(Mode differs) 文件的类型或文件的属性 (rwx) 是否被改变?如是否可运行等参数已被改变
5 :(MD5 sum differs) MD5 这一种指纹码的内容已经不同
D :(Device major/minor number mis-match) 装置的主/次代码已经改变
L :(readLink(2) path mis-match) Link 路径已被改变
U :(User ownership differs) 文件的所属人已被改变
G :(Group ownership differs) 文件的所属群组已被改变
T :(mTime differs) 文件的创建时间已被改变
所以,如果当一个配置档所有的资讯都被更动过,那么他的显示就会是:
SM5DLUGT c filename
至於那个 c 代表的是『 Config file 』的意思,也就是文件的类型,文件类型有底下这几类:
c :配置档 (config file)
d :文件数据档 (documentation)
g :鬼文件~通常是该文件不被某个软件所包含,较少发生!(ghost file)
l :授权文件 (license file)
r :读我文件 (read me)
数码签章 (digital signature): P813
软件开发商原厂所推出的软件也会有一个厂商自己的签章系统! 只是这个签章被数码化了而已。厂商可以数码签章系统产生一个专属於该软件的签章,并将该签章的公钥 (public key) 释出。 当 你要安装一个 RPM 文件时:
首先你必须要先安装原厂释出的公钥文件;
实际安装原厂的 RPM 软件时, rpm 命令会去读取 RPM 文件的签章资讯,与本机系统内的签章资讯比对,
若签章相同则予以安装,若找不到相关的签章资讯时,则给予警告并且停止安装喔。
关于如何处理数码签章的详细见书上

RPM 反安装与重建数据库 (erase/rebuilddb): P814
反安装就是将软件卸载
移除的选项很简单,就透过 -e 即可移除
不过,很常发生软件属性相依导致无法移除某些软件的问题,因此需要注意各个软件之间的相依性
由於 RPM 文件常常会安装/移除/升级等,某些动作或许可能会导致 RPM 数据库 /var/lib/rpm/ 内的文件破损,那你该如何是好?
[root@www ~]# rpm --rebuilddb   <==重建数据库


SRPM 的使用 : rpmbuild P815
利用默认值安装 SRPM 文件:
--rebuild:这个选项会将后面的 SRPM 进行『编译』与『打包』的动作,最后会产生 RPM 的文件,但是产生的 RPM 文件并没有安装到系统上。当你使用 --rebuild 的时候,最后通常会发现一行字体:
Wrote: /usr/src/redhat/RPMS/i386/pkgname.i386.rpm
这个就是编译完成的 RPM 文件罗!这个文件就可以用来安装啦!安装的时候请加绝对路径来安装即可!
--recompile:这个动作会直接的『编译』『打包』并且『安装』罗!请注意, rebuild 仅『编译并打包』而已,而 recompile 不但进行编译跟打包,还同时进行『安装』了!
SRPM 使用的路径与需要的软件:
由於 SRPM 需要重新编译,而编译的过程当中,我们至少需要有 make 与其相关的程序,及 gcc, c, c++ 等其他的编译用的程序语言来进行编译


例题: 尝试使用SRPM的 --rebuild 选项制作出一个 RPM 软件文件
[root@www ~]# rpmbuild --rebuild rp-pppoe-3.5-32.1.src.rpm


配置档的主要内容 (*.spec): P817
如何查看配置档呢?我们拿rp-pppoe作为例子
[root@www ~]# rpm -i rp-pppoe-3.5-32.1.src.rpm(# 过程不会显示任何东西,他只会将 SRPM 的文件解开后,放置到 /usr/src/redhat/)
配置参数档,亦即是在 /usr/src/redhat/SPECS 内的 *.spec 文件
接下来我们来解析整个配置档:
粗看:
① 整个文件的开头以Summary为开始,这部份的配置都是最基础的说明内容;
② 然后每个不同的段落之间,都以%来做为开头,例如%prep与%install等;
细看:主要分为5个部分:
# 1. 首先,这个部分在介绍整个软件的基本相关资讯!不论是版本还是释出次数等。
# 2. 这部分则是在配置相依属性需求的地方!
# 3. 编译前的预处理,以及编译过程当中所需要进行的命令,都写在这里,尤其 %build 底下的数据,几乎就是 makefile 里面的资讯啊!
# 4. 这里列出,这个软件释出的文件有哪些的意思!
# 5. 列出这个软件的更改历史纪录档!
再细看:
%prep:尚未进行配置或安装之前,你要编译完成的 RPM帮你事先做的事情
① 进行软件的补丁 (patch) 等相关工作;
② 寻找软件所需要的目录是否已经存在?确认用的!
③ 事先创建你的软件所需要的目录,或者事先需要进行的任务;
④ 如果待安装的Linux系统内已经有安装的时候可能会被覆盖掉的文件时,那么就必需要进行备份(backup)的工作了!
%setup:这个项目就是在进行类似解压缩之类的工作!这个项目一定要写喔!不然你的 tarball 原始码是无法被解压缩的
%build:build 就是创建啊!所以当然罗,这个段落就是在谈怎么 make 编译成为可运行的程序罗! 你会发现在此部分的程序码方面,就是 ./configure, make 等项目
%files:这个软件安装的文件都需要写到这里来,当然包括了『目录』喔!所以连同目录请一起写到这个段落当中!以备查验呢!^_^ !此外,你也可以指定每个文件的类型,包括文件档 (%doc 后面接的) 与配置档 (%config 后面接的) 等等
%changelog:这个项目主要则是在记录这个软件曾经的升级纪录


SRPM 的编译命令: P821
要将在 /usr/src/redhat 底下的数据编译或者是单纯的打包成为 RPM 或 SRPM 时,就需要 rpmbuild 命令
[root@www ~]# rpmbuild -ba rp-pppoe.spec  <==编译并同时产生 RPM 与 SRPM 文件
[root@www ~]# rpmbuild -bb rp-pppoe.spec  <==仅编译成 RPM 文件
这个时候系统就会这样做:
① 先进入到 BUILD 这个目录中,亦即是: /usr/src/redhat/BUILD 这个目录;
② 依照 *.spec 文件内的 Name 与 Version 定义出工作的目录名称,以我们上面的例子为例,那么系统就会在 BUILD 目录中先删除 rp-pppoe-3.5 的目录,再重新创建一个 rp-pppoe-3.5 的目录,并进入该目录;
③ 在新建的目录里面,针对 SOURCES 目录下的来源文件,也就是 *.spec 里面的 Source 配置的那个文件,以 tar 进行解压缩,以我们这个例子来说,则会在 /usr/src/redhat/BUILD/rp-pppoe-3.5 当中,将 /usr/src/redhat/SOURCES/rp-pppoe-3.5.tar.gz 进行解压缩啦!
④ 再来开始 %build 及 %install 的配置与编译!
⑤ 最后将完成打包的文件给他放置到该放置的地方去,如果你的规定的硬件是在 i386 的系统,那么最后编译成功的 *.i386.rpm文件就会被放置在 /usr/src/redhat/RPMS/i386 里面罗!如果是 i686 那么自然就是 /usr/src/redhat/RPMS/i686 目录下罗!


一个打包自己软件的范例: P822
Step.1:制作原始码文件 tarball 产生:
主要在于建立makefile文件,最后将处理好的源码文件移至 /usr/src/redhat/SOURCES 底下
Step.2:创建 *.spec 的配置档
[root@www SPECS]# vim main.spec 必须要仔细的配置他,不要随便处理
Step.3:编译成为 RPM 与 SRPM
[root@www SPECS]# rpmbuild -ba main.spec


YUM 线上升级机制: P824
利用 yum 进行查询、安装、升级与移除功能:
查询功能:
yum:
[option]:主要的选项,包括有:
-y :当 yum 要等待使用者输入时,这个选项可以自动提供 yes 的回应;
--installroot=/some/path :将该软件安装在 /some/path 而不使用默认路径
[查询工作项目] [相关参数]:这方面的参数有:
search  :搜寻某个软件名称或者是描述 (description) 的重要关键字;
list    :列出目前 yum 所管理的所有的软件名称与版本,有点类似 rpm -qa;
info    :同上,不过有点类似 rpm -qai 的运行结果;
provides:从文件去搜寻软件!类似 rpm -qf 的功能!
利用 yum 的功能,找出以 pam 为开头的软件名称有哪些?
[root@www ~]# yum list pam*
安装/升级功能: P826
install :后面接要安装的软件!
update  :后面接要升级的软件,若要整个系统都升级,就直接 update 即可
移除功能: P827
[root@www ~]# yum remove pam-devel

yum 的配置档: P828
[root@www ~]# vi /etc/yum.repos.d/CentOS-Base.repo   先来讨论其中一个容器的配置:
[base]:代表容器的名字!中刮号一定要存在,里面的名称则可以随意取。但是不能有两个相同的容器名称, 否则 yum 会不晓得该到哪里去找容器相关软件清单文件。
name:只是说明一下这个容器的意义而已,重要性不高!
mirrorlist=:列出这个容器可以使用的映射站台,如果不想使用,可以注解到这行;
baseurl=:这个最重要,因为后面接的就是容器的实际网址! mirrorlist 是由 yum 程序自行去捉映射站台, baseurl 则是指定固定的一个容器网址!我们刚刚找到的网址放到这里来啦!
enable=1:就是让这个容器被启动。如果不想启动可以使用 enable=0 喔!
gpgcheck=1:还记得 RPM 的数码签章吗?这就是指定是否需要查阅 RPM 文件内的数码签章!
gpgkey=:就是数码签章的公钥档所在位置!使用默认值即可
可以通过修改配置档修改yum获取的资源的来源


修改容器产生的问题与解决之道: P830
可能由於使用的容器版本有新旧之分,yum 会先下载容器的清单到本机的 /var/cache/yum 里面去,我们修改了网址却没有修改容器名称 (中刮号内的文字), 可能就会造成本机的清单与 yum 服务器的清单不同步,此时就会出现无法升级的问题了
解决方法是:
[root@www ~]# yum clean [packages|headers|all] 
packages:将已下载的软件文件删除
headers :将下载的软件档头删除
all     :将所有容器数据都删除!


yum 的软件群组功能:
安装的是一个大型专案


管理的抉择:RPM 还是 Tarball P831
如果有 RPM 的话,那么优先权还是在於 RPM 安装上面,毕竟管理上比较便利,但是如果软件的架构差异性太大, 或者是无法解决相依属性的问题,那么与其花大把的时间与精力在解决属性相依的问题上,还不如直接以 tarball 来安装,轻松又惬意
优先选择原厂的 RPM 功能:
具有容易安装/移除/升级等特点,且还提供查询与验证的功能,安装时更有数码签章的保护, 让你的软件管理变的更轻松自在!因此,当然首选就是利用 RPM 来处理
选择软件官网释出的 RPM 或者是提供的容器网址:
可以修改 yum 配置档来加入该容器,就能够自动安装与升级该软件
利用 Tarball 安装特殊软件:
某些特殊用途的软件并不会特别帮你制作 RPM 文件的,这种软件建议使用 tarball 来安装即可
用 Tarball 测试新版软件:
某些时刻你可能需要使用到新版的某个软件,但是原版厂商仅提供旧版软件

重要例题:::假设我们要安装一个软件,该软件厂商提供了 yum 的安装网址为: http://their.server.name/path/ ,那你该如何处理 yum 的配置档? P834
可以自行取个档名,在此例中我们使用『 vim /etc/yum.repos.d/their.repo 』,扩展名要正确! 内容有点像这样即可:
[their]
name=their server name
baseurl=http://their.server.name/path/
enable=1
gpgcheck=0
然后使用 yum 去安装该软件看看。
















第二十五章、 Linux 备份策略
备份介绍; P860
推荐需要备份的目录: P863
/boot
/etc
/home
/root
/usr/local(或者是 /opt 及 /srv 等)
/var(注:这个目录当中有些缓存目录则可以不备份!)


备份的种类:
完整备份之累积备份 (Incremental backup): P865
指的是在系统在进行完第一次完整备份后,经过一段时间的运行, 比较系统与备份档之间的差异,仅备份有差异的文件而已。而第二次累积备份则与第一次累积备份的数据比较, 也是仅备份有差异的数据而已
那如何还原?
假设你的系统在星期五的时候挂点了!那你要如何还原?首先,你必须要还原星期一的完整备份,然后还原星期二的累积备份, 再依序还原星期三、星期四的累积备份才算完全复原!那如果你是经过了九次的累积备份,就得要还原到第九次的阶段, 才是最完整的还原程序


累积备份使用的备份软件:
完整备份常用的工具有 dd, cpio, dump/restore 等等

完整备份之差异备份 (Differential backup): P867
差异备份指的是:每次的备份都是与原始的完整备份比较的结果。所以系统运行的越久,离完整备份时间越长, 那么该次的差异备份数据可能就会越大!
差异备份的还原较快, 因为只需要还原完整备份与最近一次的差异备份即可

差异备份使用的备份软件:
rsync、dump


鸟哥的备份策略:
主机硬件:使用一个独立的 filesystem 来储存备份数据,此 filesystem 挂载到 /backup 当中;
每日进行:目前仅备份 MySQL 数据库;
每周进行:包括 /home, /var, /etc, /boot, /usr/local 等目录与特殊服务的目录;
自动处理:这方面利用 /etc/crontab 来自动提供备份的进行;
异地备援:每月定期的将数据分别 (a)烧录到光盘上面 (b)使用网络传输到另一部机器上面。
周备份::: P868
#!/bin/bash
# ====================================================================
# 使用者参数输入位置:
# basedir=你用来储存此脚本所预计备份的数据之目录(请独立文件系统)
basedir=/backup/weekly  <==您只要改这里就好了!


# ====================================================================
# 底下请不要修改了!用默认值即可!
PATH=/bin:/usr/bin:/sbin:/usr/sbin; export PATH
export LANG=C


# 配置要备份的服务的配置档,以及备份的目录
named=$basedir/named
postfixd=$basedir/postfix
vsftpd=$basedir/vsftp
sshd=$basedir/ssh
sambad=$basedir/samba
wwwd=$basedir/www
others=$basedir/others
userinfod=$basedir/userinfo
# 判断目录是否存在,若不存在则予以创建。
for dirs in $named $postfixd $vsftpd $sshd $sambad $wwwd $others $userinfod
do
[ ! -d "$dirs" ] && mkdir -p $dirs
done


# 1. 将系统主要的服务之配置档分别备份下来,同时也备份 /etc 全部。
cp -a /var/named/chroot/{etc,var} $named
cp -a /etc/postfix /etc/dovecot.conf $postfixd
cp -a /etc/vsftpd/* $vsftpd
cp -a /etc/ssh/* $sshd
cp -a /etc/samba/* $sambad
cp -a /etc/{my.cnf,php.ini,httpd} $wwwd
cd /var/lib
 tar -jpc -f $wwwd/mysql.tar.bz2 mysql
cd /var/www
 tar -jpc -f $wwwd/html.tar.bz2 html cgi-bin
cd /
 tar -jpc -f $others/etc.tar.bz2 etc
cd /usr/
  tar -jpc -f $others/local.tar.bz2 local


# 2. 关於使用者参数方面
cp -a /etc/{passwd,shadow,group} $userinfod
cd /var/spool
 tar -jpc -f $userinfod/mail.tar.bz2 mail
cd /
 tar -jpc -f $userinfod/home.tar.bz2 home
cd /var/spool
 tar -jpc -f $userinfod/cron.tar.bz2 cron at


日备份::: P870
#!/bin/bash
# =========================================================
# 请输入,你想让备份数据放置到那个独立的目录去
basedir=/backup/daily/  <==你只要改这里就可以了!


# =========================================================
PATH=/bin:/usr/bin:/sbin:/usr/sbin; export PATH
export LANG=C
basefile1=$basedir/mysql.$(date +%Y-%m-%d).tar.bz2
basefile2=$basedir/cgi-bin.$(date +%Y-%m-%d).tar.bz2
[ ! -d "$basedir" ] && mkdir $basedir


# 1. MysQL (数据库目录在 /var/lib/mysql)
cd /var/lib
 tar -jpc -f $basefile1 mysql


# 2. WWW 的 CGI 程序 (如果有使用 CGI 程序的话)
cd /var/www
 tar -jpc -f $basefile2 cgi-bin

加入排程:::
[root@www ~]# vi /etc/crontab
# 加入这两行即可 (请注意你的文件目录!不要照抄呦!)
30 3 * * 0 root /backup/backupwk.sh
30 2 * * * root /backup/backupday.sh


















第二十六章、Linux 核心编译与管理
什么是核心 (Kernel) P893
核心就是系统上面的一个文件而已, 这个文件包含了驱动主机各项硬件的侦测程序与驱动模块。
当系统读完 BIOS 并加载 MBR 内的启动管理程序后,就能够加载核心到内存当中。然后核心开始侦测硬件, 挂载根目录并取得核心模块来驱动所有的硬件,之后呼叫 /sbin/init 就能够依序启动所有系统所需要的服务了
(一部主机上面可以拥有多个核心文件,只是启动的时候仅能选择一个来加载而已)
核心模块 (kernel module) P894
将一些不常用的类似驱动程序的咚咚独立出核心,编译成为模块,然后, 核心可以在系统正常运行的过程当中加载这个模块到核心的支持
放在 /lib/modules/$(uname -r)/kernel/ 中


升级核心的目的: P895
① 新功能的需求:
新的功能只有在新的核心里面才有,那么为了获得这个功能,只好来重新编译我的核心了
② 原本核心太过臃肿:
③ 与硬件搭配的稳定性:
核心也可能没有正确的驱动新的硬件,此时就得重新编译核心来让系统取得正确的模块才好。 
④ 其他需求 (如嵌入式系统):
就是你需要特殊的环境需求时,就得自行设计你的核心


取得最新的稳定版核心原始码:
核心官网:http://www.kernel.org/
交大资科:ftp://linux.cis.nctu.edu.tw/kernel/linux/kernel/
国高中心:ftp://ftp.twaren.net/pub/Unix/Kernel/linux/kernel/


保留原本配置:利用 patch 升级核心原始码 P897
如果你想要升级 2.6.30 的修改版本到 2.6.30.3 时,由於修改版本是针对 2.6.30 来制作的, 因此你只要下载 patch-2.6.30.3 来直接将 2.6.30 升级至 2.6.30.3 即可。但反过来说,如果你要从 2.6.30.2 升级到 2.6.30.3 呢?很抱歉的是,并没有 2.6.30.2 到 2.6.30.3 的补丁文件,所以你必须要将 2.6.30.2 还原至 2.6.30, 然后才能使用 patch-2.6.30.3 来升级 2.6.30 喔!注意这个差异!


核心原始码的解压缩/安装/观察: P898
下载原始码压缩包后。
核心原始码的解压缩与放置目录:
2.6.x 核心原始码一般建议放置於 /usr/src/kernels/ 目录底下,因此
[root@www ~]# tar -jxvf linux-2.6.30.3.tar.bz2 -C /usr/src/kernels/
核心原始码下的次目录:
arch :与硬件平台有关的项目,大部分指的是 CPU 的类别,例如 x86, x86_64, Xen 虚拟支持等;
block :与区块装置较相关的配置数据,区块数据通常指的是大量储存媒体!还包括类似 ext3 等文件系统的支持是否允许等。
crypto :核心所支持的加密的技术,例如 md5 或者是 des 等等;
Documentation :与核心有关的一堆说明文件,若对核心有极大的兴趣,要瞧瞧这里!
drivers :一些硬件的驱动程序,例如显卡、网络卡、PCI 相关硬件等等;
firmware :一些旧式硬件的微命令码 (韧体) 数据;
fs :核心所支持的 filesystems ,例如 vfat, reiserfs, nfs 等等;
include :一些可让其他程序呼叫的标头 (header) 定义数据;
init :一些核心初始化的定义功能,包括挂载与 init 程序的呼叫等;
ipc :定义 Linux 操作系统内各程序的沟通;
kernel :定义核心的程序、核心状态、运行绪、程序的排程 (schedule)、程序的讯号 (signle) 等
lib :一些函式库;
mm :与内存单元有关的各项数据,包括 swap 与虚拟内存等;
net :与网络有关的各项协议数据,还有防火墙模块 (net/ipv4/netfilter/*) 等等;
security :包括 selinux 等在内的安全性配置;
sound :与音效有关的各项模块;
virt :与虚拟化机器有关的资讯,目前核心支持的是 KVM (Kernel base Virtual Machine)


核心编译的前处理与核心功能选择:
保持干净原始码:       make mrproper :这个动作会将你以前进行过的核心功能选择文件也删除掉 P899
或者 make clean:仅 会删除类似目标档之类的编译过程产生的中间文件,而不会删除配置档!
开始挑选核心功能:(以下几种选择)
make menuconfig
最常使用的,是文字模式底下可以显示类似图形介面的方式,不需要启动 X Window 就能够挑选核心功能菜单!
make oldconfig
透过使用已存在的 ./.config 文件内容,使用该文件内的配置值为默认值,只将新版本核心内的新功能选项列出让使用者选择, 可以简化核心功能的挑选过程!对於作为升级核心原始码后的功能挑选来说,是非常好用的一个项目!
make xconfig
透过以 Qt 为图形介面基础功能的图形化介面显示,需要具有 X window 的支持。例如 KDE 就是透过 Qt 来设计的 X Window,因此你如果在 KDE 画面中,可以使用此一项目。
make gconfig
透过以 Gtk 为图形介面基础功能的图形化介面显示,需要具有 X window 的支持。例如 GNOME 就是透过 Gtk 来设计的 X Window,因此你如果在 GNOME 画面中,可以使用此一项目。
make config
最旧式的功能挑选方法,每个项目都以条列式一条一条的列出让你选择,如果配置错误只能够再次选择,很不人性化啊!


建议:
『肯定』核心一定要的功能,直接编译进核心内;
『可能在未来会用到』的功能,那么尽量编译成为模块;
『不知道那个东西要干嘛的,看 help 也看不懂』的话,那么就保留默认值,或者将他编译成为模块;


核心功能细项选择:(内容太多,真正要处理的时候再看) P900 - P914


核心的编译与安装: P914
基本功能:
① [root@www linux-2.6.30.3]# make vmlinux  <==未经压缩的核心
② [root@www linux-2.6.30.3]# make modules  <==仅核心模块
③ [root@www linux-2.6.30.3]# make bzImage  <==经压缩过的核心(默认)
④ [root@www linux-2.6.30.3]# make all      <==进行上述的三个动作
基本上我们会进行的动作是:
[root@www linux-2.6.30.3]# make clean    <==先清除缓存档
[root@www linux-2.6.30.3]# make bzImage  <==先编译核心
[root@www linux-2.6.30.3]# make modules  <==再编译模块
最后注意到,下达了 make bzImage 后:
Root device is (8, 1)
Setup is 12696 bytes (padded to 12800 bytes).
System is 2207 kB
CRC 7701ab0e
Kernel: arch/x86/boot/bzImage is ready  (#1)
[root@www linux-2.6.30.3]# ll arch/x86/boot/bzImage
-rw-r--r-- 1 root root 2272432  7月 30 13:35 arch/x86/boot/bzImage


实际安装模块: P915
我们知道模块是放置到 /lib/modules/$(uname -r) 目录下的,那如果同一个版本的模块被反覆编译后来安装时,会不会产生冲突呢?
有两个解决方法啦:
第一种:先将旧的模块目录更名,然后才安装核心模块到目标目录去;
第二种:在 make menuconfig 时,那个 General setup 内的 Local version 修改成新的名称。
建议使用第二个方式,因为如此一来,你的模块放置的目录名称就不会相同,这样也就能略过上述的目录同名问题罗! 好,那么如何安装模块到正确的目标目录呢?很简单,同样使用 make 的功能即可:
[root@www linux-2.6.30.3]# make modules_install
[root@www linux-2.6.30.3]# ll /lib/modules/
drwxr-xr-x 3 root root 4096  7月 30 14:31 2.6.30.3vbird


开始安装新核心与多重核心菜单 (grub):
移动核心到 /boot 且保留旧核心文件
[root@www ~]# cp /usr/src/kernels/linux-2.6.30.3/arch/x86/boot/bzImage /boot/vmlinuz-2.6.30.3vbird  <==实际核心
[root@www ~]# cp /usr/src/kernels/linux-2.6.30.3/.config /boot/config-2.6.30.3vbird   <==建议配置档也复制备份
创建相对应的 Initial Ram Disk (initrd)
[root@www ~]# mkinitrd -v /boot/initrd-2.6.30.3vbird.img  2.6.30.3vbird
编辑启动菜单 (grub)


额外(单一)核心模块编译: P917
① 如果 Linux 核心原始码并没有某个硬件的驱动程序 (module) ,但是开发该硬件的厂商有提供给 Linux 使用的驱动程序原始码,那么我又该如何将该项功能编进核心模块呢?
你可以将他下载后,假设这个文件放置到 /root ,那么直接将他解压缩吧! 之后就可以读一读 INSTALL/README ,然后找一下 Makefile ,就能够编译了

② 如果我的默认核心忘记加入某个功能,而且该功能可以编译成为模块,不过, 默认核心却也没有将该项功能编译成为模块,害我不能使用时,该如何是好?
利用旧有的核心原始码进行编译


总结:
简单说明核心编译的步骤为何? P919
先下载核心原始码,可以从 http://www.kernel.org 或者是 distributions 的 SRPM 来著手;
以下以 Tarball 来处理,解开原始码到 /usr/src/kernels 目录下;
先进行旧数据删除的动作:『make mrproper』;
开始挑选核心功能,可以利用『make menuconfig』、『make oldconfig』、『make gconfig』等等;
清除过去的中间缓存档数据:『make clean』
开始核心文件与核心模块的编译:『make bzImage』、『make modules』
开始核心模块的安装:『make modules_install』
开始核心文件的安装,可以使用的方式有:『make install』或者是透过手动的方式复制核心文件到 /boot/grub 当中;
创建 initrd 文件;
修改 /boot/grub/menu.lst 文件;


如果你利用新编译的核心来操作系统,发现系统并不稳定,你想要移除这个自行编译的核心该如何处理?
首先,可以将原始码删除:rm -rf /usr/src/kernels/linux-2.6.30
再者,删除掉核心模块的目录: rm -rf /lib/modules/2.6.30
最后删除掉 /boot/ 内的核心文件与 initrd 文件,以及 /boot/grub/menu.lst 内的 title 配置即可。














































如何在linux下看windows里的文件呢?
Linux显示在Windows编辑过的中文就会显示乱码是由于两个操作系统使用的编码不同所致。Linux下使用的编码是utf8,而Windows使用的是gb18030。因此,解决Linux打开txt文件中文乱码可有如下两种方法。
 
  方法一:
 
  在附件终端中,进入到txt文件所在目录,使用命令符“iconv -f gb18030  -t utf8 1.txt -o 2.txt”把gb18030编码的1.txt转换成utf8的2.txt。这样2.txt就成为Linux支持的编码。
 
  方法二:
 
  在附件终端中,使用命令符“gconf-editor”,进入环境配置,依次展开“/apps/gedit-2/preferences/encodings/”,编辑右侧的“auto_detected”将“gb18030”添加到最顶上。以后文本编辑器就可以正常显示中文了。










如何在linux中的firefox里安装flash插件呢?
http://bbs.chinaunix.net/thread-2330017-1-1.html
读取另一个系统文件:
CentOS/RHEL 5 :
rpm -Uvh http://dl.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.rpm


CentOS/RHEL 6 :
rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm












如何安装vmware tools 并且使其全屏?
(1)打开linux的cdrom看是否有VMware Tools 的文件,如果有则说明“install VMware tools”成功了
(2)挂载cdrom到/mnt/cdrom目录下,具体命令为:mkdir /mnt/cdrom
mount  /dev/cdrom /mnt/cdrom  www.2cto.com  
(3)解压cdrom中的文件: tar zxpf /mnt/cdrom/VMwareTools-- .tar.gz
(4)进入tmp目录找到解压后的文件夹并进入:cd vmware-tools-distrib
(5)执行命令:./vmware-install.pl
然后根据系统提示,选择相关的选项即可。大概5分钟左右即可加载成功。
 
加载成功之后还须执行以下命令:
/etc/init.d/network stop
rmmod vmxnet
modprobe vmxnet
/etc/init.d/network start
一切操作做完后重启系统即可:reboot
下次开机即可看到自己的linux系统可以全屏了












为什么 root 无法以 telnet 直接登陆系统,但是却能够使用 ssh 直接登陆?
一般来说, telnet 会引用 login 的 PAM 模块,而 login 的验证阶段会有 /etc/securetty 的限制! 由于远程联机属于 pts/n (n 为数字) 的动态终端机接口装置名称,并没有写入到 /etc/securetty , 因此 root 无法以 telnet 登陆远程主机。至于 ssh 使用的是 /etc/pam.d/sshd 这个模块, 你可以查阅一下该模块,由于该模块的验证阶段并没有加入 pam_securetty ,因此就没有 /etc/securetty 的限制!故可以从远程直接联机到服务器端。












如果我想要暂时使一个帐号不能登录主机,怎么操作?
有3种方法:
㈠ 将 /etc/passwd 的 shell 字段写成 /sbin/nologin ,即可让该账号暂时无法登陆主机;
㈡ 将 /etc/shadow 内的口令字段,添加一个 * 号在最前面,这样该账号亦无法登陆!
㈢ 将 /etc/shadow 的第八个字段关于账号取消日期的那个,配置小于目前日期的数字,那么他就无法登陆系统了!

















Linux下彻底关闭某个RAID磁盘阵列  :(鸟哥书上的并不全面,会导致一些partition以后无法使用)


1、umount卸载RAID设备
[root@yufei ~]# umount /dev/md5
2、停止RAID设备
[root@yufei ~]# mdadm -S /dev/md5
mdadm: stopped /dev/md5
这里顺便给大家讲一下设备停止后如何开启,算是插曲啊。
 
[root@yufei ~]# mdadm -A -s /dev/md5
mdadm: /dev/md5 has been started with 3 drives and 1 spare.
在停止前,你要用再查看一下RAID里面的硬盘信息,因为后面会用到这个,很关键哦!
 
[root@yufei ~]# mdadm -D /dev/md5
    Number   Major   Minor   RaidDevice State
       3       8       64        0      active sync   /dev/sde
       1       8       32        1      active sync   /dev/sdc
       4       8       48        2      active sync   /dev/sdd
 
       5       8       80        -      spare   /dev/sdf
OK,现在再停止一次
 
[root@yufei ~]# mdadm -S /dev/md5
mdadm: stopped /dev/md5
3、移除RAID里面的磁盘(这是关键的一步,而很多教程上都没有写)
 
删除RAID里面的所有磁盘
 
这一步,一定要把RAID停止后才能执行,否则会出现下面的错误提示
 
mdadm: Couldn’t open /dev/sde for write – not zeroing
 
[root@yufei ~]# mdadm --misc --zero-superblock /dev/sde
[root@yufei ~]# mdadm --misc --zero-superblock /dev/sdc
[root@yufei ~]# mdadm --misc --zero-superblock /dev/sdd
[root@yufei ~]# mdadm --misc --zero-superblock /dev/sdf
OK,这时候就把RAID里面的所有磁盘删除掉了。
 
4、删除相关配置文件里面的RAID信息
[root@yufei ~]# vim /etc/mdadm.conf
把我们增加的这一行删除
 
ARRAY /dev/md5 metadata=1.2 spares=1 name=yufei:5 UUID=69443d97:7e32415d:7f3843c5:4d5015cf
[root@yufei ~]# vim /etc/fstab
把我们增加的这一行删除
/dev/md5                /mnt                    ext4    defaults        0 0
经过这四步就完全删除RIAD了。重新启动,也不会有raid的相关内容了。










一些输入输出:
stdin(0): keyboard  键盘输入,并返回在前端 
stdout(1): monitor  正确返回值 输出到前端 
stderr(2): monitor 错误返回值 输出到前端 
>和>>都是重定向输出
1> 指标准信息输出路径(也就是默认的输出方式)
2> 指错误信息输出路径
2>&1 指将标准信息输出路径指定为错误信息输出路径(也就是都输出在一起)








在bash下用cat显示二进制文件后会出现乱码,整个终端显示包括shell提示符都是乱码,这个跟语言环境无关。


恢复的话,大致有以下几种方法:
方法一:盲打输入echo -e '\xf'并回车。与这个命令相对的是echo -e '\xe',在正常状态下输入此命令会把终端搞出乱码来。这两个命令的具体含义,尤其是十六进制的f和e分别代表什么还真不知道。
方法二:按Ctrl+V之后接着按Ctrl+O回车。
方法三:如果是xterm终端窗口,还可以可以盲打输入reset后回车,把终端重新初始化。这种方法在使用SecureCRT等工具telnet到服务器端的情况下不适用。








  文件比较运算符
  -e filename 如果 filename 存在,则为真 [ -e /var/log/syslog ]
  -d filename 如果 filename 为目录,则为真 [ -d /tmp/mydir ]
  -f filename 如果 filename 为常规文件,则为真 [ -f /usr/bin/grep ]
  -L filename 如果 filename 为符号链接,则为真 [ -L /usr/bin/grep ]
  -r filename 如果 filename 可读,则为真 [ -r /var/log/syslog ]
  -w filename 如果 filename 可写,则为真 [ -w /var/mytmp.txt ]
  -x filename 如果 filename 可执行,则为真 [ -L /usr/bin/grep ]
  filename1 -nt filename2 如果 filename1 比 filename2 新,则为真 [ /tmp/install/etc/services -nt /etc/services ]
  filename1 -ot filename2 如果 filename1 比 filename2 旧,则为真 [ /boot/bzImage -ot arch/i386/boot/bzImage ]
  字符串比较运算符 (请注意引号的使用,这是防止空格扰乱代码的好方法)
  -z string 如果 string 长度为零,则为真 [ -z $myvar ]
  -n string 如果 string 长度非零,则为真 [ -n $myvar ]
  string1 = string2 如果 string1 与 string2 相同,则为真 [ $myvar = one two three ]
  string1 != string2 如果 string1 与 string2 不同,则为真 [ $myvar != one two three ]

你可能感兴趣的:(鸟哥私房菜)