第一章、操作系统基础
01_03_操作系统基础
计算机体系结构包括以下几部分:
运算器
控制器
存储器,内存,编址
输出设备
输入设备
北桥 - 高速总线控制器
南桥 - 低速总线总线控制器
硬件架构:
ARM
x86
x64
安腾
alpha
UltraSparc
Power
M68000, M68K
PowerPC
OS:
Windows
Linux
Unix
HP-UX
Solaris
AIX
SCO UNIX
Unixware
OS/2
内核功能:
进程管理
内存管理
文件系统
网络功能
硬件驱动
安全机制
批处理系统
jobs1$$$$$$$jobs2$$$$$$$$
下面来讲一个关于操作系统的故事。
1965年时,贝尔实验室(Bell Labs)加入一项由通用电气(General Electric)和麻省理工学院(MIT)合作 的计划;该计划要建立一套多使用者、多任务、多层次(multi-user、multi-processor、multi-level)的MULTICS操作系统。直到1969年,因MULTICS计划的工作进度太慢,该计划被停了下来。当时,Ken Thompson(后被称为UNIX之父)已经有一个称为"星际旅行"的程序在GE-635的机器上跑,但是反应非常慢,正巧被他发现了一部被闲置的PDP-7(Digital的主机),Ken Thompson和Dernis Ritchie就将"星际旅行"的程序移植到PDP-7上。
MULTICS其实是"Multiplexed Information and Computing Service"的缩写,在1970年时,那部PDP-7却只能支持两个使用者,当时,Brian Kernighan就开玩笑地称他们的系统其实是:"UNiplexed Information and Computing Service",缩写为"UNICS",后来,大家取其谐音,就称其为"UNIX"了。1970年可称为"UNIX元年"。
1971年,Ken Thompson写了充分长篇的申请报告,申请到了一台PDP-11/24的机器。于是Unix第一版出来了。在一台PDP-11/24的机器上完成。这台电脑只有24KB的物理内存和500K磁盘空间。Unix占用了12KB的内存,剩下的一半内存可以支持两用户进行Space Travel的游戏。而著名的fork()系统调用也就是在这时出现的。
到了1973年的时候,Ken Thompson 与Dennis Ritchie感到用汇编语言做移植太过于头痛,他们想用高级语言来完成第三版,对于当时完全以汇编语言来开发程序的年代,他们的想法算是相当的疯狂。一开始他们想尝试用Fortran,可是失败了。后来他们用一个叫BCPL(Basic Combined Programming Language)的语言开发,他们整合了BCPL形成B语言,后来Dennis Ritchie觉得B语言还是不能满足要求,于是就改良了B语言,这就是今天的大名鼎鼎的C语言。于是,Ken Thompson 与Dennis Ritchie成功地用C语言重 写了Unix的第三版内核。至此,Unix这个操作系统修改、移植相当便利,为Unix日后的普及打下了坚实的基础。而Unix和C完美地结合成为一个统一体,C与Unix很快成为世界的主导。
Unix的第一篇文章 “The UNIX Time Sharing System”由Ken Thompson和Dennis Ritchie于1974年7月的 The Communications of the ACM发表。这是UNIX与外界的首次接触。结果引起了学术界的广泛兴趣并对其源码索取,所以,Unix第五版就以“仅用于教育目的”的协议,提供给各大学作为教学之用,成为当时操作系统课程中的范例教材。各大学公司开始通过Unix源码对Unix进行了各种各样的改进和扩展。于是,Unix开始广泛流行。
其中,Berkeley成立的由Bill Joy 领导的Unix研究小组取得的成就比较明显。
然而,20世纪70年代,AT&T公司开始注意到Unix所带来的商业价值。公司的律师开始寻找一些手段来保护Unix,并让其成为一种商业机密。从1979年Unix的版本V7开始,Unix的许可证开始禁止大学使用Unix的源码,包括在授课中学习。(之前由于AT&T公司被美国法院限制不可以销售除电话以外的其它产品,甚至别人向AT&T公司索取时,都不能拒绝,直到贝尔实验室独立了出来)
到了1980年,有两个最主要的Unix的版本线,一个是Berkeley的BSD UNIX,另一个是AT&T的Unix,在这个时候,很显然,竞争最终引发了Unix的战争。在这场战争中,好的是,软件开发人员还是能够得到Unix的源码并对其按照自己的需要和兴致进行裁剪。而不好的是,Unix开始一发不可收拾地开发不停地出现各种各样的变种。
1982年,Joy创建了Sun Microsystems公司并提供了工作站–Sun-1,运行SunOS(Solaris以之后的十年出现)。而AT&T则在随后的几年中发布了Unix System V的第一版,一个具有强大影响力的操作系统,最终造就了IBM的AIX和HP的HP-UX。
正值Unix战争之际,微软公司Bill Gates依靠母亲在IBM任职董事会副主席的关系,取得为其新PC机编写关键的操作系统软件的合作。由于时间紧迫,程序复杂,微软公司以5万美元的价格从西雅图的一位程序编制者Tim Paterson(帕特森)手中买下了一个操作系统QDOS的使用权,在进行部分改写后提供给IBM,并将其命名为Microsoft DOS(Disk Operating System,磁盘操作系统)。
另一家出名的电脑公司苹果,从施乐公司买进一个结合了鼠标的图形操作系统,该产品被认为会侵害施乐公司复印机业务。
微软利用与苹果合作的关系,抄袭了这款操作系统,发行了windows 1.0。但依然基于DOS,非常容易崩溃。微软从DEC雇佣了一批人员使用DEC的一个操作系统框架开发了新一代系统Window NT。
Unix收费后,Andrew开发的 Minix(一种基于微内核架构的类UNIX计算机操作系统)开始流行,Minix最有名的学生用户是Linus
Torvalds,他在芬兰的赫尔辛基大学用Minix操作平台建立了一个新的操作系统的内核,他把它叫做Linux。
80年代,Stallman 发起了GNU计划,GNU是“GNU's Not Unix”的递归缩写。加入GUN的软件都是自由并开源的,接受GNU通用公共许可证(GNU General Public License,GPL)。但发布的软件都依赖于Unix,这和GUN is Not Unix的定义严重不符。Linux诞生时就是在GPL条款下发布。1992年Linux与其他GNU软件结合,完全自由的操作系统正式诞生。GPL规定使用了GPL的软件后,你自己的软件也必须开源,这限制了GPL的普及,后来LGPL的出现改变了这一状况(LGPL: Lesser General
Public License),GNU的软件有:
Emacs: 文本编辑器
gcc: GNU C Complier
bash:
Linux:glibc, gcc,
GNU/Linux
自由软件中自由是指:
自由获取,自由修改,自由学习
Linux发行版
GNU/Linux都是以源的形式发布,需要自行编译,使用起来十分复杂,门槛太高。然后就有了Linux发行商。
RedHat
SLS
Debian
SUSE --> Novell (Netware), OpenSUSE
Ubuntu:
Mint
CentOS: Community ENTerprise OS,
社区版红帽
Fedora: 个人版红帽,RedHat公司已经将个人版红帽交给了Fedora社区
两大软件包管理软件:
Debian, dpt
RedHat, rpm
RedHat开机配置
linux ip=172.16.X.1 netmask=255.255.0.0 gateway=172.16.0.1 dns=172.16.0.1 ks=http://172.16.0.1/class.cfg
Linux内核版本和RHEL版本号可不一样:
Linux: 0.1, 1.0, 2.0, 2.2, 2.4, 2.6, 3.0, 3.7
RHEL 3.0, 4.0, 5.0, 6.0
第二章、Linux操作系统及常用命令
02_01_Linux操作系统及常用命令
Linux的基本原则:
1、由目的单一的小程序组成;组合小程序完成复杂任务;
2、一切皆文件;
3、尽量避免捕获用户接口;
4、配置文件保存为纯文本格式;
GUI接口:Graphical
User Interface
CLI接口:command-line
interface
命令提示符,prompt, bash(shell)
#: root
$: 普通用户
命令格式: 命令 选项 参数
# command options... arguments...
选项:
短选项: -
多个选项可以组合:-a -b = -ab
长选项: --
参数:命令的作用对象
虚拟终端(terminal):Ctrl+Alt+F1-F6
模拟终端:GUI图形界面中的终端
GUI:
X-Window Gnome: C
KDE: C++ XFace
CLI:
sh bash
csh zsh ksh tcsh
root, student, vistor
1.
su: switch user
# su [-l] 用户名 完全切换
# passwd
密码复杂性规则:
10^6
36^6
62^6
100^6
Linuxedu@126.com
1、使用4种类别字符中至少3种;
2、足够长,大于7位;
3、使用随机字符串;
4、定期更换;
5、循环周期足够大;
以后的课程大概包括:
RHCE+RHCA+shell编程+MySQL+Web集群+NoSQL+Hadoop+Hbase+Openstack
内部FTP:
172.16.100.177
192.168.0.1
google hack:
linux filetype:pdf
linux site:ibm.com
IDE:
login:
用户名:用户ID
认证机制:Authentication
授权:Authorization
审计:Audition (日志)
prompt,命令提示符:
magic number: 魔数,标记可执行文件的格式,exe,elf
#!/bin/bash就是脚本的魔数,又称shebang
2. ls: list
列出,列表
目录:文件,路径映射
路径:从指定起始点到目的地所经过位置
文件系统:file system
ls
-l:长格式
文件类型:
-:普通文件 (f)
d: 目录文件
b: 块设备文件 (block)
c: 字符设备文件 (character)
l: 符号链接文件(symbolic link file)
p: 命令管道文件(pipe)
s: 套接字文件(socket)
文件权限:9位,每3位一组,每一组:rwx(读,写,执行), r--
文件硬链接的次数
文件的属主(owner)
文件的属组(group)
文件大小(size),单位是字节
时间戳(timestamp):最近一次被修改的时间
访问:access
修改:modify,文件内容发生了改变
改变:change,metadata,元数据
-h:做单位转换
-a: 显示以.开头的隐藏文件
. 表示当前目录
.. 表示父目录
-A
-d: 显示目录自身属性
-i: index node, inode
-r: 逆序显示
-R: 递归(recursive)显示
3. pwd: Printing Working directory
目录:working directory, current directory
4. cd: change directory
家目录,主目录, home directory
cd ~USERNAME: 进入指定用户的家目录
cd -:在当前目录和前一次所在的目录之间来回切换
5. type: 显示指定属于哪种类型
Linux命令类型:
内置命令(shell内置),内部,内建
外部命令:在文件系统的某个路径下有一个与命令名称相应的可执行文件
环境变量:命名的内存空间
变量赋值 NAME=Jerry
PATH: 使用冒号分隔的路径
6. hash: 查看命令缓存
时间复杂度:O(1)
缓存为王,cache is king
02_02_Linux操作系统及常用命令
7. date:时间管理,查看系统时钟
Linux: 开机时读取硬件时钟,软件模拟生成系统时钟。
date [MMDDhhmm[[CC]YY][.ss]] //月 日 小时 分钟 年 . 秒
修改系统时间,如:date 1228235912.30 或 date 122823592012.30
date [OPTION]... [+FORMAT]
date +%D ---- 月/日/年
date +"This year is %Y, %n Today is %d"
8. clock/hwclock: 查看硬件时钟
clock和hwclock用法相近,只不过clock命 令除了支持x86硬件体系外,还支持Alpha硬件。
-w: 系统时钟写入硬件时钟
-s: 硬件时钟写入系统时钟
9. man: 显示命令manual pages
获得命令的使用帮助方式:
(1)内部命令:
help COMMAND (提示:man + 内部命令 查看到的是shell的帮助)
(2)外部命令:
COMMAND --help
(3)命令手册:manual
man COMMAND
(4)在线文档:
info COMMAND
(5)文档:/usr/share/doc
(6)google
MAN pages中各个小章节:
NAME:命令名称及功能简要说明
SYNOPSIS:用法说明,包括可用的选项
使用格式说明中的符号:
<>:必选
[]:可选
...:可以出现多次
|:多选一
{}:分组
DESCRIPTION:命令功能的详尽说明,可能包括每一个选项的意义
OPTIONS:说明每一个选项的意义
FILES:此命令相关的配置文件
BUGS:
EXAMPLES:使用示例
SEE ALSO:另外参照
man pages中操作:
翻屏:
向后翻一屏:f / SPACE
向前翻一屏:b
向后翻一行:j / ENTER
向前翻一行:k
查找:
/KEYWORD: 向后
n: 下一个, N:前一个
?KEYWORD:向前
n: 下一个, N:前一个
退出:q
10. whatis COMMAND: 查看该命令属于那些章节
man分章节:
1:用户命令(/bin, /usr/bin, /usr/local/bin)
2:系统调用
3:库用户
4:特殊文件(设备文件)
5:文件格式(配置文件的语法)
6:游戏
7:杂项(Miscellaneous)
8:管理命令(/sbin, /usr/sbin, /usr/local/sbin)
练习:
使用date单独获取系统当前的年份、月份、日、小时、分钟、秒
date +%Y, date +%m, date +%d, date +%H, date +%M, date +%S
11. cal: calendar
cal 2013: 查看2013年日历
cal 12 2013: 查看2013年12月日历
练习:
1、echo是内部命令还是外部命令?
2、其作用?
3、如何显示“The year is 2013. Today is 26.”为两行?
1、type echo
2.、man type
3、echo -e "The year is 2013. Today is 26."
12. echo: 回声
-n 不换行
-e 开启转义字符
练习:
1、printf是内部命令还是外部命令?
2、其作用?
3、如何显示“The year is 2013. Today is 26.”为两行?
1、type printf
2、man printf
3、printf "The year is 2013. Today is 26. "
13. printf: 打印
类似printf 函数用法
printf "The year is %d. Today is %d. " `date +%Y` `date +%d`
14. file:确定文件格式
Windows: PE
Linux: ELF
第三章、Linux根文件系统及文件管理命令详解
02_03_Linux根文件系统详解
文件系统:
rootfs: 根文件系统
FHS:Filesystem Hierarchy Standard(文件系统目录标准)的缩写,多数Linux版本采用这种文件组织形式,类似于Windows操作系统中c盘的文件目录,FHS采用树形结构组织文件。FHS定义了系统中每个区域的用途、所需要的最小构成的文件和目录,同时还给出了例外处理与矛盾处理。
根目录下的目录:
/boot: 系统启动相关的文件,如内核、initrd,以及grub(bootloader)
/dev: 设备文件
设备文件:
块设备:随机访问,数据块
字符设备:线性访问,按字符为单位
设备号:主设备号(major)和次设备号(minor)
/etc:配置文件
/home:用户的家目录,每一个用户的家目录通常默认为/home/USERNAME
/root:管理员的家目录;
/lib:库文件
静态库, .a
动态库, .dll, .so (shared object)
/lib/modules:内核模块文件
/media:挂载点目录,移动设备
/mnt:挂载点目录,额外的临时文件系统
/opt:可选目录,第三方程序的安装目录
/proc:伪文件系统,内核映射文件
/sys:伪文件系统,跟硬件设备相关的属性映射文件
/tmp:临时文件, /var/tmp
/var:可变化的文件
/bin: binary 可执行文件, 用户命令
/sbin:管理命令
/usr:universal shared read-only
有的说全称为:User System Resources, 见 http://www.ansen.org/2011/11/means-of-usr.html
/usr/bin
/usr/sbin
/usr/lib
/usr/local:
/usr/local/bin
/usr/local/sbin
/usr/local/lib
文件命名规则:
1、长度不能超过255个字符;
2、不能使用/当文件名
3、严格区分大小写
相对路径:以"./"开头的路径,默认
绝对路径: 以"/"开头的路径
使用一个操作系统主要工作:
文件管理
目录管理
运行程序
设备管理
软件管理
网络管理
目录管理
前面介绍过的:ls、cd、pwd
1. mkdir:创建空目录
-p:
-v: verbose
mkdir -pv /mnt/test/x/m /mnt/test/y
mkdir -pv /mnt/test/{x/m,y}
波浪线展开:~USERNAME
命令行展开:
在/mnt/test2/下创建a_b, a_c, d_b, d_c 四个目录
(a+d)(b+c)=ab+ac+db+dc
mkdir /mnt/test2/{a,d}_{b,c} #作为一个参数中间不可有空格
2. tree:查看目录树
3. rmdir: (remove directory) 删除目录
删除空目录
-p 如果父目录为空,同样删除
文件创建和删除
4. touch:修改文件时间戳
-a 仅修改访问时间
-m 仅修改修改时间
-t 指定时间为 [[CC]YY]MMDDhhmm[.ss]
-c 不创建文件
5. stat:显示文件状态
包括: 访问,修改,改变时间
创建文件,可以使用文件编辑器 nano
6. rm:删除文件
-i interactive 交互式
-f force 强制
-r recursive 递归
练习:
1、创建目录
(1)在/mnt下创建boot和sysroot;
(2)在/mnt/boot下创建grub;
(3)在/mnt/sysroot下创建proc, sys, bin, sbin, lib, usr, var, etc, dev, home, root, tmp
a)在/mnt/sysroot/usr下创建bin, sbin, lib
b)在/mnt/sysroot/lib下创建modules
c)在/mnt/sysroot/var下创建run, log, lock
d)在/mnt/sysroot/etc下创建init.d
(1) mkdir /mnt/{boot,sysroot}
(2) mkdir /mnt/boot/grub
(3) mkdir -p /mnt/sysroot/{proc,sys,bin,sbin,lib/modules,usr/{bin,sbin,lib},var{run,log,lock},etc/init.d,dev,home,root,tmp}
02_04_Linux文件管理命令详解
复制和移动文件
7. cp: copy
cp SRC DEST
-R, -r, --recursive 递归
-i,--interactive 交互
-f --force 强制
-p same as --preserve=mode,ownership,timestamps
-P,--no-dereference never follow symbolic links in SOURCE
-L, --dereference always follow symbolic links in SOURCE
-d same as --no-dereference --preserve=links
-a,--archive same as -dR --preserve=all 归档复制,常用于备份
cp file1 file2 file3
一个文件到一个文件
多个文件到一个目录
cp /etc/{passwd,inittab,rc.d/rc.sysinit} /tmp/
复制文件时如果目标存在。1. 目标为文件,提示覆盖。2. 目标为目录,复制的文件放到目录下。
复制目录时如果目标存在。1.目标为文件,无法覆盖。2. 目标为目录,复制源目录下所有文件到新目录下,如果文件重复,提示覆盖。
8. mv: move 移动文件
mv SRC DEST
mv -t DEST SRC
9. install: 复制文件并设置属性
-d DIRECOTRY ... :创建目录
SRC DEST
-t 指定目录
-m 设置权限
install -t DIRECTORY SRC...
install 不能复制目录。
作业1:
1、创建目录/backup
# mkdir -v /backup
2、复制目录/etc至/backup目录中,并重命名为“etc-当前日期”,如etc-2013-02-26;要求保留文件原来的属性,保持链接文件;
# cp -a /etc /backup/etc-2013-02-28
3、复制文件/etc/inittab为/tmp/inittab.new,并删除inittab.new文件的后两行;
# cp /etc/inittab /tmp/inittab.new
# nano /tmp/inittab.new
作业2:
1、思考:ls命令是否可以显示某目录的整体大小,即包括其内部的所有文件的整体大小?
2、通过帮助手册,学习使用du命令;
3、通过帮助,学习read命令;
1、不能,du可以
2、du -s -h
3、read var
03_01_Linux文件管理类命令详解
作业3:
描述GPL, BSD, Apache三个开源协定的大体联系及区别。
自由软件
开源协定,版权描述
作业4:
1、如何获取Linux当前最新的内核版本号?
www.kernel.org
2、列出你所了解的Linux发行版,并说明其跟Linux内核的关系。
Linux, GNU: GNU/Linux, 源代码
发行版:Fedora, RedHat(CentOS), SUSE, Debian(Ubuntu, Mint), Gentoo, LFS(Linux From Scratch)
RedHat: 通用格式,为了能支持大多数的CPU,编译出来的二进制可执行程序在较低平台上编译。为了发挥硬件最大性能,自己编译一个针对自己平台的Linux,Gento和LFS提供了这种方式。
复习:
运行程序
设备管理
软件管理
进程管理
网络管理
目录管理:
ls、cd、pwd、mkdir、rmdir、tree
文件管理:
touch、stat、file、rm、cp、mv、nano
日期时间:
date、clock、hwclock、cal
查看文本:
cat、tac、more、less、head、tail
10. cat:连接并显示
-n 显示行号
-E Show end, 行尾显示$
shift + pageup/pagedown 在终端缓存中翻页
分屏显示:
more、less
11. more: 向后翻
12. less:
man命令就是在用less命令查看文档。
13. head:查看前n行
n 默认为10
head -n 2 == head -2
14. tail:查看后n行
-n 默认为10
tail -f: 查看文件尾部,不退出,等待显示后续追加至此文件的新内容;
文本处理:
cut、join、sed、awk
文本文件:
Tom:23:male:2013/05/06
15. cut:
-d: 指定字段分隔符,默认是空格
-f: 指定要显示的字段
-f 1,3
-f 1-3
16. sort : 文本排序
-n:数值排序
-r: 降序
-t, --field-separator=SEP: 字段分隔符
-k, --key=POS1[,POS2]: 以哪个字段为关键字进行排序
-u: 排序后相同的行只显示一次
-f: 排序时忽略字符大小写
17. uniq: 去掉重复的行(必须相邻)
-c, --count: 显示文件中行重复的次数
-d, --repeated: only print duplicate lines 只显示重复的行
18. wc: (word count) 文本统计
-l, --lines 只显示行数
-w, --words
-c, --bytes
-L, --max-line-length
不使用参数,默认显示:行,单词,字节数
19. tr:字符处理命令 —— 转换或删除字符
tr [OPTION]... SET1 [SET2]
-d: 删除出现在字符集中的所有字符(只能有SET1)
把SET1中字符转换成SET2中字符,SET1 和SET2一对应, 如:tr ab AB, 会把a 换成A,b换成B
第四章、bash特性详解
03_02_base特性详解
bash及其特性:
shell: 外壳
GUI:Gnome, KDE, Xfce
CLI: sh, csh, ksh, bash, tcsh, zsh
Linux允许同一个用户登录多次
root, student
程序:进程
进程:在每个进程看来,当前主机上只存在内核和当前进程
进程是程序的副本,进程是程序执行实例
用户工作环境:
bash:
#
$
shell,子shell
bash--bash
bash:
1、命令历史、命令补全
2、管道、重定向
3、命令别名
4、命令行编辑
5、命令行展开
6、文件名通配
7、变量
8、编程
命令行编辑:
光标跳转:
Ctrl+a:跳到命令行首
Ctrl+e:跳到命令行尾
Ctrl+u: 删除光标至命令行首的内容
Ctrl+k: 删除光标至命令行尾的内容
Ctrl+l: 清屏
命令历史:
查看命令历史:history
-c:清空命令历史
-d OFFSET [n]: 删除指定位置的命令
-w:保存命令历史至历史文件中
环境变量
PATH:命令搜索路径
HISTSIZE: 命令历史缓冲区大小
命令历史的使用技巧:推荐一篇文章《让效率翻倍的Bash技巧》
!n:执行命令历史中的第n条命令;
!-n:执行命令历史中的倒数第n条命令;
!!: 执行上一条命令;
!string:执行命令历史中最近一个以指定字符串开头的命令
!$:引用前一个命令的最后一个参数;
Esc, .:引用前一个命令的最后一个参数;
Alt+.
命令补全: tab
搜索环境变量PATH记录的路径。
路径补全:tab
文本相关的命令
查看:cat, tac, more, less, head, tail
统计:wc
处理:tr, cut, join
排序:sort
uniq
03_03_base特性详解
复习:
bash特性:
命令行编辑:
命令历史:
history -c -w -d
HISTSIZE
~/.bash_history
!n, !-n, !!, !string, !$
命令补全,路径补全
命令补全:搜索PATH环境变量所指定的每个路径下以我们给出的字符串开头的可执行文件,如果多于一个,两次tab,可以给出列表;否则将直接补全;
路径补全:搜索我们给出的起始路径下的每个文件名,并试图补全;
命令别名
定义:alias CMDALIAS='COMMAND [options] [arguments]'
在shell中定义的别名仅在当前shell生命周期中有效;别名的有效范围仅为当前shell进程;
取消:unalias CMDALIAS
使用命令本身: CMD
命令替换: $(COMMAND), 反引号:`COMMAND`
把命令中某个子命令替换为其执行结果的过程
eg:
1. echo
"The current directory is $(pwd)."
2. echo "file-$(date +%F-%H-%M-%S)" ------------- file-2013-02-28-14-53-31.txt
%F full date; same as %Y-%m-%d
%H hour (00..23)
%M minute (00..59)
%S second (00..60)
%T time; same as %H:%M:%S
bash支持的引号:
``: 反引号,命令替换
"": 弱引用,可以实现变量替换
'': 强引用,不完成变量替换
文件名通配, globbing
*: 任意长度的任意字符
?:任意单个字符
[]:匹配指定范围内的任意单个字符
[abc], [a-m], [a-z], [A-Z], [0-9], [a-zA-Z], [0-9a-zA-Z]
[:space:]:空白字符
[:punct:]:标点符号
[:lower:]:小写字母
[:upper:]: 大写字母
[:alpha:]: 大小写字母
[:digit:]: 数字
[:alnum:]: 数字和大小写字母
# man 7 glob 查看这些内置特殊字符表示
[^]: (脱字符) 匹配指定范围之外的任意单个字符
[[:alpha:]]*[[:space:]]*[[:alpha:]] : 字母开头,字母结尾,中间有空格
练习:
1、创建a123, cd6, c78m, c1 my, m.z, k 67, 8yu, 789等文件;注意,以上文件是以逗号隔开的,其它符号都是文件名的组成部分;
2、显示所有以a或m开头的文件;
ls [am]*
3、显示所有文件名中包含了数字的文件;
ls *[0-9]*
ls *[[:digit:]]*
4、显示所有以数字结尾且文件名中不包含空白的文件;
ls *[^[:space:]]*[0-9] ????????? -- 正则表达式可以解决
5、显示文件名中包含了非字母或数字的特殊符号的文件;
ls *[^[:alnum:]]*
ls *[^a-zA-Z0-9]*
第五章、Linux用户及权限详解
03_04_Linux用户及权限详解
今天内容:
用户、组、权限
用户,用户组: 都只是标识符
安全上下文(secure context):
权限:
r, w, x
文件:
r:可读,可以使用类似cat等命令查看文件内容;
w:可写,可以编辑或删除此文件;
x: 可执行,eXacutable,可以命令提示符下当作命令提交给内核运行;
目录:
r: 可以对此目录执行ls以列出内部的所有文件;
w: 可以在此目录创建文件;
x: 可以使用cd切换进此目录,也可以使用ls -l查看内部文件的详细信息;
rwx:
r--:只读
r-x:读和执行
---:无权限
0 000 ---:无权限
1 001 --x: 执行
2 010 -w-: 写
3 011 -wx: 写和执行
4 100 r--: 只读
5 101 r-x: 读和执行
6 110 rw-: 读写
7 111 rwx: 读写执行
755:rwxr-xr-x:属主 属组 其他
rw-r-----: 640
660: rw-rw----
rwxrwxr-x: 775
用户:UID, /etc/passwd
组:GID, /etc/group
影子口令:
用户:/etc/shadow
组:/etc/gshadow
用户类别:
管理员:0
普通用户: 1-65535
系统用户:1-499, 不需要登录系统,只用来运行某些后台服务
一般用户:500-60000
用户组类别:
管理员组:
普通组:
系统组:
一般组:
用户组类别:
私有组:创建用户时,如果没有为其指定所属的组,系统会自动为其创建一个与用户名同名的组
基本组:用户的默认组
附加组,额外组:默认组以外的其它组
e.g:
进程:tom tom
对象:rwxrw-r-- jerry tom a.txt
tom执行ls命令
rwxr-xr-x root root /bin/ls, 文件属主各属组
ls 运行时,进程的属主是运行的用户
man 5 passwd
/etc/passwd
account: 登录名
password: 密码
UID:
GID:基本组ID
comment: 注释
HOME DIR:家目录
SHELL:用户的默认shell, cat /etc/shells查看合法shell
man 5 shadow: 查看/etc/shadow文件格式
/etc/shadow
account: 登录名
encrypted password: 加密的密码,两个!号表示锁定,不允许登录。格式: $1位$8位$密码
1位段: 加密方法
8位段:杂质(随机生成)
加密方法:
对称加密:加密和解密使用同一个密码
公钥加密:每个密码都成对儿出现,一个为私钥(secret key),一个为公钥(public key)
单向加密,散列加密:提取数据特征码,常用于数据完整性校验
特性: 1、雪崩效应 2、定长输出
MD5:Message Digest, 128位定长输出
SHA1:Secure Hash Algorithm, 160位定长输出
非对称加密更长,速度慢,慢3个数量级(1000倍以上)
用户,组添加
useradd USERNAME
groupadd GRPNAME
用户管理:
useradd, userdel, usermod, passwd, chsh, chfn, finger, id, chage
组管理:
groupadd, groupdel, groupmod, gpasswd
权限管理:
chown, chgrp, chmod, umask
/etc/passwd:
用户名:密码:UID:GID:注释:家目录:默认SHELL
/etc/group:
组名:密码:GID:以此组为其附加组的用户列表
/etc/shadow:
用户名:密码:最近一次修改密码的时间:最短使用期限:最长使用期限:警告时间:非活动时间:过期时间:
用户管理:
useradd, userdel, usermod, passwd, chsh, chfn, finger, id, chage
04_01_Linux用户管理命令详解
1. useradd [options] USERNAME
-u UID
-g GID(基本组)
-G GID,... (附加组) 一个用户可以属于多个附加组
-c "COMMENT"
-d /path/to/directory 指定家目录
-s SHELL ; /etc/shells:指定了当前系统可用的安全shell
-m -k 创建家目录,并复制SKEL_DIR(default: /etc/skel) 下的文件到家目录
-M 不创建用户主目录,即使系统在 /etc/login.defs 中的设置 (CREATE_HOME) 为 yes。
-r: 添加系统用户
/etc/login.defs 用户操作的一些选项
环境变量:
PATH
HISTSIZE
SHELL
2. userdel:
userdel [option] USERNAME
-r: 同时删除用户的家目录
3. id:查看用户的帐号属性信息
-u 显示uid
-g 显示基本组id
-G 显示附加组id
-n 显示名称,而非ID号,结合其它选项
4. finger: 查看用户帐号信息
finger USERNAME
5. usermod: 修改用户帐号属性
-u UID
-g GID
-a -G GID:不使用-a选项,会覆盖此前的附加组;
-c "COMMENT"
-d -m:修改家目录,并复制原家目录下文件到新家目录下
-s : shell
-l : 修改用户名
-L:锁定帐号
-U:解锁帐号
6. chsh: 修改用户的默认shell
7. chfn:change finger 修改更改真名和信息,注释信息
8. passwd [USERNAME]: 密码管理
--stdin 从标准输入接收密码, echo "redhat" | passwd --stdin root
-l lock
-u unlock
-d: 删除用户密码
9. pwck:检查用户帐号完整性
组管理:
10. groupadd:创建组
-g GID
-r:添加为系统组
11. groupmod
-g GID
-n GRPNAME
12. groupdel
13. gpasswd:为组设定密码
14. newgrp GRPNAME <--> exit(退出临时组): 临时切换为其他基本组,这时候需要用到组密码(切换到自己的附加组不需要)
练习:
1、创建一个用户mandriva,其ID号为2002,基本组为distro(组ID为3003),附加组为linux;
# groupadd -g 3003 distro
# groupadd linux
# useradd -u 2002 -g distro -G linux mandriva
2、创建一个用户fedora,其全名为Fedora Community,默认shell为tcsh;
# useradd -c "Fedora Community" -s /bin/tcsh fedora
3、修改mandriva的ID号为4004,基本组为linux,附加组为distro和fedora;
# usermod -u 4004 -g linux -G distro,fedora mandriva
4、给fedora加密码,并设定其密码最短使用期限为2天,最长为50天;
# passwd -n 2 -x 50 fedora
5、将mandriva的默认shell改为/bin/bash;
usermod -s /bin/bash mandirva
6、添加系统用户hbase,且不允许其登录系统;
# useradd -r -s /sbin/nologin hbase
7、
chage:修改用户密码过期时间
-d: 最近一次的修改时间
-E: 过期时间
-I:非活动时间
-m: 最短使用期限
-M: 最长使用期限
-W: 警告时间
04_02_权限及权限管理
复习:
权限管理:
r:
w:
x:
三类用户:
u: 属主
g: 属组
o: 其它用户
1. chown: 改变文件属主(只有管理员可以使用此命令)
# chown USERNAME file,...
-R: 修改目录及其内部文件的属主
--reference=/path/to/somefile file,...
chown USERNAME:GRPNAME file,...
chown USERNAME.GRPNAME file,...
2. chgrp: 改变文件属组
# chgrp GRPNAME file,...
-R:recursive
--reference=/path/to/somefile file,...
3. chmod: 修改文件的权限
修改三类用户的权限:
chmod MODE file,...
-R:recursive
--reference=/path/to/somefile file:参考某个文件设定权限
修改某类用户或某些类用户权限:
u,g,o,a
chmod 用户类别=MODE file,...
e.g: chmod go=rw,u=r /tmp/abc
修改某类用户的某位或某些位权限:
u,g,o,a
chmod 用户类别+|-MODE file,...
chmod u-x /tmp/abc
chmod u+x,g-x /tmp/abc
chmod u-rx /tmp/abc
练习:
1、新建一个没有家目录的用户openstack;
# useradd -M openstack
2、复制/etc/skel为/home/openstack;
# cp -r /etc/skel /home/openstack
3、改变/home/openstack及其内部文件的属主属组均为openstack;
# chown -R openstack:openstack /home/openstack
4、/home/openstack及其内部的文件,属组和其它用户没有任何访问权限
# chmod -R go= /home/openstack
手动添加用户hive, 基本组为hive (5000),附加组为mygroup
1. 修改/etc/passwd文件,data +%s 得到19700101到当前的秒数,使用bc(bc是Linux下的计算器)把秒数除以一天的秒数86400,得到19700101到今天的天数。
2. 创建家目录、复制文件、修改文件权限
3. 修改/etc/shadow文件,使用sslpasswd可以生成加盐的加密串。
openssl passwd -1 -salt '12345678'
4. umask:遮罩码
文件:666-umask
目录:777-umask
# umask
# umask 022
文件默认不能具有执行权限,如果算得的结果中有执行权限,则将其权限加1;
umask: 023
文件:666-023=643 X
目录:777-023=754
站在用户登录的角度来说,SHELL的类型:
登录式shell:
正常通常某终端登录
1. su - USERNAME
2. su -l USERNAME
非登录式shell:
1. su USERNAME
2. 图形终端下打开命令窗口
3. 自动执行的shell脚本
bash的配置文件:
全局配置
/etc/profile, /etc/profile.d/*.sh, /etc/bashrc
个人配置
~/.bash_profile, ~/.bashrc
profile类的文件:
设定环境变量
运行命令或脚本
bashrc类的文件:
设定本地变量
定义命令别名
登录式shell如何读取配置文件?
/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc
非登录式shell如何配置文件?
~/.bashrc --> /etc/basrc --> /etc/profile.d/*.sh
第六章、管道及IO重定向
04_03_管道及IO重定向
计算机组成:
运算器、控制器: CPU
存储器:RAM
输入设备/输出设备
程序:指令和数据
控制器:指令
运算器:
存储器:
地址总线:内存寻址
数据总线:传输数据
控制总结:控制指令
寄存器:CPU暂时存储器
I/O: 硬盘,
程序
INPUT设备、OUTPUT设备
系统设定
默认输出设备:标准输出,STDOUT, 1
默认输入设备:标准输入, STDIN, 0
标准错误输出:STDERR, 2
标准输入:键盘
标准输出和错误输出:显示器
I/O重定向:
Linux:
>: 覆盖输出
>>:追加输出
set -C: 禁止对已经存在文件使用覆盖重定向;
强制覆盖输出,则使用 >|
set +C: 关闭上述功能
2>: 重定向错误输出
2>>: 追加方式
&>: 重定向标准输出或错误输出至同一个文件
<:输入重定向
<<:Here Document,在此处生成文档
cat >> /tmp/myfile.txe << EOF,可以在脚本中生成文档
管道:前一个命令的输出,作为后一个命令的输入
命令1 | 命令2 | 命令3 | ...
tee:
既保存文档,又输出到屏幕
练习:
1、统计/usr/bin/目录下的文件个数;
# ls /usr/bin | wc -l
2、取出当前系统上所有用户的shell,要求,每种shell只显示一次,并且按顺序进行显示;
# cut -d: -f7 /etc/passwd | sort -u
3、思考:如何显示/var/log目录下每个文件的内容类型?
4、取出/etc/inittab文件的第6行;
# head -6 /etc/inittab | tail -1
5、取出/etc/passwd文件中倒数第9个用户的用户名和shell,显示到屏幕上并将其保存至/tmp/users文件中;
# tail -9 /etc/passwd | head -1 | cut -d: -f1,7 | tee /tmp/users
6、显示/etc目录下所有以pa开头的文件,并统计其个数;
# ls -d /etc/pa* | wc -l
7、不使用文本编辑器,将alias cls=clear一行内容添加至当前用户的.bashrc文件中;
# echo "alias cls=clear" >> ~/.bashrc
第七章、grep及正则表达式
04_04_grep及正则表达式
grep家族: grep, egrep, fgrep
grep: 根据模式搜索文本,并将符合模式的文本行显示出来。
Pattern: 文本字符和正则表达式的元字符组合而成匹配条件
grep [options] PATTERN [FILE...]
-i:忽略大小写
--color:匹配到的字符带颜色
-v::显示没有被模式匹配到的行
-o:只显示被模式匹配到的字符串
通配符:
1. *: 任意长度的任意字符
2. ?: 任意单个字符
3. []:
4. [^]:
正则表达式:REGular EXPression, REGEXP
元字符:
1. .: 匹配任意单个字符
2. []: 匹配指定范围内的任意单个字符
3. [^]:匹配指定范围外的任意单个字符
字符集合:[:digit:], [:lower:], [:upper:], [:punct:], [:space:], [:alpha:], [:alnum:]
匹配次数(贪婪模式):
1. *: 匹配其前面的字符任意次
e.g: 有:a, b, ab, aab, acb, adb, amnb,下面pattern会匹配那些字符串?
a*b: b, ab,aab
a?b: b, ab
a.*b: ab, aab, acb, adb, amnb
.*: 任意长度的任意字符
2. ?: 匹配其前面的字符1次或0次
3. {m,n}:匹配其前面的字符至少m次,至多n次
{1,} - 至少1次
{0,3} - 至多3次
位置锚定:
1. ^: 锚定行首,此字符后面的任意内容必须出现在行首
2. $: 锚定行尾,此字符前面的任意内容必须出现在行尾
^$: 空白行
3. <或: 锚定词首,其后面的任意字符必须作为单词首部出现
4. >或: 锚定词尾,其前面的任意字符必须作为单词的尾部出现
分组:
()
(ab)*:ab作为整体,出现n次
后向引用
1: 引用第一个左括号以及与之对应的右括号所包括的所有内容
2:
3:
e.g:
He love his lover.
She like her liker.
He like his lover.
grep '(l..e).*1' test.txt 匹配到1, 2行
练习:
1、显示/proc/meminfo文件中以不区分大小的s开头的行;
grep -i '^s' /proc/meminfo
grep '^[sS]' /proc/meminfo
2、显示/etc/passwd中以nologin结尾的行;
grep 'nologin$' /etc/passwd
取出默认shell为/sbin/nologin的用户列表
grep "nologin$' /etc/passwd | cut -d: -f1
取出默认shell为bash,且其用户ID号最小的用户的用户名
grep 'bash$' /etc/passwd | sort -n -t: -k3 | head -1 | cut -d: -f1
3、显示/etc/inittab中以#开头,且后面跟一个或多个空白字符,而后又跟了任意非空白字符的行;
grep "^#[[:space:]]{1,}[^[:space:]]" /etc/inittab
4、显示/etc/inittab中包含了:一个数字:(即两个冒号中间一个数字)的行;
grep ':[0-9]:' /etc/inittab
5、显示/boot/grub/grub.conf文件中以一个或多个空白字符开头的行;
grep '^[[:space:]]{1,}' /boot/grub/grub.conf
6、显示/etc/inittab文件中以一个数字开头并以一个与开头数字相同的数字结尾的行;
grep '^([0-9]).*1$' /etc/inittab
练习:
1、找出某文件中的,1位数,或2位数;
grep '[0-9]{1,2}' /proc/cpuinfo
grep --color '<[0-9]{1,2}>' /proc/cpuinfo
2、找出ifconfig命令结果中的1-255之间的整数;
需要使用扩展正则表达式
ifconfig | egrep --color '<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-9][0-9])>'
3、查找当前系统上名字为student(必须出现在行首)的用户的帐号的相关信息, 文件为/etc/passwd
grep '^student>' /etc/passwd | cut -d: -f3
id -u student
student1
student2
练习:
分析/etc/inittab文件中如下文本中前两行的特征(每一行中出现在数字必须相同),请写出可以精确找到类似两行的模式:
l1:1:wait:/etc/rc.d/rc 1
l3:3:wait:/etc/rc.d/rc 3
grep '^l([0-9]):1.*1$' /etc/inittab
05_01_egrep及扩展正则表达式
复习:
REGEXP:REGular EXPression
Pattern:模式
正则表达式:
Basic REGEXP:基本
Extended REGEXP:扩展
基本正则表达式:
.:
[]:
[^]:
次数匹配:
*:
?: 0或1次
{m,n}:至少m次,至多n次;
.*:
锚定:
^:
$:
<, :
>, :
()
1, 2, 3, ...
grep:使用基本正则表达式定义的模式来过滤文本的命令;
-i
-v
-o
--color
-E: 使用扩展正则表达式
-A n: 显示匹配到的行和其后的n行
-B n: 前的n行
-C n: 前后各n行
扩展正则表达式:省略很多反斜线
字符匹配:
.
[]
[^]
次数匹配:
*:
?:
+: 匹配其前面的字符至少1次,{1,}
{m,n}:
位置锚定:
^
$
<
>
分组:
():分组
1, 2, 3, ...
或者
|: or
C|cat: C或cat, 不是Cat或cat,这个用 '(C|c)at'
grep -E = egrep
4、显示所有以数字结尾且文件名中不包含空白的文件;
bash特性详解时的未解问题
ls .*[^[[:space:]].*[0-9]$
找出/boot/grub/grub.conf文件中1-255之间的数字;
<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])>
找出ifconfig中的IP地址
ifconfig | egrep '<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])>.<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])>.<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])>.<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])>'
ifconfig | egrep --color '(<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])>.){3}<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])>'
找出ifconfig中的ABC 3类IP地址
IPv4:
5类:A B C D E
A:1-127
B:128-191
C:192-223
<([1-9]|[1-9][0-9]|1[0-9]{2}|2[01][0-9]|22[0-3])>(.<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])>){2}.<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])>
马哥51cto博客: http://mageedu.blog.51cto.com/
fgrep: 快速grep, 不支持正则表达式
第八章、bash脚本编程(上)
05_02_bash脚本编程之一变量、变量类型等
shell编程: 脚本编程
语言转换器:编译器,解释器
编程语言:机器语言、汇编语言、高级语言
静态语言:编译型语言
特点:强类型(变量)
事先转换成可执行格式
包括:C、C++、JAVA、C#
动态语言:解释型语言, on the fly
特点:弱类型
边解释边执行
包括:PHP、SHELL、python、perl
面向过程:Shell, C
面向对象: JAVA, Python, perl, C++
变量:内存空间,命名
内存:编址的存储单元
变量类型:事先确定数据的存储格式和长度
字符
数值
整型
浮点型: 11.23, 1.123*10^1, 0.1123*10^2
存储日期:
字符:2013/10/10 - 64bit
数值: 99999 - 24bit,
布尔:真、假
逻辑:1+1>2
逻辑运算:与、或、非、异或
1: 真
0: 假
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0
1 & 1 = 1
或:
非:
! 真 = 假
! 假 = 真
异或:相异为1,相同为0
shell: 弱类型编程语言
强类型,弱类型的特点:
强:变量在使用前,必须事先声明,甚至还需要初始化;
弱:变量用时声明,甚至不区分类型;
变量赋值:VAR_NAME=VALUE
bash变量类型:
环境变量
本地变量(局部变量)
位置变量
特殊变量
1. 本地变量:<set> VARNAME=VALUE: 作用域为整个bash进程;set 可以省略
2. 局部变量:local VARNAME=VALUE:作用域为当前代码段;
3. 环境变量:作用域为当前shell进程及其子进程;
export VARNAME=VALUE
或
VARNAME=VALUE; export VARNAME
export:“导出”
export
PATH=$PATH:/usr/local/mypath
4. 位置变量:$1, $2, ...
5. 特殊变量:$?: 上一个命令的执行状态返回值;
程序执行,可能有两类返回值:
1. 程序执行结果
2. 程序状态返回代码(0-255)
0: 正确执行
1-255:错误执行,1,2,127系统预留;
输出重定向:
> 覆盖重定向
>> 追加重定向
2> 错误重定向
2>>错误追加重定向
&> 同时重定向
/dev/null: 软件设备, bit
bucket,数据黑洞
撤消变量:
unset VARNAME
查看当shell中变量:
set:包括本地变量和环境变量
查看当前shell中的环境变量:
printenv
env
export
脚本:命令的堆砌,按实际需要,结合命令流程控制机制实现的源程序
脚本的特殊标记:
shebang: 魔数
#!/bin/bash
# 注释行,不执行
脚本在执行时会启动一个子shell进程;
1. 命令行中启动的脚本会继承当前shell环境变量;
2. 系统自动执行的脚本(非命令行启动)就需要自我定义需要各环境变量;
05_03_bash脚本编程之二 条件判断
练习:写一个脚本,完成以下任务 - 答案为addusers.sh
1、添加5个用户, user1,..., user5
2、每个用户的密码同用户名,而且要求,添加密码完成后不显示passwd命令的执行结果信息;
3、每个用户添加完成后,都要显示用户某某已经成功添加;
#!/bin/bash
useradd user1
echo "user1" | passwd --stdin user1 &> /dev/null
echo "Add user1 successfully."
条件判断:
如果用户不存在
添加用户,给密码并显示添加成功;
否则
显示如果已经没在,没有添加;
bash中如何实现条件判断?
条件测试类型:
整数测试
字符测试
文件测试
条件测试的表达式:
[ expression ] : 中括号和expression之间必须有空格
` expression `
test expression
整数比较:
-eq: 测试两个整数是否相等;比如 $A -eq $B
-ne: 测试两个整数是否不等;不等,为真;相等,为假;
-gt: 测试一个数是否大于另一个数;大于,为真;否则,为假;
-lt: 测试一个数是否小于另一个数;小于,为真;否则,为假;
-ge: 大于或等于
-le:小于或等于
命令间的逻辑关系:
逻辑与: &&
第一个条件为假时,第二条件不用再判断,最终结果已经有;
第一个条件为真时,第二条件必须得判断;
逻辑或: ||
如果用户user6不存在,就添加用户user6
! id user6 && useradd user6
id user6 || useradd user6
如果/etc/inittab文件的行数大于100,就显示好大的文件;
[ `wc -l /etc/inittab | cut -d' ' -f1` -gt 100 ] && echo "Large file."
变量名称:
1、只能包含字母、数字和下划线,并且不能数字开头;
2、不应该跟系统中已有的环境变量重名;
3、最好做到见名知义;
如果用户存在,就显示用户已存在;否则,就添加此用户;
id user1 && echo "user1 exists." || useradd user1
如果用户不存在,就添加;否则,显示其已经存在;
! id user1 && useradd user1 || echo "user1 exists."
如果用户不存在,添加并且给密码;否则,显示其已经存在;
! id user1 && useradd user1 && echo "user1" | passwd --stdin user1|| echo "user1 exists."
练习,写一个脚本,完成以下要求: - 答案为adduser2.sh文件
1、添加3个用户user1, user2, user3;但要先判断用户是否存在,不存在而后再添加;
2、添加完成后,显示一共添加了几个用户;当然,不能包括因为事先存在而没有添加的;
3、最后显示当前系统上共有多少个用户;
练习,写一个脚本,完成以下要求: - 答案为third.sh文件
给定一个用户:
1、如果其UID为0,就显示此为管理员;
2、否则,就显示其为普通用户;
使用if语句:
如果 UID为0;那么
显示为管理员
否则
显示为普通用户
NAME=user16
USERID=`id -u $NAME`
if [ $USERID -eq 0 ]; then
echo "Admin"
else
echo "common user."
fi
NAME=user16
if [ `id -u $NAME` -eq 0 ]; then
echo "Admin"
else
echo "common user."
fi
05_04_bash脚本编程之三条件判断及算术运算
1. 练习:写一个脚本 - 答案为 bash.sh
判断当前系统上是否有用户的默认shell为bash;
如果有,就显示有多少个这类用户;否则,就显示没有这类用户;
grep "bash$" /etc/passwd &> /dev/null
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
if grep "bash$" /etc/passwd &> /dev/null; then
提示:“引用”一个命令的执行结果,要使用命令引用;比如: RESAULTS=`wc -l /etc/passwd | cut -d: -f1`;
使用一个命令的执行状态结果,要直接执行此命令,一定不能引用;比如: if id user1一句中的id命令就一定不能加引号;
如果想把一个命令的执行结果赋值给某变量,要使用命令引用,比如USERID=`id -u user1`;
如果想把一个命令的执行状态结果保存下来,并作为命令执行成功与否的判断条件,则需要先执行此命令,而后引用其状态结果,如
id -u user1
RETVAL=$?
此句绝对不可以写为RETVAL=`id -u user1`;
2. 练习:写一个脚本 - 答案为bash2.sh
判断当前系统上是否有用户的默认shell为bash;
如果有,就显示其中一个的用户名;否则,就显示没有这类用户;
3. 练习:写一个脚本
给定一个文件,比如/etc/inittab
判断这个文件中是否有空白行;
如果有,则显示其空白行数;否则,显示没有空白行。
1 2 3 4 5 6 7 8 9 10 11 12 |
#!/bin/bash FILE=/etc/inittab if [ ! -e $FILE ]; then echo "No $FILE." exit 8 fi
if grep "^$" $FILE &> /dev/null; then echo "Total blank lines: `grep "^$" $FILE | wc -l`." else echo "No blank line." fi |
4. 练习:写一个脚本
给定一个用户,判断其UID与GID是否一样
如果一样,就显示此用户为“good guy”;否则,就显示此用户为“bad guy”。
1 2 3 4 5 6 7 8 9 |
#!/bin/bash USERNAME=user1 USERID=`id -u $USERNAME` GROUPID=`id -g $USERNAME` if [ $USERID -eq $GROUPID ]; then echo "Good guy." else echo "Bad guy." fi |
进一步要求:不使用id命令获得其id号;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#!/bin/bash # USERNAME=user1 if ! grep "^$USERNAME>" /etc/passwd &> /dev/null; then echo "No such user: $USERNAME." exit 1 fi
USERID=`grep "^$USERNAME>" /etc/passwd | cut -d: -f3` GROUPID=`grep "^$USERNAME>" /etc/passwd | cut -d: -f4` if [ $USERID -eq $GROUPID ]; then echo "Good guy." else echo "Bad guy." fi |
5. 练习:写一个脚本
给定一个用户,获取其密码警告期限;
而后判断用户密码使用期限是否已经小于警告期限;
提示:计算方法,最长使用期限减去已经使用的天数即为剩余使用期限;
如果小于,则显示“Warning”;否则,就显示“OK”。
圆整:丢弃小数点后的所有内容
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#!/bin/bash W=`grep "student" /etc/shadow | cut -d: -f6` S=`date +%s` T=`expr $S/86400` L=`grep "^student" /etc/shadow | cut -d: -f5` N=`grep "^student" /etc/shadow | cut -d: -f3` SY=$[$L-$[$T-$N]]
if [ $SY -lt $W ]; then echo 'Warning' else echo 'OK' fi |
6. 练习:写一个脚本
判定命令历史中历史命令的总条目是否大于1000;如果大于,则显示“Some command will gone.”;否则显示“OK”。
history | tail -1 | cut -d' ' -f1
需要去掉开头的空格,cut 无法解决,留疑
shell中如何进行算术运算:
A=3
B=6
1、let 算术运算表达式
let C=$A+$B
2、$[算术运算表达式]
C=$[$A+$B]
3、$((算术运算表达式))
C=$(($A+$B))
4、expr 算术运算表达式,表达式中各操作数及运算符之间要有空格,而且要使用命令引用
C=`expr $A + $B`
条件判断,控制结构:
1. 单分支if语句
if 判断条件; then
statement1
statement2
...
fi
2. 双分支的if语句:
if 判断条件; then
statement1
statement2
...
else
statement3
statement4
...
fi
3. 多分支的if语句:
if 判断条件1; then
statement1
...
elif 判断条件2; then
statement2
...
elif 判断条件3; then
statement3
...
else
statement4
...
fi
06_01_bash脚本编程之四整数测试及特殊变量
复习:
测试方法:
[ expression ]
` expression `
test expression
bash中常用的条件测试有三种:整数,字符串,文件
整数测试:
-gt
-le
-ne
-eq
-ge
-lt
INT1=63
INT2=77
[ $INT1 -eq $INI2 ]
[[ $INT1 -eq $INT2 ]]
test $INT1 -eq $INT2
文件测试:
-e FILE:测试文件是否存在,exist的简写
-f FILE: 测试文件是否为普通文件
-d FILE: 测试指定路径是否为目录
-r FILE: 测试当前用户对指定文件是否有读取权限;
-w FILE: ~写权限
-x FILE: ~执行
e.g:
[ -e /etc/inittab ]
[ -x /etc/rc.d/rc.sysinit ]
练习:写一个脚本 - 答案为filetest2.sh
给定一个文件:
如果是一个普通文件,就显示之;
如果是一个目录,亦显示之;
否则,此为无法识别之文件;
定义脚本退出状态码
exit: 退出脚本
exit #
如果脚本没有明确定义退出状态码,那么,最后执行的一条命令的退出码即为脚本的退出状态码;
测试脚本是否有语法错误:
bash -n 脚本
调试脚本:
bash -x 脚本:打印每步执行
bash变量的类型:
本地变量(局部变量)
环境变量
位置变量:
$1, $2, ...
shift [n]:移出前面的n(默认为1)个参数,后面的参数向前移
特殊变量:
$?
$#:参数的个数
$*: 参数列表
$@:参数列表
e.g:
./filetest.sh /etc/fstab /etc/inittab
$1: /etc/fstab
$2: /etc/inittab
练习:写一脚本 - 答案为 filetest3.sh
能接受一个参数(文件路径)
判定:此参数如果是一个存在的文件,就显示“OK.”;否则就显示"No such file."
练习:写一个脚本 - 答案为 cacl.sh
给脚本传递两个参数(整数);
显示此两者之和,之乘积;
#!/bin/bash
#
if [ $# -lt 2 ]; then
echo "Usage: cacl.sh ARG1 ARG2"
exit 8
fi
echo "The sum is: $[$1+$2]."
echo "The prod is: $[$1*$2]."
练习:写一个脚本,完成以下任务
1、使用一个变量保存一个用户名;
2、删除此变量中的用户,且一并删除其家目录;
3、显示“用户删除完成”类的信息;
#!/bin/bash
#
USER=user1
if userdel -r $USER; then
echo "Delete user finished."
else
echo "Delete user failed."
fi
06_03_bash脚本编程之五字符串测试及for循环
shell编程引用变量:${VARNAME}, 括号有时可省略。
1. 练习: - 答案为testuser.sh
传递一个用户名参数给脚本,判断此用户的用户名跟其基本组的组名是否一致,并将结果显示出来。
#!/bin/bash
if [ 'id -nu $1' == 'id -gu $1' ]; then
fi
字符串测试:符号两端要有空格
==:测试是否相等,相等为真,不等为假
!=:测试是否不等,不等为真,等为假
>:一般不用
< :一般不用
-z string: 测试指定字符串是否为空,空则真,不空则假
-n string: 测试指定字符串是否不空,不空为真,空则为假
2. 练习:写一个脚本
传递一个参数(单字符就行)给脚本,如参数为q,就退出脚本;否则,就显示用户的参数;
3. 练习:写一个脚本
传递一个参数(单字符就行)给脚本,如参数为q、Q、quit或Quit,就退出脚本;否则,就显示用户的参数;
#!/bin/bash
if [ $1 = 'q' ];then
echo "Quiting..."
exit 1
elif [ $1 = 'Q' ];then
echo "Quiting..."
exit 2
elif [ $1 = 'quit' ];then
echo "Quiting..."
exit 3
elif [ $1 = 'Quit' ];then
echo "Quiting..."
exit 4
else
echo $1
fi
4. 练习:
传递三个参数给脚本,第一个为整数,第二个为算术运算符,第三个为整数,将计算结果显示出来,要求保留两位精度。形如:
./calc.sh 5 / 2
提示:
scale=2保留两位精度
echo "scale=2;111/22;" | bc
bc <<< "scale=2;111/22;"
#!/bin/bash
if [ $# -lt 3 ]; then
echo "Usage: `basename $0` num1 opt num2"
exit 1
fi
bc <<< "scale=2;$1 $2 $3"
5. 练习:
传递3个参数给脚本,参数均为用户名。将此些用户的帐号信息提取出来后放置于/tmp/testusers.txt文件中,并要求每一行行首有行号。
6. 练习,写一个脚本:
判断当前主机的CPU生产商,其信息在/proc/cpuinfo文件中vendor_id一行中。
如果其生产商为AuthenticAMD,就显示其为AMD公司;
如果其生产商为GenuineIntel,就显示其为Intel公司;
否则,就说其为非主流公司;
#!/bin/bash
VENDOR_ID=`grep vendor_id /proc/cpuinfo | head -1 | cut -d' ' -f2`
if [ $VENDOR_ID == "AuthenticAMD" ]; then
echo "AMD company"
elif [ $VENDOR_ID == "GenuineIntel" ]; then
echo "Intel company"
fi
7. 练习,写一个脚本:
给脚本传递三个整数,判断其中的最大数和最小数,并显示出来。
MAX=0
MAX -eq $1
MAX=$1
MAX -lt $2
MAX=$2
循环:一定要有:进入条件,退出条件
1. for
2. while
3. until
for循环语句
for 变量 in 列表; do
循环体
done
列表遍历完成之后,退出;
e.g:
for I in 1 2 3 4 5 6 7 8 9 10; do
加法运算
done
如何生成列表:
1. {1..100}
2. seq命令:`seq [起始数 [步进长度]] 结束数`,
8. 练习:求1-100的和 - 答案为sum.sh
declare:
-i: 将一个变量声明为整型,integer
-x: 将一个变量声明为环境变量
e.g: declare -i SUM=0
9. 写一个脚本:
1、设定变量FILE的值为/etc/passwd
2、依次向/etc/passwd中的每个用户问好,并显示对方的shell,形如:
Hello, root, your shell: /bin/bash
3、统计一共有多少个用户
for I in `seq 1 $LINES`; do echo "Hello, `head -n $I /etc/passwd | tail -1 | cut -d: -f1`"; done
只向默认shell为bash的用户问声好
第八章、bash脚本编程(中)
07_02_bash脚本编程之六使用脚本选项及组合条件测试(39 - $)
10. 写一个脚本:
1、添加10个用户user1到user10,密码同用户名;但要求只有用户不存在的情况下才能添加;
2. 扩展: - 答案为adminusers.sh
接受一个参数:
add: 添加用户user1..user10
del: 删除用户user1..user10
其它:退出
3. 参数指定 添加/删除 多个用户 - 答案为adminusers2.sh
adminusers --add user1,user2,user3,hello,hi
11. 写一个脚本:
计算100以内所有能被3整除的正整数的和;
取模,取余:%
3%2=1
100%55=45
12. 写一个脚本:
计算100以内所有奇数的和以及所有偶数的和;分别显示之;
let I=$[$I+1]
SUM=$[$SUM+$I]
let SUM+=$I
let I+=1 相当于 let I++
-=
let I-=1 相当于 let I--
++I, --I
*=
/=
%=
13. 写一个脚本:
分别显示当前系统上所有默认shell为bash的用户和默认shell为/sbin/nologin的用户,并统计各类shell下的用户总数。显示结果形如:
BASH,3users,they are:
root,redhat,gentoo
NOLOGIN, 2users, they are:
bin,ftp
#!/bin/bash
#
NUMBASH=`grep "bash$" /etc/passwd | wc -l`
BASHUSERS=`grep "bash$" /etc/passwd | cut -d: -f1`
BASHUSERS=`echo $BASHUSERS | sed 's@[[:space:]]@,@g'`
echo "BASH, $NUMBASH users, they are:"
echo "$BASHUSERS
组合测试条件
-a: 与关系
-o: 或关系
!:非关系
if [ $# -gt 1 -a $# -le 3 ]
if [ $# -gt 1 ] && [ $# -le 3 ]
练习: - 答案为 quit.sh
判断参数是不是在:q, Q, quit, Quit中。
08_01_facl及用户及Linux终端(65 - $)
生成随机数
RANDOM 系统内置环境变量可以生成随机数,范围: 0-32768
随机数生成器:熵池,保存很多随机数,可能取空
/dev/random: 熵池空时,阻塞,更安全
/dev/urandom: 熵池空时,软件模拟生成,
08_02_bash脚本编程之七 case语句及脚本选项进阶
练习:
写一个脚本,利用RANDOM生成10个随机数,并找出其中的最大值,和最小值;答案为random.sh
#!/bin/bash
#
declare -i MAX=0
declare -i MIN=0
for I in {1..10}; do
MYRAND=$RANDOM
[ $I -eq 1 ] && MIN=$MYRAND
if [ $I -le 9 ]; then
echo -n "$MYRAND,"
else
echo "$MYRAND"
fi
[ $MYRAND -gt $MAX ] && MAX=$MYRAND
[ $MYRAND -lt $MIN ] && MIN=$MYRAND
done
echo $MAX, $MIN
#!/bin/bash
#
for i in {1..10}; do
NUMS+=$RANDOM" "
done
MAXNUM=`echo $NUMS | cut -d' ' -f1`
MINNUM=$MAXNUM
for i in $NUMS; do
[ $i -gt $MAXNUM ] && MAXNUM=$i
[ $i -lt $MINNUM ] && MINNUM=$i
done
echo $NUMS
echo "max: $MAXNUM"
echo "min: $MINNUM"
面向过程的控制结构包括:
顺序结构
选择结构
循环结构
选择结构:fi和case语句
if: 单分支、双分支、多分支
if CONDITION; then
statement
...
fi
if CONDITION; then
statement
...
else
statement
...
fi
if CONDITION1; then
statement
...
elif CONDITION2; then
statement
...
esle
statement
...
fi
case语句:选择结构
case SWITCH in
value1)
statement
...
;;
value2)
statement
...
;;
*)
statement
...
;;
esac
value可以使用: - 例如case.sh
a-z
A-Z
0-9
[abc]
写debug.sh练习case的使用
练习:写一个脚本,实现功能:添加删除用户,显示详细信息 - 答案为adminusers3.sh
#!/bin/bash
#
DEBUG=0
ADD=0
DEL=0
for I in `seq 0 $#`; do
if [ $# -gt 0 ]; then
case $1 in
-v|--verbose)
DEBUG=1
shift ;;
-h|--help)
echo "Usage: `basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
exit 0
;;
--add)
ADD=1
ADDUSERS=$2
shift 2
;;
--del)
DEL=1
DELUSERS=$2
shift 2
;;
*)
echo "Usage: `basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
exit 7
;;
esac
fi
done
if [ $ADD -eq 1 ]; then
for USER in `echo $ADDUSERS | sed 's@,@ @g'`; do
if id $USER &> /dev/null; then
[ $DEBUG -eq 1 ] && echo "$USER exists."
else
useradd $USER
[ $DEBUG -eq 1 ] && echo "Add user $USER finished."
fi
done
fi
if [ $DEL -eq 1 ]; then
for USER in `echo $DELUSERS | sed 's@,@ @g'`; do
if id $USER &> /dev/null; then
userdel -r $USER
[ $DEBUG -eq 1 ] && echo "Delete $USER finished."
else
[ $DEBUG -eq 1 ] && echo "$USER not exist."
fi
done
fi
08_03_磁盘及文件系统管理详解之一(^-15)
练习:写一个脚本showlogged.sh,其用法格式为:
showlogged.sh -v -c -h|--help
其中,-h选项只能单独使用,用于显示帮助信息;-c选项时,显示当前系统上登录的所有用户数;如果同时使用了-v选项,则既显示同时登录的用户数,又显示登录的用户的相关信息;如
Logged users: 4.
They are:
root tty2 Feb 18 02:41
root pts/1 Mar 8 08:36 (172.16.100.177)
root pts/5 Mar 8 07:56 (172.16.100.177)
hadoop pts/6 Mar 8 09:16 (172.16.100.177)
#!/bin/bash
#
declare -i SHOWNUM=0
declare -i SHOWUSERS=0
for I in `seq 1 $#`; do
if [ $# -gt 0 ]; then
case $1 in
-h|--help)
echo "Usage: `basename $0` -h|--help -c|--count -v|--verbose"
exit 0 ;;
-v|--verbose)
let SHOWUSERS=1
shift ;;
-c|--count)
let SHOWNUM=1
shift ;;
*)
echo "Usage: `basename $0` -h|--help -c|--count -v|--verbose"
exit 8 ;;
esac
fi
done
if [ $SHOWNUM -eq 1 ]; then
echo "Logged users: `who | wc -l`."
if [ $SHOWUSERS -eq 1 ]; then
echo "They are:"
who
fi
fi
终端类型:
console: 控制台
pty: 物理终端 (VGA)
tty#: 虚拟终端 (VGA)
ttyS#: 串行终端
pts/#: 伪终端
练习:写一个脚本
通过命令行传递一个文件路径参数给脚本:
如果参数多了或少了,报错;
如果参数指定的路径对应的是目录而不是文件,报错;
而后,检查路径指定的文件是否为空或不存在,如果是,则新建此文件,并在文件中生成如下内容
#!/bin/bash
#
而后,使用vim编辑器打开此文件,并让光标处于这个文件的最后一行;
#!/bin/bash
if [ ! $# -eq 1 ]; then
echo "Usage: `basename $0` filepath"
exit 1
fi
if [ -d $1 ]; then
echo $?
echo "The file path is directory!"
exit 2
fi
if [ ! -e $1 ]; then
echo -e "#!/bin/bash #" > $1
vim $1
exit 3
fi
if grep "[^[:space:]]" $1 &>/dev/null; then
vim + $1
exit 4
else
echo -e "#!/bin/bash #" > $1
vim $1
exit 3
fi
写个脚本,按如下方式执行:
mkscript.sh -v|--version VERSION -a|--author AUTHOR -t|--time DATETIME -d|--description DESCRIPTION -f|--file /PATH/TO/FILE -h|--help
1、此脚本能创建或打开-f选项指向的文件/PATH/TO/FILE;如果其为空文件,能自动为其生成第一行;如果文件不空,且第一行不是#!/bin/bash,则中止此脚本,并报错“The file is not a bash script.";否则,则直接使用vim 打开此文件;
提示:/PATH/TO/FILE,要判断其目录是否存在;如果不存在,则报错;
2、如果为空文件,自动生成的第一行内容为:
#!/bin/bash
3、如果为空文件,且使用了-a选项,则在文件中添加“# Author: -a选项的参数”,比如:
# Author: Jerry
4、如果为空文件,且使用了-t选项,则在文件中添加“# Date: 脚本执行-t选项后指定的时间”,比如:
# Date: 2013-03-08 18:05
5、如果为空文件,且使用了-d选项,则在文件中添加“# Description: -d选项的内容”,比如:
# Description: Create a bash script file head.
6、如果为空文件,且使用了-v选项,则在文件添加“# Version: -v后跟的参数”,比如:
# Version: 0.1
7、-h选项只能单独使用,用于显示使用帮助;
8、其它选项,显示帮助信息;
说明:
这是一个用于创建脚本的脚本,它可以自动帮助创建一个bash脚本的文件头,这样,以后使用此脚本来创建其它脚本将变得比较高效。比如:
#!/bin/bash
# Author: Jerry(jerry@magedu.com)
# Date: 2013-03-08 18:05
# Description: Create a bash script file head.
# Version: 0.1
#
#!/bin/bash
#
print_help()
{
echo "Usage: `basename $0` [options]"
echo "Options:"
echo -e " -t|--time"
echo -e " -a|--author AUTHOR"
echo -e " -v|--version VERSION"
echo -e " -f|--file /PATH/TO/FILE"
echo -e " -d|--description DESCRIPTION"
echo -e " -h|--help"
exit 1
}
[ $# -eq 0 ] && print_help
while [ $# -gt 0 ]; do
case $1 in
-f|--file)
FILE=$2
shift 2;;
-a|--author)
AUTHOR=$2
shift 2;;
-t|--time)
DATE=`date "+%F %T"`
shift;;
-d|--description)
DESCRIPTION=$2
shift 2;;
-v|--version)
VERSION=$2
shift 2;;
-h|--help)
print_help
exit 1;;
*)
print_help
exit 1;;
esac
done
if [ -f $FILE ]; then
if grep "[^[:space:]]" $FILE &>/dev/null; then
if [ `head -1 $FILE` != "#!/bin/bash" ]; then
echo "The file is not a bash script."
exit 3
else
vim + $FILE
exit 2
fi
fi
fi
if [ -d $FILE ]; then
echo "$FILE is a directory."
exit 3
fi
echo "#!/bin/bash" >> $FILE
[ -n "$AUTHOR" ] && echo "# Author: $AUTHOR" >> $FILE
[ -n "$DATE" ] && echo "# Date: $DATE" >> $FILE
[ -n "$DESCRIPTION" ] && echo "# Description: $DESCRIPTION" >> $FILE
[ -n "$VERSION" ] && echo "# Version: $VERSION" >> $FILE
echo "#" >> $FILE
vim + $FILE
bss: Block Started by Symbol
readelf -h
readelf -S
objdump -h
ELF魔数、文件机器字节长度、数据存储方式、版本、运行平台、ABI版本、ELF重定位类型、硬件平台、硬件平台版本、入口地址、程序头入口和长度、段表的位置和长度、段的数量。
09_04_Linux压缩及归档 (66分钟-$)
脚本编程3种控制结构:
1. 顺序结构
2. 选择结构
if
case
3. 循环结构
for
while
until
while循环:适用于循环次数未知的场景,要有退出条件
语法:
while CONDITION; do
statement
...
done
练习:计算100以内所有正整数的和
#!/bin/bash
declare -i I=1
declare -i SUM=0
while [ $I -le 100 ]; do
let SUM+=$I
let I++
done
echo $SUM
练习:转换用户输入的字符为大写,除了quit:
#!/bin/bash
#
read -p "Input something: " STRING
while [ $STRING != 'quit' ]; do
echo $STRING | tr 'a-z' 'A-Z'
read -p "Input something: " STRING
done
练习:每隔5秒查看hadoop用户是否登录,如果登录,显示其登录并退出;否则,显示当前时间,并说明hadoop尚未登录:
#!/bin/bash
#
who | grep "hadoop" &> /dev/null
RETVAL=$?
while [ $RETVAL -ne 0 ]; do
echo "`date`, hadoop is not log."
sleep 5
who | grep "hadoop" &> /dev/null
RETVAL=$?
done
echo "hadoop is logged in."
10_01_Raid及mdadm命令之一 (^ - 17)
写一个脚本:
1) 显示一个菜单给用户:
d|D) show disk usages.
m|M) show memory usages.
s|S) show swap usages.
*) quit.
2) 当用户给定选项后显示相应的内容;
扩展:
当用户选择完成,显示相应信息后,不退出;而让用户再一次选择,再次显示相应内容;除了用户使用quit;
#!/bin/bash
#
cat << EOF
d|D) show disk usages.
m|M) show memory usages.
s|S) show swap usages.
*) quit.
EOF
read -p "Your choice: " CHOICE
while [ $CHOICE != 'quit' ];do
case $CHOICE in
d|D)
echo "Disk usage: "
df -Ph ;;
m|M)
echo "Memory usage: "
free -m | grep "Mem" ;;
s|S)
echo "Swap usage: "
free -m | grep "Swap" ;;
*)
echo "Unknown.." ;;
esac
read -p "Again, your choice: " CHOICE
done
控制echo显示文字的颜色以及显示效果
echo -e
" 33[1;31;41mHello 33[0m,world"
[31m: 两位数字控制颜色,第一位表示控制前/背景色,3-前景色,4-背景色,
[1m: 一位数字控制字体,加粗,闪烁,下划线等,1为加粗