shell脚本编程(三)
- tee命令,”T型管道”,将STDIN的数据同时发送到两个目的地。一个是STDOUT,另一个是tee命令行指定的文件名:
tee filename
tee会覆盖原文件,-a参数不会覆盖 Linux信号
信号 值 描述 1 SIGHUP 挂起进程 2 SIGINT 中断进程 3 SIGQUIT 停止进程 9 SIGKILL 无条件终止进程 15 SIGTERM 如果可能的化终止进程 17 SIGSTOP 无条件停止,但不终止进程 18 SIGTSTP 停止或暂停进程,但不终止它 19 SIGCONT 重新启动停止的进程 默认情况下bash shell会忽略它接收的任何SIGQUIT(3)和SIGTERM(15)信号,以防止交互的shell意外终止。shell会处理它收到的任何SIGHUP(1)和SIGINT(2)信号
- 中断进程:Ctrl+C,生成SIGINT信号
- 暂停进程:Ctrl+Z,生成SIGTSTP信号,停止后程序仍然留在内存中(可以ps命令查看)
- trap命令可以指定能够通过shell脚本监控和拦截的Linux信号。:
trap ”commands“ signals(必须用双引号)
- trap常用的捕获信号:SIGINT SIGHUP EXIT SIGTERM。
- 移除捕获可以使用破折号作为命令和想要恢复正常行为的信号列表:
e.g:trap - EXIT
- 可以在命令后加上&符号使后台模式运行shell脚本。也可同时启动任何数量的相同的后台作业。
- nohup命令可以使脚本在结束前以后台模式运行:
nohup ./shell脚本 &
运行后shell会给该命令分配一个作业编号,Liunx系统分配一个PID编号。使用nohup后台脚本将忽略任何SIGHUP信号。nohup.out文件包含通常发送到终端监视器的所有输出。(如果使用nohup运行另一个命令,输出将添加到现有的nohup.out文件) - 脚本使用$$变量显示Linux系统分配给脚本的PID
- 作业控制:
- jobs可以查看shell处理的当前作业。
- jobs命令输出作业可能带有加号和减号。带有加号的作业被视为默认作业。带有减号的作业是待默认作业。只能有一个加号和一个减号的作业。
bg 作业号
后台程序前台运行。
- 多任务操作系统中,内核负责为系统中运行的每个进程分配CPU时间。CPU一次只能运行一个进程。默认情况下,从shell启动的所有进程在Linux系统上的调度优先级(scheduling priority)都相同。
- 调度优先级从-20(最高优先级)到+20(最低优先级),bash shell优先级为0.
调命令优先级:
- nice -n设置启动命令时的优先级
e.g:nice -n 10 ./test >file &
nice不允许普通系统用户增加命令的优先级。 - renice(更改系统中运行的命令优先级,与nice有区别)
e.g:renice 10 -p 24552
:
- renice命令自动更新运行进程的调度优先级
- 与nice一样的限制:不允许普通系统用户增加命令的优先级。
- nice -n设置启动命令时的优先级
- at命令(给定时间内运行)
at -f filename time #-f指定用于读取命令的文件名(脚本文件)
at可以识别的时间格式:
- 标准的小时和分钟格式,比如10:15
- AM/PM指示符,比如10:15PM
- 具体指定的时间,比如now、noon、midnight、teatime(4PM)
- 如果指定一个过去的时间,at命令将在第二天的那个时间运行作业。
- 标准的日期格式,比如MMDDYY、MM/DD/YY或DD.MM.YY
- 文本日期格式,比如Jul4或Dec 25,有没有年份都可以
- 还可以指定时间增量:
- Now+25minutes
- 10:15PM tomorrow
- 10:15+7days
- 使用at命令时,作业将提交到作业队列(job queue)中,有26种不同的作业队列可用于不同的优先级水平。使用a到z引用作业队列。默认at作业都提交到作业队列a(最高),使用-q参数改变优先级。
- 作业在Linux系统运行时,没有与该作业关联的监视器。Linux使用提交作业的用户的电子邮件地址作为STDOUT和STDERR。任何以STDOUT和STDERR为目的地的输出都将通过邮件系统发送给用户(mail)
- atq命令能够查看系统中排队的作业
atrm+作业号
可以移除排队的作业。- batch命令与at命令稍有不同。安排脚本在系统使用率低时运行。
batch -f filename time
(可以指定batch命令应该尝试运行作业的最早时间) - 与at命令类似,默认情况下batch命令从STDIN读取命令。
cron:调度需定期运行的作业:corn程序在后台运行,它从特殊表格(cron)中查找需要调度运行的作业。
corn使用特殊格式指定作业运行的时间,表格格式:
min hour dayofmonth month dayofweek command
15 10 * * * command #每天10:15运行命令 15 10 * * * 1 command #每周一下午4:15运行 00 12 1 * * command #每个月第一天的中午12点执行 00 12 * * * if[ 'date +%d -d tommorow' =01 ];then;command #在每天12点查看本日是否是该月的最后一天,如果是,它将运行命令
- 使用crontab命令构建cron表格,列出现有的cron表格:
crontab -l
;向cron表格添加条目:crontab -e
- anacron程序使用时间戳确定调度的作业是是否在正确的时间间隔运行。如果它确定某个作业错过了调度的运行时间,它将自动尽快运行该作业。(该特性对于执行例行日志维护的脚本非常有用。)
- anacron使用自己的表格(通常:/etc/anacrontab)指定作业。:
period delay identiier command #period定义总也应该多久运行一次,以天为单位。delay项指定在anacron程序确定应该运行一个命令之后需要多长时间才会实际运行该命令。该选项可以为不同的命令这只不同额延迟值,以防所有命令在一打开Linux系统时运行。identifier项是一个位移的非空字符串,可以唯一地识别日志消息和错误电子邮件中的作业。
Linux运行级别
运行级别 描述 运行级别 描述 0 停止 4 未使用 1 单用户模式 5 多用户模式,有网络和图形X Window会话 2 多用户模式,通常没有网络支持 5 多用户模式,有网络和图形X Window会话 3 完全多用户模式,有网络 Linux系统提供了一些脚本文件,用于让脚本在系统启动或者用户启动新的bash shell时运行。rc.local(对于openSusE是boot.local)文件可以列出每次系统启动时启动的脚本。这可以帮助系统管理员在系统启动时运行特定的脚本,以进行系统维护。与此类似.bash_profile和.bashrc文件位于每个用户的主目录,提供一个位置防止与新shell一起运行的脚本和命令。.bash_profile文件在每次用户登陆系统时运行脚本,.basshrc文件按在每个新shell启动时运行脚本。
创建函数
(1) function name ( commands ) (2) name(){ coommands }
shell定义函数时,应将定义在前。
- shell函数结尾不要使用默认退出状态。可以使用return命令以特定退出状态退出函数。return命令可以使用单个整数值来定义函数退出状态。必须注意避免两个容易发生的错误:
- 函数完成后尽快提取返回值
- 退出状态的取值范围是0-255(变量$?提取)
- 正如命令输出可以捕获并存放到shell变量中一样,函数输入也可捕获并存放到shell变量中:
e.g:result='shell函数名'(反引号)
这种方法可以返回浮点数和字符串值,所以这种方法能够非常灵活地从函数返回数据。 - 向函数传递参数:bash shell将函数作为小型脚本处理。
函数使用两种类型的变量:
全局变量(这种方法有风险,尤其对多个shell脚本共用的函数)
#!/bin/bash #demonstrating a bad use of variable function func1 { temp=$[ $value+5 ] result=$[ $temp*2 ] } temp=4 value=6 func1 echo "The result is $result" if [ $temp -gt $value] then echo "temp is larger" else echo "temp is smaller" fi
- 局部变量:
local temp
向函数传递数组:先用
echo $@
将数组整个传入函数中,随后更具命令行参数重建数组变量。:**实例1:** #!/bin/bash #carry variable to function test function testit { local newarray newarray=('echo "$@"') echo "The new array value is ${newwarray[*]}" } mayarray=(1 2 3 4 5) echo "The original array is ${myarrar[*]}" testit ${myarray[*]} **实例2:** #!/bin/bash #adding values in an array funcion addarray { local sum=0 local newarray newarray=('echo "$@"') for value in ${newarray[*]} do sum=$[ $sum+$value ] done echo $sum } myarray=(1 2 3 4 5) echo "The original array is :${myarray[*]}" arg1='echo ${myarray[I]}' result='addarray $arg1' echo "The result is $result"
从函数返回数组:(数组的调用和返回关键在于
echo “$@”
)
#!/bin/bash
#returning an array value
function arraydblr {
local origarray
local newarray
local elements
local i
origarray=(`echo "$@"`)
# newarray=(`echo "$@"`)
elements=$[ $# - 1 ]
for ((i=0;i<=$elements;i++))
{
newarray[$i]=$[ ${origarray[$i]}*2 ]
}
echo ${newarray[*]}
}
myarray=(1 2 3 4 5)
echo "The orignal array is: ${myarray[*]}"
myarray=`echo ${myarray[*]}` #arg1
result=(`arraydblr $myarray`)
echo "The new array is :${result[*]}"
- 函数递归
#!/bin/bash
#using recursion
factorial() {
if [ $1 -eq 1 ]
then
echo 1
else
local temp=$[ $1-1 ]
local result=`factorial $temp`
echo $[ $result*$1 ]
fi
}
read -p "Enter value>" value
result=`factorial $value`
echo "The factorial of $value is: $result"
- 创建库:source命令。source命令在当前shell环境中执行命令,而非创建新shell来执行命令。使用source命令在shell脚本内部运行库文件脚本。这样脚本可以使用这些函数。source有一个短小的别名,成为点操作符。为了在脚本中调用test库文件,只需添加下列命令行:
. ./test
:
#!/bin/bash
#test库文件
addem(){
echo $[ $1+$2 ]
}
multem(){
echo $[ $1*$2 ]
}
divem(){
#if [ $2 -ne 0 ]
#then
echo $[ $1 / $2 ]
#else
# echo -1
# fi
}#以上是库文件
#!/bin/bash
#调用库函数
. ./test-lib
a1=10
a2=4
result1=`addem a1 a2`
result2=`multem a1 a2`
result3=`divem a1 a2`
echo "The result of adding them is: $result1"
echo "The result of multiplying them is: $result2"
echo "The result of dividing them is $result3"