shell和计划任务
shell脚本进阶
循环,控制和菜单
在shell脚本中,有时会重复执行某段代码,通常在进入循环和结束循环时设置条件,以达到重复已知或者未知次数的循环次数
常用的循环命令有:for,while,until
for循环:程序先进行条件判断,判断为真则执行循环体,为假则不执行。常用于遍历列表
for循环的常用格式
#方式1
for 变量名 in 列表;do
循环体
done
#方式2
for 变量名 in 列表
do
循环体
done
while:程序先执行循环体,每次循环之后进行田间判断,“true”则继续执行循环,“false”则退出循环。
whiel循环常用格式
while COMMANDS; do COMMANDS; done
while CONDITION; do
循环体
done
until与while类似,区别在于until判断条件为“false”则继续循环体,“true”则退出循环
until常用格式
until COMMANDS; do COMMANDS; done
until CONDITION; do
循环体
done
示例
1.for循环
[root@centos7 data]# bash test.sh
1
2
3
4
5
6
7
8
9
10
[root@centos7 data]#
[root@centos7 data]# cat test.sh
#!/bin/bash
for i in {1..10}
do
echo $i
done
[root@centos7 data]#
2.while循环
[root@centos7 data]# bash test.sh
1
2
3
4
5
6
7
8
9
10
[root@centos7 data]# cat test.sh
#!/bin/bash
i=1
while ((i<=10))
do
echo $i
let i++
done
until循环
[root@centos7 data]# bash test.sh
1
2
3
4
5
6
7
8
9
10
[root@centos7 data]# cat test.sh
#!/bin/bash
i=1
until ((i>10))
do
echo $i
let i++
done
有时根据需求,对循环进行控制,continue通过语句执行结果判断循环是否继续,continue #后跟数字表示对第几层循环有效,默认1及当前循环。break通过执行语句结果判断是否中断循环,break #终端第#层循环默认1当前循环。shift [n] 用于将参量列表 list 左移指定次数,缺省为左移一次。 参量列表 list 一旦被移动,最左端的那个参数就从列表中删除。while 循环遍历位置参量列表时,常用 到 shift
示例:
1.
[root@centos7 data]# bash test.sh
1
2
3
4
6
7
8
9
10
[root@centos7 data]# cat test.sh
#!/bin/bash
for i in {1..10}
do
if [ $i -eq 5 ]
then
continue
fi
echo $i
let i++
done
2.
[root@centos7 data]# bash test.sh
1
2
3
4
5
6
7
8
9
[root@centos7 data]# cat test.sh
#!/bin/bash
i=1
while true
do
echo $i
let i++
[ $i -eq 10 ] && break
done
3.
[root@centos7 data]# bash test.sh 1 2 3
1
2
3
[root@centos7 data]# cat test.sh
#!/bin/bash
while [ -n "$1" ]
do
echo $1
shift
done
while 循环的特殊用法,遍历文件或文本的每一行
while read line; do
循环体
done < /PATH/FROM/SOMEFILE
说明:依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line
[root@centos7 data]# bash test.sh
S
Kernel r on an m
[root@centos7 data]# cat test.sh
#!/bin/bash
while read line
do
echo $line
shift
done </etc/issue
有时脚本功能较多时会用到菜单select命令,select 循环主要用于创建菜单,按数字顺序排列的菜单项显示在标准错误上,并显示 PS3 提示 符,等待用户输入
用户输入菜单列表中的某个数字,执行相应的命令 用户输入被保存在内置变量 REPLY 中 select 是个无限循环,因此要用 break 命令退出循环,或用 exit 命令终止脚本。也可以按 ctrl+c 退出循环
[root@centos7 data]# bash test.sh
1) 1
2) 2
3) 3
4) 4
5) 5
6) 6
请选择:(1-6):1
1
请选择:(1-6):2
2
请选择:(1-6):q
选择错误,请重新选择
请选择:(1-6):6
6
[root@centos7 data]# cat test.sh
#!/bin/bash
PS3="请选择:(1-6):"
select menu in 1 2 3 4 5 6
do
case $REPLY in
1)
echo $menu
;;
2)
echo $menu
;;
3)
echo $menu
;;
4)
echo $menu
;;
5)
echo $menu
;;
6)
echo $menu;break
;;
*)
echo "选择错误,请重新选择"
;;
esac
done
函数和数组
当某段代码使用频率较高时可以考虑函数,实现代码重用和模块化编程
函数由函数名和函数体组成,引用函前需提前定义,在脚本中直接引用。也可将常用函数保存为文件。
#语法一:
func_name (){
...函数体...
}
#语法二:
function func_name {
...函数体...
}
#语法三:
function func_name () {
...函数体...
}
1.
[root@centos7 data]# bash test.sh
hello world
[root@centos7 data]# cat test.sh
#!/bin/bash
hello(){
echo "hello world"
}
hello
2.
[root@centos7 data]# cat func
#!/bin/bash
hello(){
echo "hello world"
}
[root@centos7 data]# . func
[root@centos7 data]# hello
hello world
注:
export -f function_name
declare -xf function_name
使用命令可将函数定义为环境函数
数组:存储多个元素的连续的内存空间,相当于多个变量的集合
数组名和索引
索引的编号从0开始,属于数值索引
索引可支持使用自定义的格式,而不仅是数值格式,即为关联索引,bash 4.0版本之后开始支持
bash的数组支持稀疏格式(索引不连续)
普通数组可以不事先声明,直接使用
declare -a ARRAY_NAME
#关联数组必须先声明,再使用
declare -A ARRAY_NAME
[root@centos7 data]# num=({0..10})
[root@centos7 data]# echo ${num[1]}
1
[root@centos7 data]# echo ${num[2]}
2
[root@centos7 data]# declare -A name
[root@centos7 data]# name["ceo"]={"zhang"}
[root@centos7 data]# name["cto"]={"zhao"}
[root@centos7 data]# name["coo"]={"li"}
[root@centos7 data]# echo ${name[*]}
{zhang} {li} {zhao}
[root@centos7 data]# echo ${name[ceo]}
{zhang}
使用命令unset可以删除数组
unset ARRAY[index] 按索引删除
unset ARRAY 整体删除
系统进程和计划任务
进程相关
进程介绍
Process: 运行中的程序的一个副本,是被载入内存的一个指令集合,是资源分配的单位
进程ID(Process ID,PID)号码被用来标记各个进程
UID、GID、和SELinux语境决定对文件系统的存取和访问权限
通常从执行进程的用户来继承
存在生命周期
进程创建:
init:第一个进程,从 CentOS7 以后为systemd
进程:都由其父进程创建,fork(),父子关系,CoW:Copy On Write
进程的状态
进程的基本状态有:创建,就绪,执行,阻塞,终止
进程状态的切换:
运行——>就绪:
1,占用CPU的时间过长,而系统分配给该进程占用CPU的时间是有限的;
2,更高优先级的进程要运行时,该进程就被迫让出CPU,该进程便由执行状态转变为就绪状态
就绪——>运行:运行的进程的时间片用完,调度就转到就绪队列中选择合适的进程分配CPU
运行——>阻塞:正在执行的进程因发生某等待事件而无法执行,则进程由执行状态变为阻塞状态,如
发生了I/O请求
阻塞——>就绪:进程所等待的事件已经发生,就进入就绪队列
以下两种状态是不可能发生的:
阻塞——>运行:即使给阻塞进程分配CPU,也无法执行,操作系统在进行调度时不会从阻塞队列进行
挑选,而是从就绪队列中选取
就绪——>阻塞:就绪态根本就没有执行,谈不上进入阻塞态
进程管理和性能工具
关于进程查看和管理的命令有很多,这里列举常用命令并作举例说明
1.ps
ps 即 process state,可以进程当前状态的快照,默认显示当前终端中的进程,Linux系统各进程的相
关信息均保存在/proc/PID目录下的各文件中
[root@centos7 data]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 20:31 ? 00:00:00 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root 2 0 0 20:31 ? 00:00:00 [kthreadd]
root 4 2 0 20:31 ? 00:00:00 [kworker/0:0H]
root 5 2 0 20:31 ? 00:00:00 [kworker/u256:0]
C 表示 CPU利用率
[root@centos7 data]# ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 125364 3812 ? Ss 20:31 0:00 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root 2 0.0 0.0 0 0 ? S 20:31 0:00 [kthreadd]
root 4 0.0 0.0 0 0 ? S< 20:31 0:00 [kworker/0:0H]
root 5 0.0 0.0 0 0 ? S 20:31 0:00 [kworker/u256:0]
USER 进程所有者的用户名
PID 进程号
START 进程激活时间
%CPU 进程自最近一次刷新以来所占用的CPU时间和总时间的百分比
%MEM 进程使用内存的百分比
VSZ 进程使用的虚拟内存大小,以K为单位
RSS 驻留空间的大小。显示当前常驻内存的程序的K字节数。
TTY 进程相关的终端
STAT 进程状态,包括下面的状态:
D 不可中断 Uninterruptible sleep (usually IO)
R 正在运行,或在队列中的进程
S 处于休眠状态
T 停止或被追踪
Z 僵尸进程
W 进入内存交换(从内核2.6开始无效)
X 死掉的进程
< 高优先级
N 低优先级
L 有些页被锁进内存
s 包含子进程
+ 位于后台的进程组;
l 多线程,克隆线程
TIME 进程使用的总CPU时间
COMMAND 被执行的命令行
NI 进程的优先级值,较小的数字意味着占用较少的CPU时间
PRI 进程优先级。
PPID 父进程ID
WCHAN 进程等待的内核事件名
按需查看
[root@centos7 data]# ps axo pid,%mem,%cpu
PID %MEM %CPU
1 0.2 0.0
2 0.0 0.0
4 0.0 0.0
5 0.0 0.0
6 0.0 0.0
7 0.0 0.0
按内存使用排序 --sort 倒叙
[root@centos7 data]# ps axo pid,%mem,%cpu k %mem
PID %MEM %CPU
2 0.0 0.0
4 0.0 0.0
5 0.0 0.0
6 0.0 0.0
7 0.0 0.0
2.pstree
pstree 可以用来显示进程的父子关系,以树形结构显示
-p 显示PID
-T 不显示线程thread,默认显示线程
-u 显示用户切换
-H pid 高亮显示指定进程及其前辈进程
[root@centos7 data]# pstree 1
systemd─┬─NetworkManager───2*[{NetworkManager}]
├─VGAuthService
├─agetty
├─atd
├─auditd───{auditd}
├─crond
├─dbus-daemon
├─master─┬─pickup
│ └─qmgr
3.prtstat
显示进程信息
[root@centos7 data]# prtstat 552
Process: crond State: S (sleeping)
CPU#: 0 TTY: 0:0 Threads: 1
Process, Group and Session IDs
Process ID: 552 Parent ID: 1
Group ID: 552 Session ID: 552
T Group ID: -1
Page Faults
This Process (minor major): 603 1
Child Processes (minor major): 9544 3
CPU Times
This Process (user system guest blkio): 0.00 0.00 0.00 0.06
Child processes (user system guest): 0.01 0.00 0.00
Memory
Vsize: 129 MB
RSS: 1646 kB RSS Limit: 18446744073709 MB
Code Start: 0x55992c40e000 Code Stop: 0x55992c41c98c
Stack Start: 0x7ffe959967d0
Stack Pointer (ESP): 0x7ffe959962c8 Inst Pointer (EIP): 0x7f2c7ecf6840
Scheduling
Policy: normal
Nice: 0 RT Priority: 0 (non RT)
4.top
实时显示进程状态
[root@centos7 data]# top
top - 22:30:53 up 1:59, 1 user, load average: 0.00, 0.01, 0.05
Tasks: 102 total, 3 running, 99 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1863000 total, 1534672 free, 169520 used, 158808 buff/cache
KiB Swap: 2097148 total, 2097148 free, 0 used. 1539772 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
547 root 20 0 272972 4776 3656 R 0.7 0.3 0:05.72 vmtoolsd
288 root 20 0 0 0 0 R 0.3 0.0 0:02.57 xfsaild/sda2
1302 root 20 0 161512 6088 4708 S 0.3 0.3 0:00.72 sshd
1 root 20 0 125364 3812 2568 S 0.0 0.2 0:00.69 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
4 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
5 root 20 0 0 0 0 S 0.0 0.0 0:00.13 kworker/u256:0
top 提供动态的实时进程状态
帮助:h 或 ? ,按 q 或esc 退出帮助
排序: P:以占据的CPU百分比,%CPU
M:占据内存百分比,%MEM
T:累积占据CPU时长,TIME+
首部信息显示:
uptime信息:l命令
tasks及cpu信息:t命令
cpu分别显示:1 (数字)
memory信息:m命令
退出命令:
q 修改刷新时间间隔:
s 终止指定进程:
k 保存文件:W
top命令栏位信息简介
us:用户空间
sy:内核空间
ni:调整nice时间
id:空闲
wa:等待IO时间
hi:硬中断
si:软中断(模式切换)
st:虚拟机偷走的时间
系统负载状态
1.uptime,w
查看系统负载状态
[root@centos7 data]# uptime
22:40:44 up 2:09, 1 user, load average: 0.00, 0.01, 0.05
[root@centos7 data]# w
22:41:13 up 2:09, 1 user, load average: 0.00, 0.01, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 10.0.0.1 20:32 1.00s 0.14s 0.00s w
主要查看系统运行时间,在线用户,平均负载等
2.free
查看内存状态
[root@centos7 data]# free
total used free shared buff/cache available
Mem: 1863000 169492 1534656 9684 158852 1539800
Swap: 2097148 0 2097148
内存总量,已用,可用和交换分区状态
4.iostat
[root@centos7 data]# iostat
Linux 3.10.0-1160.el7.x86_64 (centos7.example.com) 03/20/2022 _x86_64_ (1 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
0.20 0.03 0.17 0.14 0.00 99.45
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 1.61 29.91 9.51 242052 76916
scd0 0.00 0.13 0.00 1028 0
显示cpu状态和磁盘IO信息
tps:该设备每秒的传输次数(Indicate the number of transfers per second that were
issued to the device.)。"一次传输"意思是"一次I/O请求"。多个逻辑请求可能会被合并为"一次I/O
请求"。"一次传输"请求的大小是未知的。
kB_read/s:每秒从设备(drive expressed)读取的数据量;
kB_wrtn/s:每秒向设备(drive expressed)写入的数据量;
kB_read:读取的总数据量;
kB_wrtn:写入的总数量数据量;这些单位都为Kilobytes。
kill命令
kill:内部命令,可用来向进程发送控制信号,以实现对进程管理,每个信号对应一个数字,信号名称以 SIG开头(可省略),不区分大小写
常用信号:
- 1)SIGHUP 无须关闭进程而让其重读配置文件
- 2)SIGINT 中止正在运行的进程;相当于Ctrl+c
- 3)SIGQUIT 相当于ctrl+\
- 9)SIGKILL 强制杀死正在运行的进程,可能会导致数据丢失,慎用!
- 15)SIGTERM 终止正在运行的进程,默认信号
- 18)SIGCONT 继续运行
- 19)SIGSTOP 后台休眠
作业管理
作业的前台运行,后台运行,终止和并发运行
fg [[%]JOB_NUM]:把指定的后台作业调回前台
bg [[%]JOB_NUM]:让送往后台的作业在后台继续运行
kill [%JOB_NUM]: 终止指定的作业
作业并行:利用后台执行,实现并行功能,即同时运行多个进程,提高效率
方法:
1)
cat all.sh
f1.sh&
f2.sh&
f3.sh&
2)
(f1.sh&);(f2.sh&);(f3.sh&)
3)
f1.sh&f2.sh&f3.sh&
当执行多个命令并行时可用{}将命令括起来
注:wait #结束添加,实现非交互推出
例:
net=10.0.0
for i in {1..254};do
{
if ping -c1 -W1 $net.$i &> /dev/null;then
echo $net.$i is up
else
echo $net.$i is down
fi
}&
done
wait
计划任务
一次性任务
at工具可创建一次性任务
当前时间延时5分钟输出ok 发送到/var/spool/mail/root中
[root@centos7 data]# at now+5 minutes
at> echo "ok"
at> <EOT>
job 2 at Sun Mar 20 23:07:00 2022
at的时间格式
HH:MM 在今日的 HH:MM 进行,若该时刻已过,则明天此时执行任务
02:00
HH:MM YYYY-MM-DD 规定在某年某月的某一天的特殊时刻进行该项任务
02:00 2016-09-20
HH:MM[am|pm] [Month] [Date]
06pm March 17
17:20 tomorrow
HH:MM[am|pm] + number [minutes|hours|days|weeks], 在某个时间点再加几个时间后才进行该
项任务
now + 5 min
02pm + 3 days
atq可查看所有的一次性任务
周期性任务
cron系统调度进程,crontab命令可用于管理周期性任务
/etc/crontab 配置文件
/etc/cron.d/ 配置文件
/etc/cron.hourly/ 脚本
/etc/cron.daily/ 脚本
/etc/cron.weekly/ 脚本
/etc/cron.monthly/ 脚本
周期任务管理
crontab
-u 指定用户
-e 管理任务
-l 列出任务
-r 删除任务
-i 删除前提示
时间格式
计划任务时间表示法:
(1) 特定值 给定时间点有效取值范围内的值
(2) * 给定时间点上有效取值范围内的所有值,表示“每...”,放在星期的位置表示不确定
(3) 离散取值 #,#,#
(4) 连续取值 #-#
(5) 在指定时间范围上,定义步长 /#: #即为步长
(6) 特定关健字
@yearly 0 0 1 1 *
@annually 0 0 1 1 *
@monthly 0 0 1 * *
@weekly 0 0 * * 0
@daily 0 0 * * *
@hourly 0 * * * *
@reboot Run once after reboot
[root@centos7 data]# cat /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# For details see man 4 crontabs
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
分 时 日 月 周
crontab 创建任务执行脚本时建议生命PATH路径
作业:
1、编写脚本实现登陆远程主机。(使用expect和shell脚本两种形式)。
#!bin/bash
rpm -q sshpass && sshpass -p 666666 ssh -o StrictHostKeyChecking=no 10.0.0.27
#!bin/bash
user="root"
ip=10.0.0.27
expect <<EOF
spawn ssh $user@$ip
expect {
"password" { send "666666\n" }
}
expect "#" { send "ip a\n" }
expect "#" { send "exit\n" }
expect eof
EOF
2、生成10个随机数保存于数组中,并找出其最大值和最小值
#!/bin/bash
for i in {0..9}; do
num[$i]=$RANDOM
echo ${num[$i]}
if [ $i -eq 0 ];then
max=${num[$i]}
min=${num[$i]}
elif [ ${num[$i]} -gt $max ];then
max=${num[$i]}
elif [ ${num[$i]} -lt $min ];then
min=${num[$i]}
fi
done
echo "Max:$max"
echo "Min:$min"
3、输入若干个数值存入数组中,采用冒泡算法进行升序或降序排序
#! /bin/bash
n=0
while read num[$n]
do
n=$[$n+1]
done
len=${#num[*]}
for((i=0;i<len;i++))
do
for((j=0;j<len-i-1;j++))
do
t=$[$j+1]
#if [[ ${num[$j]} -gt ${num[$t]} ]] 升序
if [[ ${num[$j]} -lt ${num[$t]} ]] 降序
then
term=${num[$j]}
num[$j]=${num[$t]}
num[$t]=$term
fi
done
done
for((k=0;k<len;k++))
do
echo ${num[$k]}
done
4、总结查看系统负载的几种命令,总结top命令的指标大概什么含义(不要求全部写出来)
free 查看内存状态 已用 可用 缓存等
fdisk 查看各分区利用率
uptime 查看系统运行时间 平均负载等
w 查看当前在线用户,cpu状态
iostat 查看磁盘IO,和cpu状态
top
[root@centos7 data]# top
top - 22:30:53 up 1:59, 1 user, load average: 0.00, 0.01, 0.05
Tasks: 102 total, 3 running, 99 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1863000 total, 1534672 free, 169520 used, 158808 buff/cache
KiB Swap: 2097148 total, 2097148 free, 0 used. 1539772 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
547 root 20 0 272972 4776 3656 R 0.7 0.3 0:05.72 vmtoolsd
运行时间,在线用户,平均负载
进程信息
cpu状态
内存状态
交换分区状态
进程ID 所属用户 优先级 cpu 内存使用情况 cpu占用时间 进程
5、编写脚本,使用for和while分别实现192.168.0.0/24网段内,地址是否能够ping通,若ping通则输出"success!",若ping不通则输出"fail!"
#!bin/bash
for i in {1..254}
do
ip=10.0.0.$i
ping -c1 -W1 $ip >/dev/null && echo "$ip sucess" || echo "$ip fail" &
done
#!bin/bash
i=1
while [ $i -le 254 ]
do
ip=10.0.0.$i
ping -c1 -W1 $ip >/dev/null && echo "$ip sucess" || echo "$ip fail" &
let i++
done
wait
#!bin/bash
i=1
while true
do
ip=10.0.0.$i
ping -c1 -W1 $ip >/dev/null && echo "$ip sucess" || echo "$ip fail" &
let i++
[ $i -eq 255 ] && break
done
wait
6、每周的工作日1:30,将/etc备份至/backup目录中,保存的文件名称格式 为“etcbak-yyyy-mm-dd-HH.tar.xz”,其中日期是前一天的时间
[root@centos7 data]# crontab -l
30 1 * * 1-5 /bin/bash /data/back.sh
[root@centos7 data]# cat back.sh
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
days=`date +%F-%H-%M -d "yesterday"`
tar -cvpf etcbak-$days.tar /etc && xz etcbak-$days.tar etcbak-$days.tar.xz
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