开机流程:
1、读BIOS,加载 CMOS 的信息,进行硬件的检测,硬件驱动等等,通过 MBR(MBR.png,有每个系统的启动扇区)加载系统内核(/boot 文件)。
2、内核执行init 程序,而 init 会取得 run-level 信息。
3、init 执行/etc/rc.d/rc.sysinit 准备软件执行环境,如网络,时区等。
4、init 执行run-level 的各个服务启动
5、init 执行 /etc/rc.d/rc.local 档案 (凡是需要随系统自动启动的服务、就可以都塞到/etc/rc.d/rc.local)
6、init 执行终端机的 login 程序,最后就等待用户登入
附: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 (重新启动)
不要把设置为 0,4,6 不然就是关机,重启。
保存在 /etc/inittab 文件中,格式:
id:3:initdefault:
login shell 和 no login shell
1、login shell 要登录
2、no-login shell 没有用户登录(使用x-window 时常见)
3、在登录下再运行bash 时,就进入到一个子进程,这时也是no login shell,执行exit 退出到父进程。
示例:在~/.bashrc 添加 export test='test', 运行bash 后,可以看到设置了这个环境变量。
这两种取得bash,读取的配置文件不一致:
login shell:
1、/etc/profile
2、~/.bash_profile 或者 ~/.bash_login 或者 ~/.profile 只会读聚上面三个其中的一个,而读取的顺序则是依照上面的顺序。个人的相关配置就可以写在这时。
no login shell:
仅会读取: ~/.bashrc
指令搜索顺序
1、以相对或者绝对路径执行。如 ./shell.sh /home/jamin/bin/xxx.sh
2、别名; 如:ll 命令
3、bash 内建的指令
4、PATH
附:type 命令可以查看命令是什么命令。
[jamin@localhost ~]$ type ll
ll is aliased to `ls -l --color=auto'
file:表示外部命令,alias:为命令别名所设置的名称,builtin:为bash内置命令
内建命令,外部命令
当执行外部命令时,会创建出一个子进程。内建命令不需要用子进程来执行(已经和shell 编译在一起了,不需要外部程序文件来运行)。
注:
1、type 可以查看命令是内建命令,还是外部命令。
2、命令有多种实现方式。请用type -a 查看。如:
[jamin@localhost ~]$ type -a echo
echo is a shell builtin
echo is /bin/echo
如果要使用外部命令,直接用全路径即可
2、which 只显示外部命令
执行shell 方式
1、source
2、./test.sh /home/jamin/test.sh
3、sh xx.sh
第 2,3 两种方法是一致的,执行时会在当前进程下创建一个子进程执行,执行完成后不退出父进程,对父进程的环境不会有影响。
第1 种方法是在当前进程中进行的。对父进程环境有影响。
示例:test.sh
#!/bin/bash
test='test'
echo test
export test
使用第一种方式执行后,在当前进程下多了一个环境变量 test ,使用第2,3 种方式执行时,就没有,因为环境变量(一般变量)只会从父进程传到子进程,不会从子进程传到父进程。
注:启动时用户默认的shell 是放在在/etc/passwd 文件中的
变量定义
示例:$test="test"
1、变量名和值用等号连接,等号两边不能有空格
2、值有空格,要用'' 或者 ""
'' 内的特殊字符为一般文本,如:echo '$PATH' 打印:$PATH
"" 内的特殊字符为原有的属性。如: echo "$PATH" 打印 PATH 属性的值
3、可以使用转义字符(\) ,可以把 空格、Enter、$、\ 变成一般字符。test="a b" 可以写成test=a\ b
4、`` 或者 $() 由内部指令提供信息。
$test=`cat /etc/passwd`
5、使用变量成为环境变量:
$export test
6、取消变量
$unset test
declare 定义变量
示例:declare -i sum
-a :将后面名variable 定义为数组(array)类型
-i : 定义为整数数字(integer)类型
-x :用法与export一样,将后面的变量编程环境变量。+x 取消环境变量
-r :将变量设置成 readonly类型,也不能unset
shell 编写
test,[ ] , [[ ]],(())判断
文件
示例:test -e file_name
-e 文件是否存在
-f 文件存在且为文件
-d 文件存在且为目录
数值
test n1 -eq n2
-eq equal
-ne not equal
-gt great than
-lt less than
-ge great than or equal
-le less than or equal
字符串
test -z str 字符串是否为0,如果是空串(未定义,或者是"")返回true
test -n str 字符串是否为非0
test str1 = str2 相等
test str1 != str2 不相等
多重判断
-a and 示例: test -z str1 -a str1 = str2
-o or
! 非
双方括号;处理正则匹配的
示例:值以a 开始
$ [[ "abc" == a* ]] && echo 'y'
y
双括号 (()) 参考:
if...then
示例:经常在执行脚本的时候会有让输入 y/n,输入y 继续执行,输入n 终止。
#!/bin/bash
read -p "plase input y/n :" yn
if [ "$yn" == "Y" -o "$yn" == "y" ];then
echo "continue"
elif [ "$yn" == "N" -o "$yn" == "n" ];then
echo "termination"
else
echo "param is error"
fi
注意:
1、[ ] 符号和里面内容之间要有空格
2、"$yn" 变量要使用双引号,处理变量有空格的问题
3、then 可以换行,换行后 ; 可以不用写
4、#!/bin/bash 指定使用那一个shell,类似执行:/bin/bash ./sh01.sh(有默认的shell)
case....esac
示例:在执行脚本时可以遇到参数是start,stop,restart 的服务启动脚本。
[jamin@localhost ~]$ cat case.sh
#!/bin/bash
c=$1
case $c in
"start")
echo "start serve"
;;
"stop")
echo "stop serve"
;;
"restart")
echo "restart serve"
;;
*)
echo "Usage $0 {start|stop|restart}"
;;
esac
function
示例:把上面的case 转化成function 调用
#!/bin/bash
c=$1
function start(){
#这个 $1 和上面那个$1 不是一个东西,这个$1 是调用这个function 传递的参数
echo $1
}
function stop(){
echo "stop serve"
}
function restart(){
echo "restart serve"
}
case $c in
"start")
start "start serve"
;;
"stop")
stop
;;
"restart")
restart
;;
*)
echo "Usage $0 {start|stop|restart}"
;;
esac
函数总结:
1、必须在调用函数地方之前,声明函数,shell脚本是逐行运行。
2、可以带function function_name(){} 定义,也可以直接function_name(){} 定义,不带任何参数。
3、参数返回(函数执行返回的状态码),可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值(每一个命令执行完成后都有一个返回值0 表示成功)。 return后跟数值n(0-255,如果超出255,会减去256 的位数,返回值一定小于256)
4、函数返回值,只能通过$? 系统变量获得。查看下面示例
#!/bin/bash
sum(){
return $(($1+$2))
}
total=$(sum 1 2)
echo $?
echo $total
total 是没有值的,? 是3
5、定义函数可以与系统命令相同,说明shell搜索命令时候,首先会在当前的shell文件定义好的地方查找,找到直接执行。
6、如果需要传出其它类型函数值,可以在函数调用之前,定义变量(这个就是全局变量)。在函数内部就可以直接修改,然后在执行函数就可以读出修改过的值。
7、函数定义的变量默认是global的,如果需要定义自己变量,可以在函数中定义:local 变量=值 ,这时变量就是内部变量,它的修改,不会影响函数外部相同变量的值 。
示例:
while循环:
while [条件]
do
###
done
条件成立时执行,不成立时跳出循环。
示例:计算1...10 的数值的和
#!/bin/bash
declare -i n=1
declare -i sum=0
while [ $n -le 10 ]
do
sum=$(($sum+$n))
n=$n+1
done
echo 'sum:' $sum
#!/bin/bash
declare l="a"
declare -i n=100
fun(){
local l="bbbb"
g='ggggg'
n=n+1
}
fun
echo $l
echo $n
echo $g
结果:
a
102
ggggg
until循环:当条件不成立时执行,刚好和while 相反
until [ 条件 ]
do
###
done
示例:计算1...10 的数值的和
#!/bin/bash
declare -i n=1
declare -i sum=0
until [ $n -gt 10 ]
do
sum=$(($sum+$n))
n=$n+1
done
echo 'sum:' $sum
注意:while 是 -le(<=) until 是 -gt (>)
for 固定循环
for var in c1 c2 c3
do
###
done
示例:计算1...10 的和
#!/bin/bash
declare -i n=1
declare -i sum=0
for n in `seq 1 10`
do
sum=$(($sum+$n))
done
echo "sum:" $sum
注:
1、file_list=`ls /home/jamin` 也可以用到for 循环中。
2、while until for 中使用 break continue 控制循环。
示例:如上面的for 循环中如果数字是5,就不加入到和中:
if [ $n -eq 5 ];then
echo '5 is skiped'
continue
fi
break n n默认为1,为当前循环。
跳出外部循环
示例
for n in list
do
for i in list1
do
if ...;then
break 2 # 跳出外部循环
fi
done
done
continue 和break 类似,通过指定n 确定继续执行哪一级的循环
3、可以把循环的输出重定向到文件。
示例(for,其它循环也适用):把for 循环内的输出内容重定向到文件
n=1
sum=0
for n in `seq 1 10`
do
echo "num is $n"
if [ $n -eq 5 ];then
echo '5 is skip'
continue
fi
sum=$(($sum+$n))
done > ./loop.log
echo "sum:" $sum
for 遍历变量
特殊字符处理:要用引号、双引号、转义字符\ 进行转义
for var in "this's" test
do
echo $var
down
for var in this\'s test
....
....
注意:for 不会把一个值两边的 " 当成值的一部分
设置分割符
是按照环境变量IFS的值分割的,IFS默认值为:空格|制表符|换行符
可以设置IFS 变量,修改默认分割符。
示例遍历文件
last 命令输出内容如下(只取了一行):
jamin pts/0 192.168.28.1 Mon May 15 12:25 still logged in
...
...如果用for 来遍历last 的标准输出文件
#!/bin/bash
list=`last`
for n in $list
do
echo $n
done
输出为每一行按照按照空格分割后的每一个值。如下:
jamin
pts/0
192.168.28.1
Mon
May
15
12:25
still
logged
in
....
如果要按照行输出,就要修改IFS 的值:
示例:一行一行遍历last 的标准输出:#!/bin/bash
list=`last`
IFS=$'\n'
for n in $list
do
echo $n
done
注意:在使用过程中,可能在一个地方设置了IFS 变量,在别的地方要忽略这个设置。一般用法如下:
IFS.OLD=$IFS
IFS=$'\n':;" #比如说,设置了 换行 : ; " 4个为分割符
#使用新的IFS,使用完后,要设置成原来的IFS变量
IFS=$IFS.OLD
shell 的跟踪和debug
$sh [-nvx] xx.sh
-n :不要执行 script,仅显示语法的问题;
-v :再执行 sccript 前,先将 scripts 的所有内容输出到屏幕上;
-x :将使用到的 script 内容显示到屏幕上!
包管理方式:rpm srpm yum。这里只介绍rpm
系统代表 软件管理 使用命令 在线升级
red hat rpm rpm ,rpmbuild yum
ubuntu dpkg dpkg apt(apt-get)
rpm: 即red hat package manager
把要装的软件先编译,并且打包成RPM 机制的包装档案,通过这个包装档案里面的数据库记录,记录这个包装档案安装时必要的软件属性。当安装这个档案时,RPM 会先按照档案的数据库记录查询Linux 主机是否具备相应的依赖软件。安装后,把此档案的信息写入Linux RPM 的数据库中,以便将来的查询、验证、更新等等。(如 maven)
问题:
1、rpm 安装的环境必须要和编译打包的环境一致或者相当。(主要是cpu 和 依赖的软件)
2、软件环境需要满足rpm 安装的依赖
3、反安装时,最底层的软件不可移除
SRPM:
由于上面的问题,就要使用rpm 包的源码,即SRPM ,即 source rpm,RPM 包的源码,通常是xx.src.rpm 命名。
源码包中也包含了该软件所依赖的软件信息及所有rpm包的数据,同时也提供了参数配置文件(configure 和 makefile)。
可以通过修改参数配置文件,编译生成适合我们机器环境的rpm包。
安装SRPM 步骤:
1、先将该软件以rpm 管理的方式编译,生成rpm 档案
2、然后使用编译生成的rpm 包进行安装
注:rpm 包命名:mysql-community-client-5.7.18-1.el6.x86_64.rpm 包括 软件名,版本,打包信息,适用cpu
rpm 优点:
1、RPM 内含已经编译过的程序与配置文件等数据,可以让用户克除重新编译的困扰;
2、RPM 在被安装之前,会先检查系统的硬盘容量、操作系统版本等,可避克档案被错误的安装;
3、RPM 档案本身提供软件版本信息、相依属性软件名称、软件用途说明、软件所含档案等信息,便于了解软件;
4、RPM 管理的方式使用数据库记录 RPM 档案的相关参数,便于升级、移除、查询与验证。
为了解决RPM 软件依赖的关系,在打包时就把软件信息一起打包如软件的版本、依赖的软件、档案记录等。在Linux 上也建立一个rpm 数据库记录机器上安装的rpm 软件信息。如此在安装rpm 时,rpm 会去检查是否已经安装了相关依赖的软件。yum就是克服rpm 软件相互依赖的工具。
yum
centos 将打包的rpm 放到yum 服务器,然后分析rpm 依赖性问题并且将软件信息记录下来(就是软件的head信息),并生成rpm 的依赖列表。
当使用yum 安装时,yum 先把到服务器上下载依赖清单列表,并和本地已经安装的相比较,如果没有安装则yum 直接安装别的依赖。
当客户端有安装、更新的需求时, yum 会向服务器要求清单的更新,等到清单更新到本机的 /var/cache/yum 里面后, 等一下更新时
就会用这个清单与本机的 RPM 数据库进行比较,这样就知道该下载什么软件。接下来 yum 会跑到容器朋务器 (yum server) 下载所需要的软件,然后再透过 RPM 的机制开始安装。
rpm 命令:
rpm -ivh xxx.rpm
-i :install 的意思
-v :察看安装信息
-h :显示安装进度
安装软件的相关信息被写入 /var/lib/rpm/ 目录下的数据库文件中了。
安装多个
$rpm -i a.rpm b.rpm
安装网上的rpm
$rpm -i http://xxxxxx.rpm
升级
rpm -[UF]vh xxx.rpm
U:软件即使没有安装过,则系统将予以直接安装; 若后面接的软件有安装过旧版,则系统自动更新至新版。
F:软件没有被安装则不会被安装,只有已经被安装的软件才会升级。
查询
rpm 在查询的时候其实是在查询/var/lib/rpm/ 这个目录下的数据库档案。也可以查询没有安装的rpm 档案信息。
查询已经安装的软件
$rpm -qa openssl 列出openssl 软件信息
$rpm -qa 列出安装的所有软件
-qi 列出软件信息
-ql 列出软件所有的文件的完整文件名
-qf file_name 查询这个文件属于那个软件
-qR 列出软件的依赖软件(Required)
-qp[ilR] 查询未安装软件的信息(p 是package )
注:还有别的选项没有列举完
rpm 卸载软件
$rpm -e openssl
注: 可能由于依赖关系不能卸载软件,卸载软件的过程一定要是从上层往下层卸载。如:a -依赖-> b -依赖-> c 如果要卸载a 时,就要卸载c时,就要先卸载a,再卸载b,最后卸载c
重建数据库
$rpm --rebuilddb
rpm 验证与数字签名,查看软件有没有被修改过。(可以查询相关信息)
yum
示例:
$ yum list openssl
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: mirrors.aliyun.com
* extras: mirrors.aliyun.com
* updates: mirrors.aliyun.com
Installed Packages
openssl.x86_64 1.0.1e-48.el6 @anaconda-CentOS-201605220104.x86_64/6.8
Available Packages
openssl.i686 1.0.1e-57.el6 base
openssl.x86_64 1.0.1e-57.el6 base
上面 Installed Packages 说明是已经安装的版本
yum
查询
yum list 列出目前 yum 所管理的所有的软件名称和版本
yum info 和上面类似,不过有软件的信息
yum provides file_name 文件属于那一个软件
安装:
$yum install xxx -y
$yum update xxx 要整个系统都升级,就直接 update 即可
移除:
$yum remove xxx 同rpm,先解决属性相依的问题