转自:http://www.cnblogs.com/feisky/archive/2010/03/31/1701560.html
说明:说明:在学习linux下shell编程时,可以在看完此篇后再看下上一篇的Linux Shell编程语法基础这篇文章(如果没看的话),这两篇文章具有互补作用。
我们可以使用任意一种文字编辑器,比如gedit、kedit、emacs、vi等来编写shell脚本,它必须以如下行开始(必须放在文件的第一行):
# !/bin/sh
注意:最好使用“!/bin/bash”而不是“!/bin/sh”,如果使用tc shell改为tcsh,其他类似。
符号#!用来告诉系统执行该脚本的程序,本例使用/bin/sh。编辑结束并保存后,如果要执行该脚本,必须先使其可执行:
chmod +x filename
此后在该脚本所在目录下,输入 ./filename 即可执行该脚本。
目录
- 1 变量赋值和引用
- 2 Shell里的流程控制
- 2.1 if 语 句
- 2.2 && 和 || 操作符
- 2.3 case 语句
- 2.4 select 语句
- 2.5 while/for 循环
- 3 Shell里的一些特殊符号
- 3.1 引号
- 4 Here Document
- 5 Shell里的函数
- 6 Shell脚本示例
- 6.1 二进制到十进制的转换
- 6.2 文件循环拷贝
- 7 脚本调试
变量赋值和引用
Shell编程中,使用变量无需事先声明,同时变量名的命名须遵循如下规则:
需要给变量赋值时,可以这么写:
变量名=值
要取用一个变量的值,只需在变量名前面加一个$ ( 注意: 给变量赋值的时候,不能在"="两边留空格 )
#!/bin/sh
# 对变量赋值:
a="hello world" #等号两边均不能有空格存在
# 打印变量a的值:
echo "A is:" $a
挑个自己喜欢的编辑器,输入上述内容,并保存为文件first,然后执行 chmod +x first 使其可执行,最后输入 ./first 执行该脚本。其输出结果如下:
A is: hello world
有时候变量名可能会和其它文字混淆,比如:
num=2
echo "this is the $numnd"
上述脚本并不会输出"this is the 2nd"而是"this is the ";这是由于shell会去搜索变量numnd的值,而实际上这个变量此时并没有值。这时,我们可以用花括号来告诉shell要打印的是num变量:
num=2
echo "this is the ${num}nd"
其输出结果为:this is the 2nd
需要注意shell的默认赋值是字符串赋值。比如:
var=1
var=$var+1
echo $var
打印出来的不是2而是1+1。为了达到我们想要的效果有以下几种表达方式:
let "var+=1"
var=$[$var+1]
var=`expr $var + 1`#注意加号两边的空格,否则还是按照字符串的方式赋值。
注意:前两种方式在bash下有效,在sh下会出错。
let表示数学运算,expr用于整数值运算,每一项用空格隔开,$[]将中括号内的表达式作为数学运算先计算结果再输出。
Shell脚本中有许多变量是系统自动设定的,我们将在用到这些变量时再作说明。除了只在脚本内有效的普通shell变量外,还有环境变量,即那些由export关键字处理过的变量。本文不讨论环境变量,因为它们一般只在登录脚本中用到。
Shell里的流程控制
if 语 句
"if"表达式如果条件为真,则执行then后的部分:
if ....; then
....
elif ....; then
....
else
....
fi
大多数情况下,可以使用测试命令来对条件进行测试,比如可以比较字符串、判断文件是否存在及是否可读等等……通常用" [ ] "来表示条件测试,注意这里的空格很重要,要确保方括号前后的空格。
[ -f "somefile" ] :判断是否是一个文件
[ -x "/bin/ls" ] :判断/bin/ls是否存在并有可执行权限
[ -n "$var" ] :判断$var变量是否有值
[ "$a" = "$b" ] :判断$a和$b是否相等
执行man test可以查看所有测试表达式可以比较和判断的类型。下面是一个简单的if语句:
#!/bin/sh
if [ ${SHELL} = "/bin/bash" ]; then
echo "your login shell is the bash (bourne again shell)"
else
echo "your login shell is not bash but ${SHELL}"
fi
变量$SHELL包含有登录shell的名称,我们拿它和/bin/bash进行比较以判断当前使用的shell是否为bash。
还可以使用 test 选项 文件名 来测试,而测试结果使用echo $?来查看
选项有: -d -f -w -r -x -L
数值测试的选项有: -eq = -ne -qt > -lt < -le <= -ge >=
&& 和 || 操作符
熟悉C语言的朋友可能会喜欢下面的表达式:
[ -f "/etc/shadow" ] && echo "This computer uses shadow passwords"
这里的 && 就是一个快捷操作符,如果左边的表达式为真则执行右边的语句,你也可以把它看作逻辑运算里的与操作。上述脚本表示如果/etc/shadow文件存在,则打印”This computer uses shadow passwords”。同样shell编程中还可以用或操作(||),例如:
#!/bin/sh
mailfolder=/var/spool/mail/james
[ -r "$mailfolder" ] || { echo "Can not read $mailfolder" ; exit 1; }
echo "$mailfolder has mail from:"
grep "^From " $mailfolder
该脚本首先判断mailfolder是否可读,如果可读则打印该文件中的"From" 一行。如果不可读则或操作生效,打印错误信息后脚本退出。需要注意的是,这里我们必须使用如下两个命令:
-打印错误信息
-退出程序
我们使用花括号以匿名函数的形式将两个命令放到一起作为一个命令使用;普通函数稍后再作说明。即使不用与和或操作符,我们也可以用if表达式完成任何事情,但是使用与或操作符会更便利很多。
case 语句
case表达式可以用来匹配一个给定的字符串,而不是数字(可别和C语言里的switch...case混淆)。
case ... in
...) do something here
;;
…
;;
esac
file命令可以辨别出一个给定文件的文件类型,如:file lf.gz,其输出结果为:
lf.gz: gzip compressed data, deflated, original filename,
last modified: Mon Aug 27 23:09:18 2001, os: Unix
我们利用这点写了一个名为smartzip的脚本,该脚本可以自动解压bzip2, gzip和zip 类型的压缩文件:
#!/bin/sh
ftype=`file "$1"` # Note ' and ` is different
case "$ftype" in
"$1: Zip archive"*)
unzip "$1" ;;
"$1: gzip compressed"*)
gunzip "$1" ;;
"$1: bzip2 compressed"*)
bunzip2 "$1" ;;
*) echo "File $1 can not be uncompressed with smartzip";;
esac
你可能注意到上面使用了一个特殊变量$1,该变量包含有传递给该脚本的第一个参数值。也就是说,当我们运行:
smartzip articles.zip
$1 就是字符串 articles.zip。
select 语句
select表达式是bash的一种扩展应用,擅长于交互式场合。用户可以从一组不同的值中进行选择:
select var in ... ; do
break;
done
.... now $var can be used ....
下面是一个简单的示例:
#!/bin/sh
echo "What is your favourite OS?"
select var in "Linux" "Gnu Hurd" "Free BSD" "Other"; do
break;
done
echo "You have selected $var"
如果以上脚本运行出现 select :NOT FOUND 将 #!/bin/sh 改为 #!/bin/bash 该脚本的运行结果如下:
What is your favourite OS?
1) Linux
2) Gnu Hurd
3) Free BSD
4) Other
#? 1
You have selected Linux
while/for 循环
在shell中,可以使用如下循环:
while ...; do
....
done
只要测试表达式条件为真,则while循环将一直运行。关键字"break"用来跳出循环,而关键字”continue”则可以跳过一个循环的余下部分,直接跳到下一次循环中。
for循环会查看一个字符串行表(字符串用空格分隔),并将其赋给一个变量:
for var in ....; do
....
done
下面的示例会把A B C分别打印到屏幕上:
#!/bin/sh
for var in A B C ; do
echo "var is $var"
done
下面是一个实用的脚本showrpm,其功能是打印一些RPM包的统计信息:
#!/bin/sh
# list a content summary of a number o
作为服务器,安全方面是非常重要的一个问题。很多时候就是要求系统做到系统禁止别的主机进行ping自己的地址。下面介绍下Linux下如何禁止ping和怎么开启系统IPv4的转发功能。其实非常简单,只需一条命令就搞定了。同时,切换也相当方便。看下面的图就知道,只需要修改目录/proc/sys/net/ipv4/中的icmp_echo_ignore_all文档的一个值,而这个值的范围也非常小,只在0和1之间。有友友们会想,这样就可以了?确实是的,因为改proc目录的文件是马上生效的。
0,代表禁止这个功能,也就是允许ping
1,代表允许这个功能,也就是禁止ping
同样也是在该目录下修改文档:ip_forward的值即可开启和关闭Linux系统IPv4的转发功能,都是即使生效的。
本文链接
系统cron设定:/etc/crontab
通过 /etc/crontab 文件,可以设定系统定期执行的任务,当然,要想编辑这个文件,得有root权限。
让我们打开 /etc/crontab,看看cron的语法:
#
# $Header: /var/cvsroot/gentoo-x86/sys-process/vixie-cron/files/crontab-3.0.1-r4,v 1.1 2005/03/04 23:59:48 ciaranm Exp $
#
#
# Global variables
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/
# check scripts in cron.hourly, cron.daily, cron.weekly and cron.monthly
0 * * * * root rm -f /var/spool/cron/lastrun/cron.hourly
1 3 * * * root rm -f /var/spool/cron/lastrun/cron.daily
15 4 * * 6 root rm -f /var/spool/cron/lastrun/cron.weekly
30 5 1 * * root rm -f /var/spool/cron/lastrun/cron.monthly
*/10 * * * * root test -x /usr/sbin/run-crons && /usr/sbin/run-crons
真正描述执行的任务在后五行,每行代表了一个定期执行的任务,从前到后,分为3部分:
第一部分,一堆奇怪的数字和星号,这部分描述任务的执行周期和时间,后面我们将详细解释。
第二部分,上面的文件全部是"root",描述了执行任务时的用户。
第三部分,为需要执行的完整命令。
第一部分分为5个小部分,没部分可以是数字或者星号,分别代表了分钟、小时、日期、月份、周,让我们来看一个例子:
分 时 日 月 周
星号,即代表不限制,上面的例子就是:每天的7点0分,都将执行mpg123 ~/wakeup.mp3,放首歌,把自己从睡梦中叫醒~
以下是各部分的取之范围:
分钟0~59 小时0~23 日期1~31 月份1~12周0~6
其中周的范围0~6,0代表星期天,1~6代表周一~周六。
让我们来看更多的例子:
0 2 1 * * root rm -f /tmp/* #每月1号凌晨2点,清理/tmp下的文件
0 8 6 5 * root mail robin < /home/galeki/happy.txt #每年5月6日给robin发信祝他生日快乐
假如,我想每隔2分钟就要执行某个命令,或者我想在每天的6点、12点、18点执行命令,诸如此类的周期,可以通过 “ / ” 和 “ , ” 来设置:
0 6,12,18 * * * root ............... #每天6点、12点、18点执行........
注意:运行脚本文件,需修改其属性,使其可执行:chmod +x /.../.../test.php
参照:http://os.51cto.com/art/200805/75224.htm
本文链接