shell编程基础
- 创建shell文件的第一行必须是:#!/bin/bash 指明要使用的shell.
cat << HELP
可以用来显示帮助信息等
...
HELP
- “ (跟波浪线在一块的那个) 执行命令并赋值给变量
- 设置局部变量
various=test
- 设置局部变量为全局变量
export various
- 输出重定向
ls >> a.txt
追加到文件
ls > a.txt
覆盖到文件
ls &>> a.txt
所有信息包括错误信息 追加到文件 - 输入重定向
cat < test.sh | more
将test.sh的内容输出终端 并以more的形式显示 - 使用expr 进行数值计算
使用反引号 echo`expr 1 \* 2` ==> 2
使用方括号echo $[1 * 2] ==> 2
- 使用bc计算机解决浮点计算的问题
使用反括号echo `echo " scale=2;3.44/5" | bc`
#友好一点,把不同的计算放到不同的行
var5=`bc << EOF
scale = 4
a = 4
b = 3
a / b
EOF
`
echo $var5 - 用
echo $?
查看退出状态 - if-then语句
if command[;]
then
commands
fi - if-then-else语句
if command
then
commands
else
commands
fi - 嵌套if语句
if command1
then
commands
elif command2
then
more commands
fi - test命令
if-then 语句不能测试跟命令的退出状态无关的条件,即if后边所跟随的command必须是要返回退出状态的。
- 语法1
if test condition
then
commands
fi - 语法2
if [condition]
then
commands
fi
[]定义test命令中用到的条件,[]左右必须加空格
test命令可以判断3类条件
- 数值比较
n1 -eq n2
检查n1和n2是否相等n1 -ge n2
大于等于n1 -gt n2
大于n1 -le n2
小于等于n1 -lt n2
小于n1 -ne n2
不等于
- 字符串比较
str1 = str2
str1 != str2
str1 \< str2
str1 \> str2
-n str1
检查str1的长度是否非0-z str1
检查str1的长度是否为0
- 文件比较
-d file
检查file是否存在并且是一个目录-e file
检查file是否存在-f file
检查file是否存在并且是一个文件-r file
检查文件是否存在并可读-s file
检查文件是否存在并非空-w file
检查文件是否存在并可写-x file
检查文件是否存在并可执行-O file
检查文件是否存在并属于当前用户-G file
检查文件是否存在并且默认组与当前用户相同file1 -nt file2
检查file1是否比file2新file1 -ot file2
检查file1是否比file2旧
- 数值比较
- 语法1
- 复合条件测试
[ condition ] && [ condition ]
[ condition ] || [ condition ]
双圆括号
(( expression ))
# 针对数字计算的高级特性特性 描述 val++
val--
++val
--val
!
逻辑求反 ~
位求反 **
幂运算 <<
>>
&
|
&&
||
双方括号
[[ expression ]]
# 针对字符串的高级特性
# 模式匹配,正则表达式- case
case variable in
pattern1 | pattern2) command1;;
parttern3) command2;;
*) default command3;;
esac for
for var in list
do
commands
done
#默认以“空格 制表符 换行符”作为字段分隔符
#修改字段分隔符 IFS=”\n”
#用通配符读取目录
for file in /home/mmm/ /etc/
do
done
#C风格的for
for(( i=0,j=10; i<10;i++,j-- ))
do
commands
donewhile
while test command
do
other command
done
当test语句执行后的退出状态为0时才执行do…done- until
until test command
do
other command
当test语句执行后的退出状态非0时才执行do…done - break
跳出for while until内部循环
break 1
跳出外部循环
break 2
(3,4,5。。。。) - 处理循环的输出
for var in ...
do
done >> out.txt
- 读取命令行参数
$1 $2 $3 $....
- 读取在执行的程序的名称
$0
- 在对命令行参数进行处理之前,最好判断一下用户是否输入了参数
if [ -n $# ]
then
...
fi - 特殊参数变量
参数计数:$#
- 抓取所有数据
$*
将所有参数当成单个单词保存
$@
将所有参数当成一个字符串处理 - 移动变量
shift
默认情况下它会将每个参数变量减1,$3的值会移动到$2. $1的值会被删除,并且无法恢复
但是$0
依旧表示的是当前正在执行的程序的名称 - 查找简单选项
while [ -n "$1" ]
do
case "$1" in
-a) echo "";;
-b) echo "";;
*) echo "";;
shift
done
并不能识别类似-at类型的参数 - 分离参数和选项
while [ -n "$1" ]
do
case "$1" in
-a) echo "Found the -a option";;
-b) echo "-b option";;
-c) echo "-c option";;
# 用--区分参数和选项
--)shift; break;;
*) echo "$1 is not an option";;
esac
shift
done
count=1
#打印参数
for param in $@
do
echo "Parameter #$count : $param"
count=$[$count+1]
done
并不能识别类似-at类型的参数 - 处理带值的选项
while [ -n "$1" ]
do
case "$1" in
-a) echo "Found the -a option";;
-b)
param=$2
echo "Fount the -b option , with parameter value is $param"
shift 2
;;
-c) echo "-c option";;
--)shift; break;;
*) echo "$1 is not an option";;
esac
shift
done
#打印参数
count=1
for param in $@
do
echo "Parameter #$count : $param"
count=$[$count+1]
done
并不能识别类似-at类型的参数 - 使用getopt命令
getopt options optstring parameters
其中optstring
定义了命令行有效的选项字母,还定义了哪些选项字母需要参数值
getopt ab:cd -a -b test1 -cd test2 test3
解释:ab:cd
是命令行有效的选项字母,其中b是需要参数值的,b的参数值是test1,-cd是第二组选项字母,test2 test3是parameters. - 在脚本中使用getopt命令
用set命令将命令行参数替换成set命令的命令行的值
set -- `getopt -q ab:cd "$@"`
set -- `getopt ab:cd -ab testb -cd test3 test4`
while [ -n "$1" ]
do
case "$1" in
-a) echo "Found the -a option";;
-b)
param=$2
echo "Fount the -b option , with parameter value is $param"
shift 2
;;
-c) echo "-c option";;
--)shift; break;;
*) echo "$1 is not an option";;
esac
shift
done
#打印参数
count=1
for param in $@
do
echo "Parameter #$count : $param"
count=$[$count+1]
done - 在脚本中使用getopts命令
getopts optstring various
getopt只有一行输出
getopts有多个输出,对应参数变量的顺序,并且会删除选项前的-号
#getopts :ab:c opt
#./abc.sh运行输出:not found -b option
#getopts ab:c opt
#./abc.sh运行输出:./abc.sh:选项需要一个参数 -- b \n not found -b option
while getopts ab:c opt
do
case "$opt" in
a) echo "Found a option";;
b) echo "Found b option,with parameter value is $OPTARG";;
c) echo "Fount c option";;
*) echo "not found $1 option";;
esac
done 选项标准化
# 设置命令行参数的选项时,有一些是已经有固定意义的,如下选项 描述 -a
显示所有对象 -c
生成一个计数 -d
指定一个目录 -e
扩展一个对象 -f
指定读入数据的文件 -h
显示命令的帮助信息 -i
忽略文本大小写 -l
产生输出的长格式版本 -n
使用非交互模式 -o
指定将所有输出重定向到的输出文件 -q
以安静模式运行 -r
递归地处理目录和文件 -s
以安静模式运行 -v
生成详细输出 -x
删除某个对象 -y
对所有问题回答yes 获得用户输入(read)
echo -n "Enter your name:"
read name
echo "hello $name,XXXX"
read -p 无需写echo -n "Enter your name:"
#给输入的数据分配多个变量,如果变量表在数据完成之前用完了,剩余数据分配在最后一个变量中
read -p "Enter your name:" first last
echo "Checking data for $first, $last .....
#如果不在read命令中指定变量,则read命令会将它收到的任何数据都放进特殊环境变量REPLY中
read -p "Enter your name:"
factorial=1
for (( count=1;count<=$REPLY;count++ ))
do
factorial=$[ $factorial * $count ]
done
echo "阶乘:"$factorial
#read命令的超时参数-t
if read -t 5 -p "Please enter your name:" name
then
echo "Hello $name,XXX"
else
echo "Sorry,too slow!"
fi
#read命令对输入的字符计数,当输入的字符打到预设的字符数时,自动退出,将输入的数据赋给变量
#-n1说明 -n表示对输入的字符计数 1则表示预设的字符的个数,即输入满几个字符时退出read命令
read -n1 -p "Do you want to continue [Y/N]?" answer
case $answer in
Y|y) echo "you can continue";;
N|n) echo "ok,goodbye";exit;;
esac
echo "The End!"
#隐藏方式读取-s
#比如密码,不希望其显示在屏幕上.
read -s -p "Enter you password:" pass
echo
echo "Is your password really $pass?"
#read 读取文件
#将文件运行cat命令后的输出通过管道直接传给含有read命令的while命令
count=1
cat test | while read line
do
echo "Line $count:$line"
(( count++ ))
done
echo "The end"标准文件描述符
#linux文件描述符是一个非负整数,每个过程一次最多可以有9个文件描述符.
#bash中保留的仅有三个:文件描述符 缩写 描述 0
STDIN
标准输入 1
STDOUT
标准输出 2
STDERR
标准错误 # STDIN
cat
: 接收STDIN(键盘)的输入,并显示在终端
cat < a.txt/cat << a.txt
: 接收非STDIN文件的输入,并显示在终端
#STDOUT
ls -l
:将结果直接显示在终端
ls -l > a.txt/ls -l >> a.txt
:将结果显示在文本文件中创建本地临时文件
#6个X自动生成6个随机字母数字,用来保证文件名在目录中是唯一的
#在当前目录创建
mktemp test.XXXXXX
#在/tmp/文件夹创建
mktemp -t test.XXXXXX
- 创建临时目录
mktemp -d dir.XXXXXX
记录消息
# 将消息显示在STDOUT,并且重定向到filename文件中
tee filename
# 默认情况下tee是覆盖的,如果想追加使用-a
date | tee -a testfile
最常见的linux信号
信号 值 描述 1
SIGHUP
挂起进程 2
SIGINT
终止进程 3
SIGQUIT
停止进程 9
SIGKILL
无条件终止进程 15
SIGTERM
可能的话终止进程 17
SIGSTOP
无条件停止进程,但不是终止进程 18
SIGTSTP
停止或暂停进程,但不终止进程 19
SIGCONT
继续运行停止的进程 捕捉信号
trap commands signals
#如果脚本收到了trap命令中列出的信号,它会阻止它被shell处理,而在本地处理它.
#表示其不会被外部处理,只会在当前执行的程序中进行处理
trap "echo 'Sorry! I have trapped Ctrl-C'" SIGINT SIGTERM- 捕捉脚本的退出
trap "echo byebye" EXIT
count=1
while [ $count -le 5 ]
do
echo "Loop #$count"
sleep 3
count=$[ $count + 1 ]
done - 移除捕捉
trap "echo byebye" EXIT
count=1
while [ $count -le 5 ]
do
echo "Loop #$count"
sleep 3
count=$[ $count + 1 ]
done
trap - EXIT - 后台运行脚本
./test.sh &
- 在非控制台下运行脚本
#如果使用nohup命令,关闭关联会话时,脚本会忽略掉任何终端发送过来的SIGHUP信号
#由于nohup命令会从终端解除进程的关联,进程会丢掉到STDOUT和STDERR的链接.nohup命令会自动将STDOUT和STDERR的消息重定向到一个名叫nohup.out的文件中.
nohup ./test1 &
查看作业
jobs
参数 描述 -l
列出进程的PID以及作业号 -n
只列出上次shell发出的通知后改变了状态的作业 -p
只列出作业的PID -r
只列出运行中的作业 -s
只列出已经停止的作业 重启停止的作业
#以后台模式重启一个作业 2是作业号
bg 2
- 调整谦让度
#调度优先级是个整数值,从-20(最高)到+20(最低).默认情况下,bash shell以优先级0来启动所有进程
#nice命令用来在启动命令时调度优先级.
#让命令以更低的优先级运行 -n
#nice命令阻止普通系统用来来增加命令的优先级
nice -n 10 ./test.sh &
#renice 指定运行进程的PID来改变它的优先级
#只能对属于你的进程执行renice
#只能通过renice降低进程的优先级
#root用户可以通过renice调整任何进程的优先级到任何级别
renice 10 -p 28501
- 定时运行作业
#at 命令.
#at的守护进程atd以后台模式运行.
#atd检查系统上/var/spool/at这个特殊目录,来获取用at命令提交的作业.
#at命令只执行一次
at [ -f filename ] time
#at命令能识别的时间格式
#1.标准的小时和分钟格式 10:15
#2.~AM/~PM指示符 10:15~PM
#3. 特定可命名的时间,now noon,midnight,teatime(4~PM)
#如果指定一个已经过去了的时间,at命令会在第二天改时间运行改作业
#4.标准日期格式.MMDDYY MM/DD/YY DD.MM.YY
#5.文本日期,Jul 4 Dec 25.加不加年份均可
#6.指定时间增量 当前时间+25 min
#7. 明天10:15~PM
#8.10:15+ 7 天
#列出等待的作业并删除
#atq列出等待的作业
#atrm 59 删除 - 计划定期执行脚本
#cron时间表
#可周期性执行
#假设linux系统是7X24小时运行的,如果关机导致错过了计划作业,则不会再执行
#格式: min hour dayofmonth month dayofweek command
#15 10 1 2 * command
#以上表示 在2月份的第一天(2月1日)上午10点15分执行
#在一个月的最后一天执行,通过在每天的12点检查明天是不是下月的第一天.
#00 12 * * * if[ `date +%d -d tomorrow`=01 ];then;command
#构建cron时间表
# 查看 crontab -l
#添加时间表 -e
#当创建的脚本不要求有精确的执行时间时,可以用预配置的cron脚本目录,4个基本目录: hourly daily monthly weekly - anacron程序
#解决cron错过计划作业的问题
#如果anacron知道作业错过了计划好的运行,它会尽快运行改作业.
#通常用于进行常规日志维护的脚本
#只处理位于cron目录的程序,比如/etc/cron.monthly 开机时运行脚本
#System V init过程
#red hat系列运行级 描述 0 关机 1 单用户模式 2 多用户模式,通常不支持网络 3 全功能的多用户模式,支持网络 4 可定义用户 5 多用户模式,支持网络和图形化X Window会话 6 重启 #debian发行版
运行级 描述 0 关机 1 单用户模式 2~5 多用户模式,支持网络和图形化X Window会话 6 重启 # 存储运行级别的目录
# 有的是/etc/rc#.d #代表运行级
# 有的是/etc/init.d
# 有的是/etc/init.d/rc.d
#Upstart init 过程
#不关注运行级别,而关注时间,比如系统开机.
#使用/etc/event.d或者/etc/init目录下的文件来启动进程.
#定义自己的开机脚本
#linux本地开机文件位置发行版 文件位置 debian etc/init.d/rc.local Fedora /etc/rc.d/rc.local Mandriva /etc/rc.local openSuse /etc/init.d/boot.local Ubuntu /etc/rc.local #在新shell中启动
# 当新shell是新的登录生成的话,bash shell 会运行.bash_profile文件.
# 当新shell启动时,包括有新的登录的情况,bash shell会运行.bashrc文件