• 十一、脚本控制与计划任务(未完)


    信号

    Linux利用信号与运行在系统中的进程进行通信。

    可以编写脚本使其收到特定信号时执行某些命令,从而控制shell脚本的操作。

    linux常见信号

    信号 描述
    1 SIGHUP 挂起进程
    2 SIGINT 终止进程
    3 SIGQUIT 停止进程
    9 SIGKILL 强制终止进程
    15 SIGTERM 正常终止进程
    17 SIGSTOP 强制停止进程
    18 SIGTSTP 停止或暂停进程
    19 SIGCONT 继续运行停止的进程

    默认情况下bash shell会忽略收到的3,15信号,这样使交互式shell不会意外终止。

    bash shell会接收1,2信号,如离开一个交互式shell之前,shell会把1信号即挂起信号传给所有由该shell启动的进程。

    通过2信号,中断shell,Linux内核会停止为shell分配CPU处理时间,同样shell会把该信号传给由他启动的进程。

    生成信号

    linux使用键盘组合键生成停止或暂停两种基本信号

    中断进程

    ctrl+c生成2信号,终止进程

    [root@tzPC ~]# sleep 100
    ^C

    暂停进程

    ctrl+z生成18信号,停止shell中运行的进程,停止进程会让程序继续保存在内存中并能从上次暂停的位置继续运行。

    [1]是shell分配的作业号,shell把运行中的每个进程称为作业并为其分配唯一的作业号

    [root@tzPC ~]# sleep 100
    ^Z
    [1]+  已停止               sleep 100

    jobs查看后台停止的进程

    [root@tzPC ~]# jobs
    [1]+  已停止               sleep 100

    将后台停止的进程恢复到前台运行

    [root@tzPC ~]# fg 1

     如果shell会话中有一个已停止的作业再退出shell时bash会提醒你

    [root@tzPC ~]# sleep 100
    ^Z
    [1]+  已停止               sleep 100
    [root@tzPC ~]# exit
    exit
    有停止的任务。

    使用ps -l查看已停止的作业

    [root@tzPC ~]# ps -l
    F S   UID    PID   PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
    4 S     0  89099  89094  0  80   0 - 28912 do_wai pts/0    00:00:00 bash
    0 T     0  91144  89099  0  80   0 - 26976 do_sig pts/0    00:00:00 sleep
    0 R     0  91231  89099  0  80   0 - 37235 -      pts/0    00:00:00 ps

    知道了已停止作业的PID,可以使用kill命令发送SIGKILL信号终止他

    [root@tzPC ~]# kill -9 91144

    捕获信号

    trap命令

    捕获信号并执行其他命令

    语法格式

    trap commands signals

     signals可以是数值或linux信号名

    例:使用trap命令忽略SIGINT信号,捕获ctrl+c组合键

    效果

    [root@tzPC 16Unit]# bash test1.sh 
    This is a test script
    Loop #1
    Loop #2
    Loop #3
    ^CSorry! I have trapped Ctrl-C
    Loop #4
    Loop #5
    ^CSorry! I have trapped Ctrl-C
    Loop #6
    Loop #7
    Loop #8
    Loop #9
    Loop #10

    脚本

    [root@tzPC 16Unit]# cat test1.sh
    #!/bin/bash
    #Testing signal trapping
    trap "echo 'Sorry! I have trapped Ctrl-C'" SIGINT
    echo This is a test script
    count=1
    while [ $count -le 10 ]
    do
            echo "Loop #$count"
            sleep 1
            count=$[ $count + 1 ]
    done

    捕获脚本退出

    捕获shell脚本退出只要在trap命令后加上EXIT信号即可。

    效果

    [root@tzPC 16Unit]# cat test2.sh
    #!/bin/bash
    #Trapping the script exit
    trap "echo 脚本执行完毕." EXIT
    count=1
    while [ $count -le 5 ]
    do
            echo "Loop #$count"
            sleep 1
            count=$[ $count + 1 ]
    done

    如果提前退出同样能捕获到EXIT信号

    [root@tzPC 16Unit]# bash test2.sh
    Loop #1
    Loop #2
    Loop #3
    ^C脚本执行完毕.

     修改或移除捕获

    例:修改捕获命令

    [root@tzPC 16Unit]# bash test3.sh
    Loop #1
    Loop #2
    ^CSorry...Ctrl+C is trapped.
    Loop #3
    Loop #4
    Loop #5
    Second #1
    ^CI modified the trap!
    Second #2
    Second #3
    Second #4
    Second #5

    脚本

    [root@tzPC 16Unit]# cat test3.sh
    #!/bin/bash
    #Modifying a set trap
    trap "echo 'Sorry...Ctrl+C is trapped.'" SIGINT
    count=1
    while [ $count -le 5 ]
    do
            echo "Loop #$count"
            sleep 1
            count=$[ $count + 1 ]
    done
    trap "echo 'I modified the trap!'" SIGINT
    #这里修改了捕获到SIGINT的命令
    count=1
    while [ $count -le 5 ]
    do
            echo "Second #$count"
            sleep 1
            count=$[ $count + 1 ]
    done

    删除捕获,在trap跟信号名称之间加--即可

    trap -- SIGINT
    或者
    trap - SIGINT

    脚本

    [root@tzPC 16Unit]# cat test3.sh
    #!/bin/bash
    #Modifying a set trap
    trap "echo 'Sorry...Ctrl+C is trapped.'" SIGINT
    count=1
    while [ $count -le 5 ]
    do
            echo "Loop #$count"
            sleep 1
            count=$[ $count + 1 ]
    done
    trap - SIGINT
    #或者trap -- SIGINT同样的效果
    echo "I just removed the trap"
    count=1
    while [ $count -le 3 ]
    do
            echo "Second #$count"
            sleep 1
            count=$[ $count + 1 ]
    done

    后台模式运行脚本

    后台运行的脚本echo默认输出到显示器,最好重定向到文件里,不然会让人头昏脑胀,哈哈

    运行多个后台作业

    [root@tzPC 16Unit]# bash test4.sh &
    [2] 89870
    [root@tzPC 16Unit]# bash test5.sh &
    [3] 90239
    [root@tzPC 16Unit]# bash test6.sh &
    [4] 90421

    ps查看

    每一个后台进程都和终端会话pts/0终端联系在一起,如果终端会话退出那么后台进程也会退出

    [root@tzPC 16Unit]# ps
       PID TTY          TIME CMD
     77372 pts/0    00:00:00 bash
     89870 pts/0    00:00:00 bash
     89872 pts/0    00:00:00 sleep
     90239 pts/0    00:00:00 bash
     90240 pts/0    00:00:00 sleep
     90421 pts/0    00:00:00 bash
     90422 pts/0    00:00:00 sleep
     92024 pts/0    00:00:00 ps
    115344 pts/0    00:00:00 bash

    在非控制台下运行脚本

    即使退出终端也让脚本一直运行的方法

    之前有些过一篇笔记screen命令就可以做到

    传送门:https://www.cnblogs.com/tz90/p/13289340.html

     书里讲的nohup命令

    nohup命令会阻断所有发送给该进程的SIGHUP信号,也就是关闭session的信号。

    运行脚本,此时session窗口假设为1

    [root@tzPC 16Unit]# cat test4.sh
    #!/bin/bash
    count=1
    while true
    do
            echo "hello,$count"
            sleep 2
            count=$[ $count + 1 ]
    done
    [root@tzPC 16Unit]# nohup bash test4.sh
    nohup: 忽略输入并把输出追加到"nohup.out"

    打开另外一个session窗口2查看进程

    [root@tzPC ~]# ps aux | fgrep test4.sh
    root      22674  0.0  0.1 113132  1416 pts/0    S+   16:36   0:00 bash test4.sh
    root      23685  0.0  0.0 112676   896 pts/2    R+   16:37   0:00 grep -F --color=auto test4.sh

    关闭session1窗口,再次查看进程发现进程还在

    nohup命令会解除session跟进程的关联也就是说关闭终端nohup命令执行的命令依旧在后台执行,这样造成nohup命令不再通STDOUT和STDERR描述符联系在一起,也就输出不到屏幕上。

    这时nohup命令会自动将STDOU和STDERR消息重定向到当前目录下名为nohup.out文件中。

    参考:https://blog.csdn.net/hl449006540/article/details/80216061

     作业控制

    作业停止后可以使用kill命令终止该进程,要重启停止的进程需要发送SIGCONT信号。

    启动、停止、终止以及恢复作业的功能统称为作业控制

    查看作业

    jobs可以查看正在处理的作业

    脚本案例

    [root@tzPC 16Unit]# cat test10.sh
    #!/bin/bash
    #Test job control
    echo "Script Process ID: $$"
    count=1
    while [ $count -le 10 ] 
    do
            echo "Loop #$count"
            sleep 10
            count=$[ $count + 1 ]
    done
    echo "End of script..."

    运行脚本使用Ctrl+Z停止脚本

    [root@tzPC 16Unit]# bash test10.sh
    Script Process ID: 63760
    Loop #1
    ^Z
    [1]+  已停止               bash test10.sh

    同样运行脚本使用&在后台进程中启动

    这里将输出重定向到文件,避免头昏脑胀哈哈(我喜欢书里的这句话)!

    [root@tzPC 16Unit]# bash test10.sh > test10.out &
    [2] 64666

    使用jobs查看

    [root@tzPC 16Unit]# jobs
    [1]+  Stopped                 bash test10.sh
    [2]-  Running                 bash test10.sh > test10out &

    jobs -l 选项查看作业的PID

    [root@tzPC 16Unit]# jobs -l
    [1]+ 68838 Stopped                 bash test10.sh
    [2]- 68855 Running                 bash test10.sh > test10out &

    上图所示,带+的作业是默认作业,在使用未指定作业号的作业控制命令时,该作业会被当初作业控制命令的操作对象。

    带-的作业会成为下一个默认作业。

    任何时候都只有一个带加号跟带减号的作业。

    jobs常用命令参数

    参数    描述
    -l    列出进程的PID跟作业好
    -n    只列出上次shell发出的通知后改变了状态的作业  
    -p    只列出作业的PID
    -r    只列出运行中的作业
    -a    只列出已停止的作业

    重启停止的作业

    bg命令可以将已停止的作业作为后台进程重启

    [root@tzPC 16Unit]# bash test10.sh >test10out
    ^Z
    [1]+  Stopped                 bash test10.sh > test10out
    [root@tzPC 16Unit]# jobs
    [1]+  Stopped                 bash test10.sh > test10out
    [root@tzPC 16Unit]# bg
    [1]+ bash test10.sh > test10out &
    [root@tzPC 16Unit]# jobs
    [1]+  Running                 bash test10.sh > test10out &

    因为该作业时默认作业所以bg后面不用加作业号

    fg命令可以将已停止的作业作为前台进程重启。

    [root@tzPC 16Unit]# jobs
    [1]+  Stopped                 bash test10.sh > test10out
    [root@tzPC 16Unit]# fg 1
    bash test10.sh > test10out

     谦让度

    1. 调度优先级时内核分配给进程的CPU时间,优先级越高进程占用CPU的时间也就越多
    2. 调度优先级是个整数值
    3. 取值范围从-20(最高优先级)到+19(最低优先级)
    4. 由shell启动的所有进程调度优先级默认都相同,都为0
    5. 需要root权限

    nice命令

    -n参数修改优先级

    [root@tzPC 16Unit]# nice -n 10 bash test4.sh >test4out &
    [1] 72440

    查看优先级NI

    [root@tzPC 16Unit]# ps -p 72440 -o pid,ppid,ni,cmd
       PID   PPID  NI CMD
     72440  68701  10 bash test4.sh

    renice命令

    用于更改系统上已经运行命令的优先级,需要用到已运行命令进程的PID

    1. 只能对属主进程执行renice
    2. 普通用户只能降低进程优先级
    3. root用户可以调高跟降低进程优先级
    [root@tzPC 16Unit]# bash test5.sh &
    [1] 73522
    [root@tzPC 16Unit]# ps -p 73522 -o pid,ppid,ni,cmd
       PID   PPID  NI CMD
     73522  68701   0 bash test5.sh
    
    [root@tzPC 16Unit]# renice -n 10 -p 73522
    73522 (process ID) old priority -10, new priority 10
    [root@tzPC 16Unit]# ps -p 73522 -o pid,ppid,ni,cmd
       PID   PPID  NI CMD
     73522  68701  10 bash test5.sh

    定时运行作业

    1. at(一次性执行)
    2. cron(定期执行)
    3. anacron(定期执行)

    用at命令计划执行脚本

    1. 必须运行atd服务
    2. atd守护进程会每隔60秒检查/var/spool/at目录下文件,并同时检查文件设置的运行时间,如果跟当前时间匹配,则运行。
    3. 如果错过指定的时间,at命令会在第二天指定时间运行文件。

    启动atd服务并加入开机启动项

    [root@tzPC 16Unit]# systemctl start atd #必须启动atd服务
    [root@tzPC 16Unit]# systemctl enable atd #加入开机启动项

    at命令格式

    at -f filename time

    time格式

    10:15

    10:15 PM

    now、noon、midnight、teatime(4 PM)

    MMDDYY、MM/DD/YY、DD.MM.YY

    Jul 4、Dec 25

    时间增量(当前时间+25min、明天10:15PM、10:15+7天)

    优先级

    支持26中不同的优先级,以小写字母a-z和大写字母A-Z标识,默认为a优先级

    a的优先级最高,z的优先级最低

    使用-q参数指定优先级

    at命令的输出

    脚本文件的输出会发送到该用户的邮件

    案例

    -f指定运行脚本文件,now表示立刻执行该脚本

    [root@tzPC 16Unit]# cat test13.sh
    #!/bin/bash
    #Test using at command
    echo "This script ran at $(date +%B%d,%T)" >test13out
    sleep 5
    echo "This is the script's end..." >>test13out
    
    [root@tzPC 16Unit]# at -f test13.sh now
    job 4 at Fri Aug 21 16:40:00 2020

    注意:最好将脚本文件的输出重定向到文件,因为如果没有安装sendmail,脚本的输出结果就获取不了

    列出等待中的作业

    [root@tzPC 16Unit]# at -M -f test10.sh teatime
    job 5 at Sat Aug 22 16:00:00 2020
    [root@tzPC 16Unit]# at -M -f test10.sh tomorrow
    job 6 at Sat Aug 22 16:47:00 2020
    [root@tzPC 16Unit]# at -M -f test10.sh 13:30
    job 7 at Sat Aug 22 13:30:00 2020
    [root@tzPC 16Unit]# at -M -f test10.sh now
    job 8 at Fri Aug 21 16:47:00 2020
    [root@tzPC 16Unit]# atq
    5    Sat Aug 22 16:00:00 2020 a root
    6    Sat Aug 22 16:47:00 2020 a root
    7    Sat Aug 22 13:30:00 2020 a root
    8    Fri Aug 21 16:47:00 2020 = root

    删除等待中的作业

    artm 7

    cron命令定期执行脚本

    使用cron命令,前提条件是系统是7X24小时运行,如果计划运行时间系统正好处于关机状态,这个计划任务就不会运行,即使开机也不会运行错过的计划任务。

    启动crond服务并加入开机启动项

    [root@tzPC 16Unit]# systemctl start crond
    [root@tzPC 16Unit]# systemctl enable crond

    cron时间定义格式

    min hour dayofmonth month dayofweek command

    dayofmonth表示月份中的日期值(1-31日)

    每天10:15运行命令

    15 10 * * * command

    每周一下午4:15运行命令

    15 16 * * 1 command

    在每月最后一天执行命令(这里书中命令有误),应该如下写法

    00 12 1 * * if [ `date +%d -d tomorrow` = 01 ];then command ;fi

    命令列表必须指定脚本绝对路径,同时也可给脚本参数或者重定向到文件

    15 10 * * * /home/tz/test4.sh > test4out

    -e参数创建cron计划任务

    [root@tzPC 16Unit]# crontab -e

    15 10 * * * /root/script/16Unit/test10.sh >test10out

    查看cron时间表

    [root@tzPC 16Unit]# crontab -l
    15 10 * * * /root/script/16Unit/test10.sh >test10out

    浏览cron目录

    有4个基本目录

    hourly、daily、monthly、weekly

    分别对应每小时、每天、每月、每周运行一次

    将脚本放入对应目录即可

    [root@tzPC etc]# ls /etc/cron.*ly
    /etc/cron.daily:
    logrotate  man-db.cron
    
    /etc/cron.hourly:
    0anacron
    
    /etc/cron.monthly:
    
    /etc/cron.weekly:

    anacron命令

    此命令执行的计划任务如果错过了执行时间,会尽快运行错过的计划任务。

    常用于清理日志文件

    该命令只会处理位于cron目录的脚本

    用时间戳来确定脚本是否在规定时间内运行,每个cron目录都有个时间戳文件,位于/var/spool/anacron

    [root@tzPC etc]# cat /var/spool/anacron/cron.monthly
    20200817

    查看anacron时间表

    [root@tzPC etc]# cat /etc/anacrontab
    # /etc/anacrontab: configuration file for anacron
    
    # See anacron(8) and anacrontab(5) for details.
    
    SHELL=/bin/sh
    PATH=/sbin:/bin:/usr/sbin:/usr/bin
    MAILTO=root
    # the maximal random delay added to the base delay of the jobs
    RANDOM_DELAY=45
    # the jobs will be started during the following hours only
    START_HOURS_RANGE=3-22
    
    #period in days   delay in minutes   job-identifier   command
    1    5    cron.daily        nice run-parts /etc/cron.daily
    7    25    cron.weekly        nice run-parts /etc/cron.weekly
    @monthly 45    cron.monthly        nice run-parts /etc/cron.monthly

    anacron时间定义格式

    period delay identifier command

     #待补充

     学习来自:《Linux命令行与Shell脚本大全 第3版》第16章

    今天的学习是为了以后的工作更加的轻松!
  • 相关阅读:
    JSON的序列化与还原
    正则表达式的一些基础
    跨域二三事
    与Web服务器通信
    与 Web 服务器通信
    代码重构
    构造函数与各种继承方法特点
    this指向问题——严格、非严格模式,事件处理程序
    《JavaScript设计模式与开发实践》学习笔记——单例模式
    Git常用命名及常见操作流程
  • 原文地址:https://www.cnblogs.com/tz90/p/13533942.html
Copyright © 2020-2023  润新知