您的位置:首页 > 运维架构 > Shell

Linux之编程:Linux Shell编程概述

2013-12-07 17:22 190 查看

简介

从程序员的角度来看, Shell本身是一种用C语言编写的程序,从用户的角度来看,Shell是用户与Linux操作系统沟通的桥梁(本质上来说,Shell每一行可以看做一个命令)。用户既可以输入命令执行,又可以利用 Shell脚本编程,完成更加复杂的操作。在Linux GUI日益完善的今天,在系统管理等领域,Shell编程仍然起着不可忽视的作用。深入地了解和熟练地掌握Shell编程,是每一个Linux用户的必修 功课之一。

Linux的Shell种类众多,常见的有:Bourne Shell(/usr/bin/sh或/bin/sh)、Bourne Again Shell(/bin/bash)、C Shell(/usr/bin/csh)、K Shell(/usr/bin/ksh)、Shell for Root(/sbin/sh),等等。不同的Shell语言的语法有所不同,所以不能交换使用。每种Shell都有其特色之处,基本上,掌握其中任何一种 就足够了。在本文中,我们关注的重点是Bash,也就是Bourne Again Shell,由于易用和免费,Bash在日常工作中被广泛使用;同时,Bash也是大多数Linux系统默认的Shell。在一般情况下,人们并不区分 Bourne Shell和Bourne Again Shell,所以,在下面的文字中,我们可以看到#!/bin/sh,它同样也可以改为#!/bin/bash。

Shell 基本格式

利用vi等文本编辑器编写Shell脚本的格式是固定的,如下:

#!/bin/sh

首行中的符号#!告诉系统其后路径所指定的程序即是解释此脚本文件的Shell程序。如果首行没有这句话,在执行脚本文件的时候,将会出现错误。

#comments

后续的部分就是主程序,Shell脚本像高级语言一样,也有变量赋值,也有控制语句。除第 一行外,以#开头的行就是注释行,直到此行的结束。如果一行未完成,可以在行尾加上",这个符号表明下一行与此行会合并为同一行。

Your commands go here

一个小的示例程序

#!/bin/sh
#example of shell
echo "first example"
echo #this inserts an empty line in output
echo "we are currently in the following directory"
/bin/pwd
echo
echo "this directory contains the following files"
/bin/ls


脚本执行

用户需要执行一个脚本,需要对这个脚本具有r权限,对脚本所在目录有rx权限。

l 创建一个包含命令和控制结构的文件。

l 修改这个文件的权限使它可以执行,使用chmod u+x

l 执行./example或者sh example

数据结构

变量定义

变量时shell传递数据的一种方法,用来代表每个取值的符号名。

Shell Script有两种类型的变量:

l 临时变量:Shell程序内部定义的,其使用范围仅限于定义它的程序,对其他程序不可见。包括了用户自定义变量、位置变量。

l 永久变量:永久变量是环境变量,其值不随shell脚本的执行结束而消失。

Shell Script是一种弱类型语言,其使用变量的时候不需要首先声明其类型。新的变量会在本地数据区分配内存进行存储,这个变量归当前的Shell所有,任何子进程都不能访问本地变量。

变量的辅助命令:

set

查看系统中所有定义的变量

unset 变量名

注意,不要加$符号

删除变量

用户自定义变量

变量赋值的方式是:

variable_name=variable_value

【注意】赋值号两边应该没有空格,否则variable_name会被当做一个命令。

如果对一个已经有值的变量赋值,新值将取代旧值。取值的时候要在变量名前加$,$variable_name可以在引号中使用,这一点和其他高级语言是明显不同的。如果出现混淆的情况,可以

v 用花括号来区分,例如:

echo "Hi, $as"

就不会输出“Hi, hello worlds”,而是输出“Hi,”。这是因为Shell把$as当成一个变量,而$as未被赋值,其值为空。正确的方法是:

echo "Hi, ${a}s"

v 使用单引号,单引号中的变量不会进行变量替换操作。

譬如:$ABC = “time is $Date”,echo $ABC的值为:time is 2013-12-4

$ABC = ‘time is $Date’,echo $ABC的值为:time is $Date

永久变量

位置变量和特殊变量

Shell 解释执行用户命令时,将命令行的第一个部分(实际的命令加选项)作为命令名,其它部分作为参数。由出现在命令行上的位置确定的参数称为位置参数。例如:

ls -l file1 file2 file3

$0 这个程序的文件名 ls -l

$n 这个程序的第n个参数值,n=1-9

特殊变量

$*

这个程序的所有参数

$#

这个程序的参数个数

$$

这个程序的PID

$!

执行上一个后台命令的PID

$?

执行上一个命令的返回值。

