更多笔记点击查看
Linux学习从入门到打死也不放弃,完全笔记整理(持续更新)
https://blog.51cto.com/13683480/2095439
笔记整理开始时间:2018年4月12日11:37:35
本章内容:
编程基础
脚本基本格式
变量
运算
条件测试
配置用户环境
编程基础:
程序:指令+数据
程序编程风格:
过程式:以指令为中心,数据服务于指令
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤
一步一步实现,使用的时候一个一个依次调用就可以了
对象式:以数据为中心,指令服务于数据
面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为
了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为
shell程序:提供了编程能力,解释执行
是对一堆Linux命令的逻辑化处理
程序的的执行方法:
计算机:运行二进制指令
编程语言:
低级:汇编
高级:
编译:高级语言-->编译器-->目标代码
在编译时将代码转换成2进制
java,c#
解释:高级语言-->解释器-->机器代码
在程序执行时才转换成2进制
shell,perl,python
编程基本概念:
编程逻辑处理方式
顺序执行,循环执行,选择执行
shell编程:过程式,解释执行
编程语言的基本结构:
各种系统命令的组合
数据存储:变量、数组
表达式:a + b
语句:if
shell脚本基础:
shell脚本:
包含一些命令或声明,并符合一定格式的文本文件
格式要求:首行shebang机制
#!/bin/bash shell
#!/usr/bin/python python
#!/usr/bin/perl perl
shell脚本的用途有:
自动化常用命令
执行系统管理和故障排除
创建简单的应用程序
处理文本或文件
创建shell脚本:
第一步:使用文本编辑器来创建文本文件
第一行必须包括shell声明序列:#!
#!/bin/bash
添加注释
注释以#开头
第二步:运行脚本
给予执行权限,+x,在命令行上指定脚本的绝对或相对路径
/root/hello
直接运行解释器(bash),如:
bash /root/hello
cat ff115 |bash
PS:source 执行程序 表示脚本会在当前shell运行不开启子进程
脚本规范:
1.第一行一般为调用使用的语言
2.程序名,避免更改文件名为无法,正确找到的文件
(如不要取名bash,或者其他存在的程序名)
3.版本号
4.更改后的时间
5.作者相关信息
6.该程序的作用。以及注意事项
7.最后是各版本的更新简要说明
脚本基本结构
#!shebang
configuration_variables 配置变量
function_definitions 定义函数
main code 主要代码
脚本调试:
检测脚本中的语法错误
bash -n hello.world
如:
[root@sentos7 ~/bin]#bash -n ceshi
ceshi: line 2: unexpected EOF while looking for matching `"'
ceshi: line 7: syntax error: unexpected end of file
调试执行:
bash -x hello.world
PS:
bash -n 只检查语法错误
如果是语法错误后续命令不执行
如果是命令not found 后续会继续执行
bash -x +代表深度,直接执行+,被调用执行++
脚本内不支持别名,也无法添加别名
变量:命名的内存空间
数据存储方式:
把程序中准备使用的数据赋给一个简短、易于记忆的名字
类型:
字符型
数值:×××,浮点型
作用:
数据存储
参与运算
表示数据范围
强类型:
变量不经过强制转换,它永远是这个数据类型,不允许隐式的类型转化。一般
定义变量时必须指定类型,参与运算必须符合类型要求;调用未声明变量会
产生错误。
如jave c#
弱类型:
语言的运行时会隐式做数据类型转换。无须指定类型,默认均为字符型,参
与运算会自动进行隐式类型转换,变量无须事先定义可直接调用
如:bash不支持浮点数, php
变量命名法则:
1.不能使用程序中的保留字;例如:if ,for
2.只能使用数字、字母及下划线,且不能以数字开头
3.见名知义
4.统一命名规则:驼峰命名法
bash中变量的种类:
根据变量的生效范围等标准等标准划分下面变量类型:
局部变量:
生效范围为当前shell进程;对当前shell之外的其他shell进程,
包括当前shell的子shell进程均无效
环境(全局)变量:
生效范围为当前shell进程及其子进程
本地变量:生效范围为当前shell进程中某代码片段,通常指函数
位置变量:$1,$2,..${10}..来表示,用于让脚本在脚本代码中调用通过命令行传递
给它的参数
特殊变量:
$?,$0,$*,$@,$#,$$
$? 前一个命令的退出状态,成功为0,不成功为非0
局部变量:
变量赋值:name='value'
可以使用引用value:
1.可以是直接字串; name=‘root’
2.变量引用: name=$USER
3.命令引用: name=`command`
name=$(cmd)
ps:
变量一旦赋值,除非重新赋值,否则所占内存空间不变,值不变
name1=name2的情况
就算赋值之后name2的值改变了,name1的值保持不变
i=100 赋值为字符,不问数字类型
变量引用:
${name} $name
"":弱引用,其中的变量引用会被替换为变量值,如
[root@sentos7 ~/bin]#echo "$PS1"
\[\e[1;35m\][\u@\h \w]\$\[\e[0m\]
'':强引用,其中的变量引用不会被替换为变量值,而保持原字符串
[root@sentos7 ~/bin]#echo '$PS1'
$PS1
显示已经定义的所有变量:set
删除变量: unset name
PS:
pstree -p 进程tree
echo $$ 当前进程的进程编号
echo $PPID 父进程的进程编号
练习1
1、编写脚本/root/bin/systeminfo.sh,显示当前主机系统信息,包括主机名,
IPv4地址,操作系统版本,内核版本,CPU型号,内存大小,硬盘大小
2、编写脚本/root/bin/backup.sh,可实现每日将/etc/目录备份到
/root/etcYYYY-mm-dd中
3、编写脚本/root/bin/disk.sh,显示当前硬盘分区中空间利用率最大的值
4、编写脚本/root/bin/links.sh,显示正连接本主机的每个远程主机的IPv4地址
和连接数,并按连接数从大到小排序
环境变量:
变量声明,赋值:
export name=Value 相当于name=Value;export name
declare -x name2=Value
let c=name+name2;export c
变量引用:$name,${name2}
显示所有环境变量:
env
printenv
export
declare -x
删除变量:
unset name
bash内建的环境变量:
PATH:
SHELL:
USER:
UID:
HOME:
PWD:
SHLVL: 当前shell层数
LANG: 语言键盘、字符编码
MAIL: 当前用户mail目录
HOSTNAME:
HISTSIZE:
_: 前一个命令的最后一个参数
只读和位置变量:
只读变量:只能声明,但不能修改和删除
声明只读变量:
readonly name
declare -r name
查看只读变量:
readonly -p
位置变量:再脚本代码中调用通过命令行传递给脚本的参数
$1,$2,..${10}..: 对应相应第1,2..10..个参数
脚本中命令:shift[n] 可以传递参数位置,如:
shift 可以将原本$2,变成$1
shift 3 将原$4变成$1
$0 命令本身,名字
默认带路径,可以用 `basename $0`取出来
$0 如果是软链接的话 $0会显示各自软链接的名字
$* 传递给脚本的所有参数,全部参数合为一个字符串
$@ 传递给脚本的所有参数,每个参数为独立字符串
$# 传递给脚本的参数的个数
$@ $* 在脚本调用脚本传递参数时,如果用"$*",会将所有参数当成一个
字符串传递
$* $@ "$@" 会将每个参数单独传递
set -- 清空所有位置变量
退出状态
进程使用退出状态来报告成功或失败
$? 保存最近的命令退出状态
0 成功
1-255 失败
例如:
ping -c1 172.20.3.14 &>/dev/null
echo $?
退出状态码:
bash 自定义退出状态码
exit [n] 自定义退出状态码
注意:
脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于
exit命令后面的数字
如果没有给脚本指定退出状态码,整个脚本的退出状态码取决于脚本
中执行的最后一条命令的状态码
算术运算:let
bash中的算术运算:help let
常用算术:
+,-,*,/,%(取模 取余),**(乘方),id++,id--,
实现算术运算的格式:
1. let var=算术表达式
let z=x+y;let x++;let y=x**2;
let z=(3*x+4*y/3)-2*x
2. var=$[算术表达式]
z=$[(3*x+4*y/3)-2*x]
3. var=$((算术表达式))
z=$(((3*x+4*y/3)-2*x))
4. var=$(expr arg1 arg2 arg3...)
如:z=$(expr $x + $y) 表示z=x+y
*需要写成\*
5. declare -i var=数值(可以使是算式)
declare -i x=x+y
declare -i x=3*x+y*4/2
6. echo ’算术表达式‘ |bc
bash有内建的随即数生成器:$RANDOM(0-32676)
echo $[$RANDOM%50]: 0-49之间随机数
赋值:
增强型赋值:
+=,-=,*=,/=,%=
let x+=3;x-=1;x*=5;x/=4
+3 -1 *5 /4
shell不支持浮点计算,所以除法会有商整取余
自增,自减
let x+=1;let x++
let x-=1;let x--
练习2
1、编写脚本/root/bin/sumid.sh,计算/etc/passwd文件中的第10个用户和第
20用户的ID之和
2、编写脚本/root/bin/sumspace.sh,传递两个文件路径作为参数给脚本,计
算这两个文件中所有空白行之和
3、编写脚本/root/bin/sumfile.sh,统计/etc, /var, /usr目录中共有多少个一级
子目录和文件
逻辑运算
与: &
或: |
非: !
!1=0
!0=1
短路运算:
cmd1 && cmd2
如果cmd1为假,cmd2不需要执行,反之cmd1为真,需要cmd2执行
cmd1 || cmd2
如果cmd1为真,cmd2不需要执行,反之cmd1为假,需要cmd2执行
cmd1 && cmd2 || cmd3 要求cmd2必真
cmd1为真,执行cmd2
为假,执行cmd3
异或:^ XOR
二进制运算,同为0 异为1
a=5;b=6;echo $a $b;a=$[a^b];b=$[a^b];a=$[a^b];echo $a $b
将a b的值互换
ture 和false
只返回真或者假,不做任何操作
true && echo hello
false && echo hello||echo nihao
条件测试:test
判断某需求是否满足,需要由测试机制来实现
专用的测试表达式需要由测试命令辅助完成测试过程
评估布尔声明,以便用在条件性执行中
若真 则返回0
若假 则返回1
测试命令:
test expression 如:test a = b ;echo $?
[ $a = b ] && echo ture || echo false
[[ $a =~ pattern ]]
表达式epression 前后必须有空白字符
根据退出状态而定,命令可以有条件的执行
&& 代表条件性的and then
|| 代表条件性的 or else
例如:
grep -q no_such_user /etc/passwd || echo 'NO such user'
id usera &>/dev/null && echo "usera is exist" || useradd usera
长格式的例子:
test "$A" == "$B" && echo "Strings are equal"
[ "$A" == "$B" ]
test "$A" -eq "$B" && echo "Integers are equal"
[ "$A" -eq "$B" ]
bash的数值测试:
-v var
变量是否设置 test -v var && echo hello||echo nihao
[ -v var ] && set || not set
PS:
此处使用变量var前不可加"$",否则判断异常
数值测试:
-gt 是否大于 [ $A -gt $B ]
-ge 是否大于等于
-eq 是否等于
-ne 是否不等于
-lt 是否小于
-le 是否小于等于
bash的字符串测试:
== 是否等于 等于为真,0
> ascii码是否大于ascii码
< 是否小于
!= 是否不等于 不等于为真,0
=~ 左侧字符串是否能够被右侧的pattern所匹配
注意:此表达式一般用于[[ ]]中,支持扩展的正则表达式
-z "string" 字符串是否为空,空为真,不空为假
-n "string" 字符串是否不空,不空为真,空为假
注意: 用于字符串比较时用到的操作数都应该使用引号
[[ ]]使用pattern时 表达式 不能加引号 ,也不能识别\< \> \b
判断是否为空也可以:
[ x = x"$a" ] && echo ture || echo false
练习3:
1、编写脚本/root/bin/argsnum.sh,接受一个文件路径作为参数;如果参数
个数小于1,则提示用户“至少应该给一个参数”,并立即退出;如果参数个数
不小于1,则显示第一个参数所指向的文件中的空白行数
2、编写脚本/root/bin/hostping.sh,接受一个主机的IPv4地址做为参数,测
试是否可连通。如果能ping通,则提示用户“该IP地址可访问”;如果不可
ping通,则提示用户“该IP地址不可访问”
3、编写脚本/root/bin/checkdisk.sh,检查磁盘分区空间和inode使用率,如
果超过80%,就发广播警告空间将满
Bash的文件测试:
存在性测试:
-a file 同 -e
-e file 文件存在性测试,存在为真,否则为假
存在性及类别测试
-b file 是否存在且为块设备文件
-c file 是否存在且为字符设备文件
-d file 是否存在且为目录文件
-f file 是否存在且为普通文件
-h file 或 -L file 是否存在且为符号链接文件
-p file 是否存在且为命名管道文件
-S file 是否存在且为套接字文件
Bash的文件权限测试:
文件权限测试:
-r file 是否存在且可读
-w file 是否存在且可写
-x file 是否存在且可执行
文件特殊权限测试:
-u file 是否存在且拥有suid权限
-g file 是否存在且拥有sgid权限
-k file 是否存在且拥有sticky权限
Bash的文件属性测试:
文件大小测试:
-s file 是否存在且为空
文件是否打开
-t fd:fd 文件描述符是否在某终端已经打开
-N file 文件自从上一次被读取之后是否被修改过
-O file 当前用户是否为文件属主
-G file 当前有效用户是否为文件属组
双目测试:
file1 -ef file2 file1是否是file2的硬链接
file1 -nt file2 file1是否新于file2 (mtime)
file1 -ot file2 file1是否旧与file2
Bash的组合测试条件:
第一种方式:
cmd1 && cmd2 且
cmd1 || cmd2 或
!cmd 非
如: [[ -r FILE ]] && [[ -w FILE ]]
第二种方式:
[ expression1 -a expression2 ] 并且
[ expression1 -o expression2 ] 或者
[ !expression ] 非
例:
[ -z "$HOSTNAME" -o "$HOSTNAME" == "localhost.localdomain" ] &&
hostname www.magedu.com
[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab
PS:
&&(-a) ||(-o)可连续使用
[ -r "$1" -a -w "$1" -a -x "$1" ] && echo ture || false
[ -a "$1" ] && [ -r "$1" ] && [ -w "$1" ] && [ -x "$1" ] && echo ture || false
只要有一个为假,就返回假
[ -r "$1" -o -w "$1” -o "$1" ] && echo ture || false
[ -r "$1" ] || [ -w "$1" ] || [ -x "$1"] && echo ture || false
只要一个为真,则返回为真
练习:
1、编写脚本/bin/per.sh,判断当前用户对指定参数文件,是否不可读并且不可写
2、编写脚本/root/bin/excute.sh ,判断参数文件是否为sh后缀的普通文件,如
果是,添加所有人可执行权限,否则提示用户非脚本文件
3、编写脚本/root/bin/nologin.sh和login.sh,实现禁止和充许普通用户登录系统
read:
使用read来把输入值分配给一个或多个shell变量
-p 指定要显示的提示,如:
read -p "Please input your name: " name
-s 静默输入,一般用于密码,如:
read -s -p "Please input your password: " passw
-n N 指定输入的字符长度N
指定长度之后,如达到长度,后续指令不会换行,直接在输入的内容之后显示了
想要达到换行的目的,需要下一行加上
echo "" 但是如果手动回车则会显示一行空行
-d '字符' 输入结束符 到此字符直接结束输入
read -t 20 -n 20 -p "Please input you ID, end with'#' : " ID
与-n类似,也是不会换行
-t N TIMEOUT为N秒
timeout并不会退出脚本,而是会执行后续指令
read 如果从标准输入中读取值,给每个单词分配一个变量
所有剩余单词都被分配给最后一个变量
不支持管道接受标准输入 | read name
bash如何展开命令行
把命令行分成单个命令词
展开别名
展开大括号的声明({})
展开波浪符声明(~)
命令替换$()和(``)
再次吧命令行分成命令词
展开文件通配(*、?、[abc]等等)
准备I/O重导向(<,>)
运行命令
防止扩展:
反斜线 \ 会使随后的字符按原意解释
$ echo your cost:\$5.00
your cost:$5.00
加引号来防止扩展
单引号'' 防止所有扩展
双引号"" 也防止所有扩展,但是以下情况例外
$ --变量扩展
`` $() --命令替换
\ --禁止单个字符扩展
! --历史命令替换
bash的配置文件:
按生效范围划分、存在两类
全局配置:
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
个人配置:
~/.bash_profile
~/.bashrc
shell登录两种方式
交互式登录:
1)直接通过终端输入账号密码登录
2)使用 su - username 切换的用户
执行顺序:
/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile -->
~/.bashrc --> /etc/bashrc
非交互式登录:
1)su username
2)图形界面下打开的终端
3)执行脚本
4)任何其他的bash实例
执行顺序:~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh
按功能划分:
profile类:
为交互式登录的shell提供配置
全局:/etc/profile, /etc/profile.d/*.sh
个人:~/.bash_profile
功能:
用于定义环境变量
运行命令或脚本
bashrc类:
为交互式和非交互式登录的shell提供配置
全局:/etc/bashrc
个人:~/.bashrc
功能:
定义命令别名和函数
定义本地变量
配置文件修改生效:
修改profile和bashrc文件后需生效
两种方法:
重新启动shell进程(重新登录)
. 或 source
例如: . ~/.bashrc
Bash退出任务:
保存在~/.bash_logout文件中
在退出登录shell时运行
用于:
创建自动备份
清楚临时文件
变量:$-
h:hashall,打开这个选项后,shell
会将命令所在的路径hash下来,避免每次都要查询。通过set+h将h选项关闭
i:interactive-comments,包含这个选项说明当前的shell是一个交互式的shell
所谓的交互式shell,在脚本中,i选项都是关闭的
m:monitor,打开监控模式,就可以通过job control来控制进程的停止、继续、
后台或者前台执行等。
B:braceexpand,大括号扩展
H:history,H选项打开,可以展开历史列表中的命令,可以通过!来完成,
例如!!,返回最近的一个历史命令,!n 返回第n个历史命令
练习:
1、让所有用户的PATH环境变量的值多出一个路径,例如:
/usr/local/apache/bin
2、用户root登录时,将命令指示符变成红色,并自动启用如下别名:
rm=‘rm –i’
cdnet=‘cd /etc/sysconfig/network-scripts/’
editnet=‘vim /etc/sysconfig/network-scripts/ifcfg-eth0’
editnet=‘vim /etc/sysconfig/network-scripts/ifcfg-eno16777736 或 ifcfg-ens33 ’ (如果系
统是CentOS7)
3、任意用户登录系统时,显示红色字体的警示提醒信息“Hi,dangerous!”
4、编写生成脚本基本格式的脚本,包括作者,联系方式,版本,时间,描述等
5、编写用户的环境初始化脚本reset.sh,包括别名,登录提示符,vim的设置,
环境变量等
笔记整理完成时间:2018年4月13日16:58:39