Linux脚本能力不是太强,最近再补习下,毕竟linux shell在日常工作中还是很普遍的,

用起来更方便、省时省力。


以下是学习笔记,偏理论,后面有几个例子,供参考。


shell脚本组成元素
系统命令、文本处理工具(grep\sed等)、变量、条件判断、循环结构和函数

--------------------------------------------

三剑客:grep,sed,awk,还有wc,sort,head等

------------------------------------------------

echo:
echo -e “\033[40;35m...\033[0m”
背景颜色:40-49,40黑色,41红色,42绿色,43***...
字体颜色:30-39,30黑色,31红色,32绿色...

-------------------------------------------------------

sort:
-d 按字典顺序排序
-n 按数字大小输出
-r 逆序输出排序结果
-k 指定分类是域上的数字分类
-t 域分隔符;用非空格或tab分割域

sort -k3 -n -r -t:/etc/passwd
以第三个域的分类,按照数字的逆序排列

----------------------------------------------------

wc:
-c 统计字符数量
-l 统计行数
-w 统计单词数量

-----------------------------------------

diff:
对文件进行比较

------------------------------------------------------

grep:
-n 在每行前显示其行的编号
-v 逆向输出,打印不匹配的行

忽略大小写
grep ‘[Tt]his’ file.txt

过滤出非#开头的行
grep ‘^[^#]’ file.txt

模糊匹配
grep “s...n” file.txt

----------------------------------------------------

sed:行编辑器
s 替代
i 行前插入
a 行后插入
d 删除全部匹配的行
D 删除首次匹配的行

sed -n ‘1,4p’ /etc/passwd
-n防止打印原本的文本,只打印修改后的输出
p打印
1,4第一行到第四行

sed '/80/D' file.txt
删除首次匹配到80的行

sed ‘s/var/usr/g’ file.txt
用var替代usr
s是替代
g表示全部替代
没有g则是首次匹配替代

sed ‘50,¥s/help/man/g’file.txt
替代50行之后的

---------------------------------------------

awk:列编辑器
-F ; 以;为分隔符
NR 当前处理的行数
NF 当前处理的列数
¥0 选取整行
¥1 第一列
¥NF 最后一列

awk -F :‘{print NR,¥1,¥2}’ /etc/password
以:为分隔符,打印出第一列和第二列的内容

awk -F :‘{print NR,¥1,¥NF}’ /etc/password
打印出第一列和最后一列

-----------------------------------------------------

脚本规范
#!/bin/bash
#注释
正文

脚本执行权限
chmod u+x hello.sh   #u指users,x指执行权限
./hello.sh


本地变量
只在当前用户下的当前shell中,当用户退出shell则变量不存在
a=1
echo ¥a   #如果后面有单位则echo ¥{a}m
1

环境变量:
适用于所有用户进程,用户注销时失效

位置变量:
用于指定变量位置

特殊变量:
¥#         列出传递给脚本的所有参数
¥*(¥@)  用一个字符显示所有向脚本传递的参数
¥¥        脚本运行的当前进程ID号
¥?        显示最后命令的退出状态。0表示没有错误,其他值则表示异常

“”  可引用除¥、`、\、字符以外的任意字符或字符串
‘’  与双引号类似,但是shell会忽略任何的引用值,屏蔽其特殊含义
`     shell将反引号的内容作为系统命令并执行
\     如字符有特殊含义,反斜线会屏蔽其特殊含义,防止误解

echo -e   -e是转译符  \n换行

------------------------------------------------

date +%T 显示系统当前时间
uptime 显示系统CPU负载

条件测试:
test -option xxx
返回0表示真,返回1表示假,返回其他值结果同样为假
xxx

-d 目录
-e 是否存在
-f 是否为普通文件
-s 文件大小是否等于0
-r -w -x 是否可读 可写 可执行

-a 与操作
-o 或操作
! 非操作

== 两个字符串相等
!= 两个字符串不等
-z 空字符串
-n 非空字符串

-eq 等于
-ne 不等于
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于

条件选择:
if...else...fi

if 条件
then        #条件为真
  命令1
else        #条件为假
  命令2
fi           #结束


case...in...esac

case variable in
  模式1命令1..;;
  模式2命令2..;;
esca

*  匹配任意字符
? 匹配任意单字符
[] 匹配字符范围

---------------------------------------------

循环结构:

for variable in list
do
  命令1
  命令2
done

for i in `seq 1 3`
do
  ssh hostname-$i
  service httpd restart
done

while支持死循环

while 条件
do
  命令1
  命令2
done

-------------------------------------------------------------------

函数结构
#!/bin/bash
#
function 函数名()
{
  命令1
  ...
}


单次任务调度
@ 指定时间调度一次性任务

@ [选项] time
  -f 从文件中读取命令或者脚本
  -m 作业完成发mail
  -v 显示执行时间
启动服务
service atd start

删除任务 at rm

at -f test.sh 10:00pm Feb 11

Crontab 定期运行脚本
  -e 添加时间和脚本等任务
  -l 列出已经添加的时间和脚本任务
  -r 删除目前的任务
  -v 列出任务状态

全局  /etc/crontab
用户  /var/spool/cron   使用-e添加即在当前用户下

crontab用户控制
/etc/cron.allow
/etc/cron.deny

*  *  *  *  *   分 时 日 月 星期几

*/5 每五分钟

-------------------------------------------------------------

举例1:
日期     昨天     今天     涨跌   涨幅
...
20080413 3,384.43 3,294.83 -54.37 -1.239%
20080621 3,3254.43 3,454.83 59.31 3.231%
...

列出20081011的所以数据
grep "20081011" shanghai.txt

列出200806月份上涨的数据
grep "200806" shanghai.txt | grep -v "-"
-v 取反,理解为获取非“-”的数据

grep "200808" shanghai.txt |wc -l
对8月份的数据进行数量统计

获取8月份涨幅最大的数据
grep "200808" shanghai.txt | sort -k5 -n | tail -1
-k5 以第五列进行排序
-n  按照数字大小进行排序
-r  逆序排列

sed -n "$p"   取最后一行
sed -n "1p"   取第一行
head -1       第一行

列出10月份上涨的数据,仅取日期和涨幅
grep "200810" shanghai.txt | awk '{if($4>0){print $1,$5}}'
awk支持shell语句

列出十月份涨幅在5-80之间的数据
grep "200810" shanghai.txt | awk '{if($4>5 && $4<80){print $0}}'
$0 整行

--------------------------------------------------------

举例2:
top -n 1    此时这一秒的系统负载情况

#!/bin/bash
#
CpuIdle=""
top -n 1 > sysinfo.txt
CpuIdle=`cat sysinfo.txt |grep "Cpu" |awk '{print $5}'|awk -F i '{print $1}'`
echo "Cpu Idle:${CpuIdle}"

echo 3 >/proc/sys/vm/drop_caches   丢弃缓存,与脚本无关

----------------------------------------------------------

举例3:
是否可以ping通192.168.1.1,给出结果
if ping 192.168.1.1 -c 1
then
  echo "192.168.1.1 online"
else
  echo "192.168.1.1 offline"

----------------------------------------

举例4:
将ip写入iplist文本里
>hoststatus.txt
for ip in `cat iplist`
do
  if ping ${ip} -c 1 >/dev/null 2>&1
  then
    echo "${ip} online" | tee -a hoststatus.txt
  else
    echo "${ip} offline" | tee -a hoststatus.txt
done

sort -t. -k4 -n hoststatus.txt
以.为分割域,以第四列数字排序

----------------------------------------

规范:
尽量少于单引号‘’
对个别特殊字符进行特殊含义屏蔽时,使用\
使用单引号进行特殊字符屏蔽时,单引号内一般不使用其他引用符号
使用反引号``执行一个shell命令时,一般加其他引用符号

#在脚本中一般用于描述性注释
;在脚本中一般用于示例性注释

变量名由数字和字母组成
最好采用全小写英文
尽量缩写,最好不超过6个字符

脚本最好以全英文小写命名
版本号或者日期或者其他用途可以使用. _ -等符号
尽量避免? * 空格 ¥ &等
脚本命名不得以数字打头
test.1.sh

函数规范
变量名可以由数字和字母组成
使用驼峰命名法   即首字母大写
支持多个单词命名,但是最好不要超过两个
尽量不要缩写,除非众所周知