返回值为0表示上一个命令执行成功。

返回值不为0表示错误代码。

变量类型

基本类型

基本类型

定义时赋值,如NUM=1,$NAME=’Zhang’或者$NAME=”张”。

命令类型

将一个命令的执行结果赋给变量,如:TIME=`date`,此时`称为命令替换符或者TIME=$(date)。

变量

将一个变量赋值给另一个变量,如:A=$B

流程控制

变量测试Test

变量测试语句用于测试变量是否相等,是否为空,以及文件类型等等,基本格式为:

test 测试条件

文件测试

-b filename

当filename 存在并且是块文件时返回真(返回0)

-c filename

当filename 存在并且是字符文件时返回真

-d pathname

当pathname 存在并且是一个目录时返回真

-e pathname

当由pathname 指定的文件或目录存在时返回真

-f filename

当filename 存在并且是正规文件时返回真

-g pathname

当由pathname 指定的文件或目录存在并且设置了SGID 位时返回真

-h filename

当filename 存在并且是符号链接文件时返回真 (或 -L filename)

-k pathname

当由pathname 指定的文件或目录存在并且设置了"粘滞"位时返回真

-p filename

当filename 存在并且是命名管道时返回真

-r pathname

当由pathname 指定的文件或目录存在并且可读时返回真

-s filename

当filename 存在并且文件大小大于0 时返回真

-S filename

当filename 存在并且是socket 时返回真

-t fd

当fd 是与终端设备相关联的文件描述符时返回真

-u pathname

当由pathname 指定的文件或目录存在并且设置了SUID 位时返回真

-w pathname

当由pathname 指定的文件或目录存在并且可写时返回真

-x pathname

当由pathname 指定的文件或目录存在并且可执行时返回真

-O pathname

当由pathname 存在并且被当前进程的有效用户id 的用户拥有时返回真(字母O 大写)

-G pathname

当由pathname 存在并且属于当前进程的有效用户id 的用户的用户组时返回真

file1 -nt file2

file1 比file2 新时返回真

file1 -ot file2

file1 比file2 旧时返回真

f1 -ef f2

files f1 and f2 are hard links to the same file

逻辑测试

-a

逻辑与,操作符两边均为真,结果为真,否则为假。

-o

逻辑或,操作符两边一边为真,结果为真,否则为假。

!

逻辑否,条件为假,结果为真。

举例: [ -w result.txt -a -w score.txt ] ;echo $? // 测试两个文件是否均可写

字符串测试

-z string

字符串string 为空串(长度为0)时返回真

-n string

字符串string 为非空串时返回真

str1 = str2

字符串str1 和字符串str2 相等时返回真

str1 == str2

同 =

str1 != str2

字符串str1 和字符串str2 不相等时返回真

str1 < str2

按字典顺序排序,字符串str1 在字符串str2 之前

str1 > str2

按字典顺序排序,字符串str1 在字符串str2 之后

举例: name="zqf"; [ $name = "zqf" ];echo $? // 打印 0 表示变量name 的值和字符串"zqf"相等

常见数值测试

常见数值测试

int1 -eq int2

如果int1 等于int2,则返回真

int1 -ne int2

如果int1 不等于int2,则返回真

int1 -lt int2

如果int1 小于int2,则返回真

int1 -le int2

如果int1 小于等于int2,则返回真

int1 -gt int2

如果int1 大于int2,则返回真

int1 -ge int2

如果int1 大于等于int2,则返回真

在 (()) 中的测试:

<

小于(在双括号里使用)

(("$a" < "$b"))

<=

小于等于 (在双括号里使用)

(("$a" <= "$b"))

>

大于 (在双括号里使用)

(("$a" > "$b"))

>=

大于等于(在双括号里使用)

(("$a" >= "$b"))

If 语句

变量测试语句一般不单独使用,一般作为if语句的测试条件,譬如:

if test -d $1 then

...

elif 条件2 then

...

fi

而变量测试语句可用[]进行简化,譬如:

test -d $1

等价于

[ -d $1 ]

Case

case 变量 in

字符串1) 命令列表1

;;

...

*) 通用命令

;;

esac

循环

While

while 条件

do

命令

done

Until

until 条件

do

命令

done

until类似于while循环,不同的是until是条件返回值为假时才继续执行。

For

for 变量 in 名字列表

do

命令列表

done

#!/bin/sh

for DAY in Sunday Monday Tuesday

do

echo "The day is : $DAY"

done

For语句也可以如下使用:

Vi hello.sh

#!/bin/bash

for((i=0;i<3;i++))

do

echo $i

done

流控制语句

v continue:继续当前循环

v break:跳出当前循环

Shell 命令

I/O输入输出

控制行

read

从键盘读入数据,赋值给变量

使用格式:

read UserName Para1 Para2,...

注意

l 输入参数个数小于定义,则缺省不赋值。

l 输入参数个数多于定义,则多余的参数会一次性赋给最后一个变量。

select

select 变量 in 关键字

do

command 1

...

command n

done

#!/bin/sh

echo "You choice?"

select var in "a" "b" "c";do

break;

done

echo $var

如果提示select not found,则

把#!/bin/sh改为#!/bin/bash

执行脚本时将sh select.sh改为 bash select.sh

tee

读取标准输入的数据,并将其内容输出成文件。

语法:

tee [-ai][--help][--version][文件...]

参数:

-a或--append :附加到既有文件的后面,而非覆盖它.

-i-i或--ignore-interrupts :忽略中断信号。

--help :在线帮助。

--version :显示版本信息。

文件输入

运算

算术运算

expr

对整数型变量进行算术运算,注意运算参数之间的空格不可以省略。

expr 3 + 5

expr $var1 - 5

expr $var1 / $var2

expr $var3 \* 10 乘法需要转义字符

let

let 是 bash 內建的整數運算。arg 代表運算式。

當得到的值為 0,回應狀態值 1,其他數值,則回應狀態值 0。

#!/bin/bash

let "t1 = ((a = 5 + 3, b = 7 - 1, c = 15 - 4))"

echo "t1 = $t1, a = $a, b = $b"

#!/bin/bash

let a=5+4 b=9-3

echo $a $b

进程控制

流程

exit

退出程序执行,并返回一个返回码,返回码为0表示正常退出,非0表示非正常退出

exit 0

字符串

统计

wc 命令

Linux系统中的wc(Word Count)命令的功能为统计指定文件中的字节数、字数、行数,并将统计结果显示输出。

1.命令格式:

wc [选项]文件...

2.命令功能:

统计指定文件中的字节数、字数、行数,并将统计结果显示输出。该命令统计指定文件中的字节数、字数、行数。如果没有给出文件名,则从标准输入读取。wc同时也给出所指定文件的总统计数。

3.命令参数:

-c 统计字节数。

-l 统计行数。

-m 统计字符数。这个标志不能与 -c 标志一起使用。

-w 统计字数。一个字被定义为由空白、跳格或换行字符分隔的字符串。

-L 打印最长行的长度。

-help 显示帮助信息

--version 显示版本信息

实例1:查看文件的字节数、字数、行数

命令:

wc test.txt

分隔

awk -F

域分隔符‘命令’

示例:

1、检测系统中UID为0的用户

awk -F: ‘$3==0 {print $1}’ /etc/passwd

2、检测系统中密码为空的用户

awk -F: ‘length($2)==0 {print $1}’ /etc/shadow

调试

sh -x script:使用+号表示脚本执行情况。

sh -n script:不执行脚本只是进行脚本的语法检测,返回所有的错误。

************DEMO************

文件管理

删除

自动清除过时文件

1创建shell:

touch /opt/soft/bin/auto-del-30-days-ago-log.sh

chmod +x auto-del-30-days-ago-log.sh

新建一个可执行文件auto-del-30-days-ago-log.sh,并分配可运行权限

2编辑shell脚本:

vi auto-del-30-days-ago-log.sh

编辑auto-del-30-days-ago-log.sh文件如下:

#!/bin/sh

find /opt/soft/log/ -mtime +30 -name "*.log" -exec rm -rf {} \;

3计划任务:

#crontab -e

将auto-del-30-days-ago-log.sh执行脚本加入到系统计划任务,到点自动执行

输入:

10 0 * * * /opt/soft/log/auto-del-7-days-ago-log.sh >/dev/null 2>&1

这里的设置是每天凌晨0点10分执行auto-del-7-days-ago-log.sh文件进行数据清理任务了。

搜索

监控指定大小的文件

查找当前目录中所有大于500M的文件,把这些文件名写到一个文本文件中,并统计其个数。

find ./ -size +500M -type f | tee file_list | wc -l

在目录/tmp下找到100个以abc开头的文件,然后把这些文件的第一行保存到文件new中。

for filename in `find /tmp -type f -name "abc*"|head -n 100`

do

sed -n '1p' $filename>>new

done

每隔10分钟监控一次,监控/usr下如果大于5G,发邮件给管理员

#!/bin/bash

while true

do

sleep 600

n=$(du -s /usr | cut -f1)

if [ $n -gt 5242880 ]

then

mail -s "greater" filwsyl@gmail.com < ~/filename #将文件filename的内容发送出去。

fi

done

监控指定路径的文件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: