Linux合集之Linux实用运维脚本分享及Linux CPU的上下文切换
2024-04-29 22:00:00

Linux合集之Linux实用运维脚本分享及Linux CPU的上下文切换

Linux实用运维脚本分享

#查看僵尸进程nps -al | gawk '{ print $2,用运$4}' | grep Znn# 匹配电子邮件的地址ncat index.html | egrep -o "[A-Za-z0-9._]+@[A-Za-z0-9.]+.[a-zA-Z]{ 2,4}" > ans.txtnn#匹配http URLncat index.html | egrep -o "http://[A-Za-z0-9.]+.[a-zA-Z]{ 2,3}" > ans.txt nn#纯文本形式下载网页nlynx -dump www.rumenz.com > plain.txtnn#只打印HTTP头部信息 ,无须远程下载文件ncurl --head www.rumenz.comnn#使用POST提交数据ncurl -d "param2=nickwolfe¶m2=12345" http://www.rumenz.com/login.cginn#显示分组途经的维脚网关ntraceroute www.rumenz.comnn#列出系统中的开放端口以及运行在端口上的服务nlsof -i nn#nc命令建立socket连接nn#设置监听 nc -l 5555n#连接到套接字 nc 192.0.0.1 5555nn#快速文件传输n#接收端 nc -l 5555 > destination_filenamen#发送端 nc 192.0.0.1 5555 < source_filenamenn#找出指定目录最大的n个文件ndu -ak target_dir | sort -nrk 1 | head -n 4n# du中a为递归,k为kb;sort中n为数字,r为降序,k指定列nn#向终端中的所有登陆用户发送广播信息ncat message.txt | wallnn#创建新的screen窗口nscreennn#打印所有的.txt和.pdf文件nfind . ( -name "*.txt" -o -name "*.pdf" ) -printnn# -exec command { } ;是连用的,所有符合的本分都会放置在{ }中,去执行command nn#将文件分割成多个大小为10kb的享及下文文件nsplit -b 10k data.file nn#打印两个文件的交集ncomm A.txt B.txt -3 | sed 's/^t//'nn#sed移除空白行nsed '/^$/d' filenn

mysql备份

#!/bin/bashnnset -ennUSER="backup"nPASSWORD="backup"n# 数据库数据目录 #nDATA_DIR="/data/mysql"nBIN_INDEX=$DATA_DIR"/mysql-bin.index"n# 备份目录 #nBACKUP_DIR="/data/backup/mysql"nBACKUP_LOG="/var/log/mysql/backup.log"nnDATE=`date +"%Y%m%d"`nTIME=`date +"%Y%m%d%H"`nnLOG_TIME=`date +"%Y-%m-%d %H:%M:%S"`nDELETE_BINLOG_TIME="7 day"nINCREMENT_INTERVAL="3 hour"nnnote() { n printf "[$LOG_TIME] note: $*n" >> $BACKUP_LOG;n}nnwarning() { n printf "[$LOG_TIME] warning: $*n" >> $BACKUP_LOG;n}nnerror() { n printf "[$LOG_TIME] error: $*n" >> $BACKUP_LOG;n exit 1;n}nnfull_backup() { n local dbs=`ls -l $DATA_DIR | grep "^d" | awk -F " " '{ print $9}'`nn for db in $dbsn don local backup_dir=$BACKUP_DIR"/full/"$dbn local filename=$db"."$DATEn local backup_file=$backup_dir"/"$filename".sql"nn if [ ! -d $backup_dir ]n thenn mkdir -p $backup_dir || { error "创建数据库 $db 全量备份目录 $backup_dir 失败"; continue; }n note "数据库 $db 全量备份目录 $backup_dir 不存在 ,创建完成";n finn note "full backup $db start ..."n mysqldump --user=${ USER} --password=${ PASSWORD} --flush-logs --skip-lock-tables --quick $db > $backup_file || { warning "数据库 $db 备份失败"; continue; }nn cd $backup_dirn tar -cPzf $filename".tar.gz" $filename".sql"n rm -f $backup_filen chown -fR mysql:mysql $backup_dirnn note "数据库 $db 备份成功";n note "full backup $db end."n donen}nnincrement_backup() { n local StartTime=`date "-d $INCREMENT_INTERVAL ago" +"%Y-%m-%d %H:%M:%S"`n local DELETE_BINLOG_END_TIME=`date "-d $DELETE_BINLOG_TIME ago" +"%Y-%m-%d %H:%M:%S"`n local dbs=`ls -l $DATA_DIR | grep "^d" | awk -F " " '{ print $9}'`nn mysql -u$USER -p$PASSWORD -e "purge master logs before '$DELETE_BINLOG_END_TIME'" && note "delete $DELETE_BINLOG_TIME days before log";nn filename=`cat $BIN_INDEX | awk -F "/" '{ print $2}'`n for i in $filenamen don for db in $dbsn don local backup_dir=$BACKUP_DIR"/increment/"$dbn local filename=$db"."$TIMEn local backup_file=$backup_dir"/"$filename".sql"nn if [ ! -d $backup_dir ]n thenn mkdir -p $backup_dir || { error "创建数据库 $db 增量备份目录 $backup_dir 失败"; continue; }n note "数据库 $db 增量备份目录 $backup_dir 不存在 ,切换创建完成";n finn note "increment backup $db form time $StartTime start ..."nn mysqlbinlog -d $db --start-datetime="$StartTime" $DATA_DIR/$i >> $backup_file || { warning "数据库 $db 备份失败"; continue; }nn note "increment backup $db end."n donen donenn for db in $dbsn don local backup_dir=$BACKUP_DIR"/increment/"$dbn local filename=$db"."$TIMEn local backup_file=$backup_dir"/"$filename".sql"nn cd $backup_dirn tar -cPzf $filename".tar.gz" $filename".sql"n rm -f $backup_filenn note "数据库 $db 备份成功";n donen}nncase "$1" inn full)n full_backupn ;;n increment)n increment_backupn ;;n *)n exit 2n ;;nesacnnexit 1nn

目录备份

#!/bin/bashn#n#n# 时间nDATE=$(date '+%Y-%m-%d_%H_%M_%S')n# 备份目录 nBACKUPDIR="/home/backups"n# 需要备份的用运目录nSORFILE=/optn# 目标文件名nDESFILE=/home/backups/$SORFILE.$(date '+%Y-%m-%d_%H_%M_%S').zipnn[ ! -d $BACKUPDIR ] && mkdir -p $BACKUPDIRncd $BACKUPDIRnnecho "start backup $SORFILE ..."nsleep 3n#echo "$DESFILE"nnn#tar cvf $DESFILE $SORFILEn#gzip -f .zip $DESFILEnzip -r $DESFILE $SORFILE &>/dev/nullnif [ "$?" == "0" ]nthenn echo $(date +%Y-%m-%d)" zip sucess">>backup.lognelsen echo $(date +%Y-%m-%d)" zip failed">>backup.logn exit 0nfinn# 删除3天前的备份nfind $BACKUPDIR -type f -ctime +3 | xargs rm -rfnn

PING查询

#!/bin/bashn#用途 :根据网络配置对网络地址192.168.0进行修改,检查是维脚否是活动状态nn#{ start..end}shell扩展生成一组地址nfor ip in 192.168.0.{ 1..255}ndo n (n ping $ip -c 2 &> /dev/null n # > 标准输出重定向,和1>一致n # 2>&1 将标准错误输出 重定向 到标准输出n # &>file 将标准输出和标准错误输出都重定向到文件filename中nn if [ $?本分 -eq 0 ];thenn echo $ip is aliven fin )&ndonenwaitn#并行ping,加速nn

磁盘IO检查

##iostat是查看磁盘活动统计情况nn##显示所有设备负载情况 r/s: 每秒完成的读 I/O 设备次数 。即 rio/s;w/s: 每秒完成的享及下文写 I/O 设备次数。即 wio/s等niostat nn##每隔2秒刷新磁盘IO信息 ,切换并且每次显示3次niostat 2 3nn#显示某个磁盘的用运IO信息niostat -d sda1nn##显示tty和cpu信息niostat -tnn##以M为单位显示磁盘IO信息niostat -mnn##查看TPS和吞吐量信息 kB_read/s:每秒从设备(drive expressed)读取的数据量;kB_wrtn/s:每秒向设备(drive expressed)写入的数据量;kB_read :读取的总数据量;kB_wrtn:写入的总数量数据量;niostat -d -k 1 1nn#查看设备使用率(%util)、响应时间(await)niostat -d -x -k 1 1nn#查看CPU状态niostat -c 1 3nn#统计进程(pid)的维脚stat,进程的stat自然包括进程的IO状况npidstatnn#只显示IOnpidstat -d 1 nn#-d IO 信息,-r 缺页及内存信息-u CPU使用率-t 以线程为统计单位1 1秒统计一次npidstat -u -r -d -t 1nn#文件级IO分析,查看当前文件由哪些进程打开nlsof nls /proc/pid/fdnn#利用 sar 报告磁盘 I/O 信息DEV 正在监视的块设备 tps 每秒钟物理设备的 I/O 传输总量 rd_sec/s 每秒从设备读取的扇区数量 wr_sec/s 每秒向设备写入的扇区数量 avgrq-sz I/O 请求的平均扇区数n#avgqu-sz I/O 请求的平均队列长度 await I/O 请求的平均等待时间,单位为毫秒 svctm I/O 请求的本分平均服务时间,单位为毫秒 %util I/O 请求所占用的享及下文时间的百分比,即设备利用率nsar -pd 10 3 nn#iotop top的切换io版niotopnn#查看页面缓存信息 其中的Cached 指用于pagecache的内存大小(diskcache-SwapCache)。随着写入缓存页 ,Dirty 的值会增加 一旦开始把缓存页写入硬盘,Writeback的值会增加直到写入结束。ncat /proc/meminfo nn#查看有多少个pdflush进程 Linux 用pdflush进程把数据从缓存页写入硬盘n#pdflush的行为受/proc/sys/vm中的参数的控制/proc/sys/vm/dirty_writeback_centisecs (default 500): 1/100秒, 多长时间唤醒pdflush将缓存页数据写入硬盘 。默认5秒唤醒2个(更多个)线程。如果wrteback的时间长于dirty_writeback_centisecs的时间 ,可能会出问题ncat /proc/sys/vm/nr_pdflush_threadsnn#查看I/O 调度器n#调度算法n#noop anticipatory deadline [cfq] n#deadline : deadline 算法保证对既定的IO请求以最小的延迟时间 。n#anticipatory :有个IO发生后  ,如果又有进程请求IO,则产生一个默认6ms猜测时间 ,猜测下一个进程请求IO是干什么。这对于随机读取会造成较大的延时 。对数据库应用很糟糕 ,而对于Web Server等则会表现不错。n#cfq: 对每个进程维护一个IO队列,各个进程发来的IO请求会被cfq以轮循方式处理,对每一个IO请求都是公平。适合离散读的应用 。n#noop: 对所有IO请求都用FIFO队列形式处理。默认IO不会存在性能问题 。ncat /sys/block/[disk]/queue/schedulernnn#改变IO调度器n$ echo deadline > /sys/block/sdX/queue/schedulern#提高调度器请求队列的n$ echo 4096 > /sys/block/sdX/queue/nr_requestsnn

性能相关

#查看当前系统loadnuptimenn#查看系统状态和每个进程的系统资源使用状况ntopnn#可视化显示CPU的使用状况nhtopnn#查看每个CPU的负载信息nmpstat -P ALL 1nn#每隔1秒查看磁盘IO的统计信息niostat -xkdz 1nn#每隔一秒查看虚拟内存的使用信息nvmstat 1nn#查看内存使用统计信息nfreenn#查看网络使用信息nnicstat -z 1nn#类似vmstat的显示优化的工具ndstat 1nn#查看系统活动状态 ,比如系统分页统计 ,块设备IO统计等nsarnn#网络连接状态查看nnetstat -snn#进程资源使用信息查看npidstat 1npidstat -d 1nn#查看某个进程的系统调用信息 -p后面是进程id,-tttT 进程系统后的系统调用时间nstrace -tttT -p 12670n#统计IO设备输入输出的系统调用信息nstrace -c dd if=/dev/zero of=/dev/null bs=512 count=1024knnn#tcpdump 查看网络数据包ntcpdump -nr /tmp/out.tcpdumpnn#块设备的读写事件信息统计nbtrace /dev/sdb nn#iotop查看某个进程的IO操作统计信息niotop -bod5nn#slabtop 查看内核 slab内存分配器的使用信息nslabtop -scnn#系统参数设置nsysctl -ann#系统性能指标统计信息nperf stat gzip file1n#系统cpu活动状态查看nperf record -a -g -F 997 sleep 10nn

进程相关

## processes 进程管理nn##ps查看当前系统执行的线程列表,进行瞬间状态,不是连续状态 ,连续状态需要使用top名称查看 更多常用参数请使用 man ps查看npsnn##显示所有进程详细信息nps auxnn##-u 显示某个用户的进程列表nps -f -u www-data nn## -C 通过名字或者命令搜索进程nps -C apache2nn## --sort 根据进程cpu使用率降序排列,查看前5个进程 -pcpu表示降序 pcpu升序nps aux --sort=-pcpu | head -5 nn##-f 用树结构显示进程的层次关系 ,父子进程情况下nps -f --forest -C apache2 nn##显示一个父进程的所有子进程nps -o pid,uname,comm -C apache2nps --ppid 2359 nn##显示一个进程的所有线程 -L 参数nps -p 3150 -L nn##显示进程的执行时间 -o参数nps -e -o pid,comm,etime nn##watch命令可以用来实时捕捉ps显示进程nwatch -n 1 'ps -e -o pid,uname,cmd,pmem,pcpu --sort=-pmem,-pcpu | head -15' nn##jobs 查看后台运行的进程 jobs命令执行的结果 ,+表示是一个当前的作业,减号表是是一个当前作业之后的一个作业,jobs -l选项可显示所有任务的PID,jobs的状态可以是running, stopped, Terminated,但是如果任务被终止了(kill),shell 从当前的shell环境已知的列表中删除任务的进程标识;也就是说,jobs命令显示的是当前shell环境中所起的后台正在运行或者被挂起的任务信息njobsnn##查看后台运营的进程号njobs -pnn##查看现在被终止或者退出的进程号njobs -nnnn##kill命令 终止一个前台进程可以使用Ctrl+C键 kill 通过top或者ps获取进程id号 kill [-s 信号 | -p ] [ -a ] 进程号 ...n##发送指定的信号到相应进程。不指定型号将发送SIGTERM(15)终止指定进程 。关闭进程号12的进程nkill 12nnn##等同于在前台运行PID为123的进程时按下Ctrl+C键nkill -2 123nn##如果任无法终止该程序可用“-KILL” 参数 ,其发送的信号为SIGKILL(9) ,将强制结束进程 nkill -9 123nn##列出所有信号名称n##HUP 1 终端断线n##INT 2 中断(同 Ctrl + C)n##QUIT 3 退出(同 Ctrl + )n##TERM 15 终止n##KILL 9 强制终止n##CONT 18 继续(与STOP相反 , fg/bg命令)n##STOP 19 暂停(同 Ctrl + Z)nkill -lnn##得到指定信号的数值nkill -l KILLnn##杀死指定用户所有进程nkill -u peidalinuxnkill -9 $(ps -ef | grep peidalinux) nn##将后台中的命令调至前台继续运行 将进程123调至前台执行nfg 123nn##将一个在后台暂停的命令,变成继续执行nbg 123nn##该命令可以在你退出帐户/关闭终端之后继续运行相应的进程。nohup就是不挂起的意思 下面输出被重定向到myout.file文件中nnohup command > myout.file 2>&1 &nn##at:计划任务,在特定的时间执行某项工作,在特定的时间执行一次。n## 格式 :at HH:MM YYYY-MM-DD //HH(小时):MM(分钟) YYYY(年)-MM(月份)-DD(日)n##HH[am pm]+D(天) days //HH(小时)[am(上午)pm(下午)]+days(天)nat 12:00(时间) //at命令设定12:00执行一项操作n#at>useradd aaa //在at命令里设定添加用户aaan#ctrl+d //退出at命令n#tail -f /etc/passwd //查看/etc/passwd文件后十行是否增加了一个用户aaann##计划任务设定后  ,在没有执行之前我们可以用atq命令来查看系统没有执行工作任务 。natqnn##启动计划任务后 ,如果不想启动设定好的计划任务可以使用atrm命令删除。natrm 1 //删除计划任务1nn##pstree命令:列出当前的进程,以及它们的树状结构 格式  :pstree [选项] [pid|user]npstreenn##nice命令 :改变程序执行的优先权等级 应用程序优先权值的范围从-20~19,数字越小 ,优先权就越高 。一般情况下,普通应用程序的优先权值(CPU使用权值)都是0,如果让常用程序拥有较高的优先权等级 ,自然启动和运行速度都会快些。需要注意的是普通用户只能在0~19之间调整应用程序的优先权值 ,只有超级用户有权调整更高的优先权值(从-20~19) 。nnice [-n <优先等级>][--help][--version][命令]nnice -n 5 lsnn##sleep命令:使进程暂停执行一段时间ndate;sleep 1m;datennn##renice命令 renice命令允许用户修改一个正在运行进程的优先权。利用renice命令可以在命令执行时调整其优先权。n##其中 ,参数number与nice命令的number意义相同 。(1) 用户只能对自己所有的进程使用renice命令。(2) root用户可以在任何进程上使用renice命令 。(3) 只有root用户才能提高进程的优先权nrenice -5 -p 5200 #PID为5200的进程nice设为-5 nn##pmap命令用于显示一个或多个进程的内存状态。其报告进程的地址空间和内存状态信息 #pmap PID npmap 20367nn

javadump.sh

#!/bin/shnnDUMP_PIDS=`ps --no-heading -C java -f --width 1000 |awk '{ print $2}'`nif [ -z "$DUMP_PIDS" ]; thenn echo "The server $HOST_NAME is not started!"n exit 1;nfinnDUMP_ROOT=~/dumpnif [ ! -d $DUMP_ROOT ]; thenn mkdir $DUMP_ROOTnfinnDUMP_DATE=`date +%Y%m%d%H%M%S`nDUMP_DIR=$DUMP_ROOT/dump-$DUMP_DATEnif [ ! -d $DUMP_DIR ]; thenn mkdir $DUMP_DIRnfinnfor PID in $DUMP_PIDS ; don#Full thread dump 用来查线程占用 ,死锁等问题n $JAVA_HOME/bin/jstack $PID > $DUMP_DIR/jstack-$PID.dump 2>&1n echo -e ".c"n#打印出一个给定的Java进程 、Java core文件或远程Debug服务器的Java配置信息 ,具体包括Java系统属性和JVM命令行参数。n $JAVA_HOME/bin/jinfo $PID > $DUMP_DIR/jinfo-$PID.dump 2>&1n echo -e ".c"n#jstat能够动态打印jvm(Java Virtual Machine Statistics Monitoring Tool)的相关统计信息 。如young gc执行的次数 、full gc执行的次数  ,各个内存分区的空间大小和可使用量等信息 。n $JAVA_HOME/bin/jstat -gcutil $PID > $DUMP_DIR/jstat-gcutil-$PID.dump 2>&1n echo -e ".c"n $JAVA_HOME/bin/jstat -gccapacity $PID > $DUMP_DIR/jstat-gccapacity-$PID.dump 2>&1n echo -e ".c"n#未指定选项时 ,jmap打印共享对象的映射。对每个目标VM加载的共享对象 ,其起始地址 、映射大小及共享对象文件的完整路径将被打印出来, n $JAVA_HOME/bin/jmap $PID > $DUMP_DIR/jmap-$PID.dump 2>&1n echo -e ".c"n#-heap打印堆情况的概要信息 ,包括堆配置 ,各堆空间的容量 、已使用和空闲情况 n $JAVA_HOME/bin/jmap -heap $PID > $DUMP_DIR/jmap-heap-$PID.dump 2>&1n echo -e ".c"n#-dump将jvm的堆中内存信息输出到一个文件中,然后可以通过eclipse memory analyzer进行分析n#注意 :这个jmap使用的时候jvm是处在假死状态的 ,只能在服务瘫痪的时候为了解决问题来使用 ,否则会造成服务中断。n $JAVA_HOME/bin/jmap -dump:format=b,file=$DUMP_DIR/jmap-dump-$PID.dump $PID 2>&1n echo -e ".c"n#显示被进程打开的文件信息nif [ -r /usr/sbin/lsof ]; thenn /usr/sbin/lsof -p $PID > $DUMP_DIR/lsof-$PID.dumpn echo -e ".c"n findonen#主要负责收集、汇报与存储系统运行信息的。nif [ -r /usr/bin/sar ]; thenn /usr/bin/sar > $DUMP_DIR/sar.dumpnecho -e ".c"nfin#主要负责收集、汇报与存储系统运行信息的 。nif [ -r /usr/bin/uptime ]; thenn /usr/bin/uptime > $DUMP_DIR/uptime.dumpnecho -e ".c"nfin#内存查看nif [ -r /usr/bin/free ]; thenn /usr/bin/free -t > $DUMP_DIR/free.dumpnecho -e ".c"nfin#可以得到关于进程 、内存 、内存分页、堵塞IO、traps及CPU活动的信息。nif [ -r /usr/bin/vmstat ]; thenn /usr/bin/vmstat > $DUMP_DIR/vmstat.dumpnecho -e ".c"nfin#报告与CPU相关的一些统计信息nif [ -r /usr/bin/mpstat ]; thenn /usr/bin/mpstat > $DUMP_DIR/mpstat.dumpnecho -e ".c"nfin#报告与IO相关的一些统计信息nif [ -r /usr/bin/iostat ]; thenn /usr/bin/iostat > $DUMP_DIR/iostat.dumpnecho -e ".c"nfin#报告与网络相关的一些统计信息nif [ -r /bin/netstat ]; thenn /bin/netstat > $DUMP_DIR/netstat.dumpnecho -e ".c"nfinecho "OK!"nn

常用工具安装

#!/usr/bin/env bashnn# ---------------------------------------------------------------------------------n# 控制台颜色nBLACK="033[1;30m"nRED="033[1;31m"nGREEN="033[1;32m"nYELLOW="033[1;33m"nBLUE="033[1;34m"nPURPLE="033[1;35m"nCYAN="033[1;36m"nRESET="$(tput sgr0)"n# ---------------------------------------------------------------------------------nnprintf "${ BLUE}n"ncat << EOFn###################################################################################n# 安装常用命令工具n# 命令工具清单如下:n# 核心工具 :df、du、chkconfign# 网络工具:ifconfig 、netstat 、route 、iptablesn# IP工具 :ip 、ss 、ping 、tracepath 、tracerouten# DNS工具:dig 、host、nslookup、whoisn# 端口工具 :lsof、nc、telnetn# 下载工具:curl 、wgetn# 编辑工具 :emacs、vimn# 流量工具:iftop 、nethogsn# 抓包工具:tcpdumpn# 压缩工具:unzip、zipn# 版本控制工具:git、subversionn#n###################################################################################nEOFnprintf "${ RESET}n"nnprintf "n${ GREEN}>>>>>>>>> 安装常用命令工具开始${ RESET}n"nn# 核心工具nprintf "n${ CYAN}>>>> install coreutils(df、du)${ RESET}n"nyum install -y coreutilsnprintf "n${ CYAN}>>>> install chkconfig${ RESET}n"nyum install -y chkconfignn# 网络工具nprintf "n${ CYAN}>>>> install net-tools(ifconfig 、netstat 、route)${ RESET}n"nyum install -y net-toolsnprintf "n${ CYAN}>>>> install iptables${ RESET}n"nyum install -y iptablesnn# IP工具nprintf "n${ CYAN}>>>> install iputils(ping、tracepath)${ RESET}n"nyum install -y iputilsnprintf "n${ CYAN}>>>> install traceroute${ RESET}n"nyum install -y traceroutenprintf "n${ CYAN}>>>> install iproute(ip 、ss)${ RESET}n"nyum install -y iproutenn# 端口工具nprintf "n${ CYAN}>>>> install lsof${ RESET}n"nyum install -y lsofnprintf "n${ CYAN}>>>> install nc${ RESET}n"nyum install -y ncnprintf "n${ CYAN}>>>> install netstat${ RESET}n"nyum install -y netstatnn# DNS工具nprintf "n${ CYAN}>>>> install bind-utils(dig、host 、nslookup)${ RESET}n"nyum install -y bind-utilsnprintf "n${ CYAN}>>>> install whois${ RESET}n"nyum install -y whoisnn# 下载工具nprintf "n${ CYAN}>>>> install curl${ RESET}n"nyum install -y curlnprintf "n${ CYAN}>>>> install wget${ RESET}n"nyum install -y wgetnn# 编辑工具nprintf "n${ CYAN}>>>> install emacs${ RESET}n"nyum install -y emacsnprintf "n${ CYAN}>>>> install vim${ RESET}n"nyum install -y vimnn# 流量工具nprintf "n${ CYAN}>>>> install iftop${ RESET}n"nyum install -y iftopnprintf "n${ CYAN}>>>> install nethogs${ RESET}n"nyum install -y nethogsnn# 抓包工具nprintf "n${ CYAN}>>>> install tcpdump${ RESET}n"nyum install -y tcpdumpnn# 压缩工具nprintf "n${ CYAN}>>>> install unzip${ RESET}n"nyum install -y unzipnn# 版本控制工具nprintf "n${ CYAN}>>>> install git${ RESET}n"nyum install -y gitnprintf "n${ CYAN}>>>> install subversion${ RESET}n"nyum install -y subversionnnprintf "n${ GREEN}<<<<<<<< 安装常用命令工具结束${ RESET}n"nn

常用lib库安装

#!/usr/bin/env bashnn# ---------------------------------------------------------------------------------n# 控制台颜色nBLACK="033[1;30m"nRED="033[1;31m"nGREEN="033[1;32m"nYELLOW="033[1;33m"nBLUE="033[1;34m"nPURPLE="033[1;35m"nCYAN="033[1;36m"nRESET="$(tput sgr0)"n# ---------------------------------------------------------------------------------nnprintf "${ BLUE}n"ncat << EOFn###################################################################################n# 安装常见 libn# 如果不知道命令在哪个 lib,可以使用 yum search xxx 来查找n# lib 清单如下 :n# gcc gcc-c++ kernel-devel libtooln# openssl openssl-develn# zlib zlib-develn# pcren###################################################################################nEOFnprintf "${ RESET}n"nnprintf "n${ GREEN}>>>>>>>>> 安装常见 lib 开始${ RESET}n"nnprintf "n${ CYAN}>>>> install gcc gcc-c++ kernel-devel libtool${ RESET}n"nyum -y install make gcc gcc-c++ kernel-devel libtoolnnprintf "n${ CYAN}>>>> install openssl openssl-devel${ RESET}n"nyum -y install make openssl openssl-develnnprintf "n${ CYAN}>>>> install zlib zlib-devel${ RESET}n"nyum -y install make zlib zlib-develnnprintf "n${ CYAN}>>>> install pcre${ RESET}n"nyum -y install pcrennprintf "n${ GREEN}<<<<<<<< 安装常见 lib 结束${ RESET}n"nn

系统检查脚本

#!/usr/bin/env bashnn##############################################################################n# console colornC_RESET="$(tput sgr0)"nC_BLACK="033[1;30m"nC_RED="033[1;31m"nC_GREEN="033[1;32m"nC_YELLOW="033[1;33m"nC_BLUE="033[1;34m"nC_PURPLE="033[1;35m"nC_CYAN="033[1;36m"nC_WHITE="033[1;37m"n##############################################################################nnprintf "${ C_PURPLE}"ncat << EOFn###################################################################################n# 系统信息检查脚本n###################################################################################nEOFnprintf "${ C_RESET}"nn[[ $(id -u) -gt 0 ]] && echo "请用root用户执行此脚本 !" && exit 1nsysversion=$(rpm -q centos-release | cut -d- -f3)ndouble_line="==============================================================="nline="----------------------------------------------"nn# 打印头部信息nprintHeadInfo() { n cat << EOFn+---------------------------------------------------------------------------------+n| 欢迎使用 【系统信息检查脚本】 |n+---------------------------------------------------------------------------------+nEOFn}nn# 打印尾部信息nprintFootInfo() { n cat << EOFn+---------------------------------------------------------------------------------+n| 脚本执行结束,感谢使用!|n+---------------------------------------------------------------------------------+nEOFn}nnoptions=( "获取系统信息" "获取服务信息" "获取CPU信息" "获取系统网络信息" "获取系统内存信息" "获取系统磁盘信息" "获取CPU/内存占用TOP10" "获取系统用户信息" "输出所有信息" "退出" )nprintMenu() { n printf "${ C_BLUE}"n printf "主菜单 :n"n for i in "${ !options[@]}"; don index=`expr ${ i} + 1`n val=`expr ${ index} % 2`n printf "t(%02d) %-30s" "${ index}" "${ options[$i]}"n if [[ ${ val} -eq 0 ]]; thenn printf "n"n fin donen printf "${ C_BLUE}请输入需要执行的指令:n"n printf "${ C_RESET}"n}nn# 获取系统信息nget_systatus_info() { n sys_os=$(uname -o)n sys_release=$(cat /etc/redhat-release)n sys_kernel=$(uname -r)n sys_hostname=$(hostname)n sys_selinux=$(getenforce)n sys_lang=$(echo $LANG)n sys_lastreboot=$(who -b | awk '{ print $3,$4}')n sys_runtime=$(uptime | awk '{ print $3,$4}' | cut -d, -f1)n sys_time=$(date)n sys_load=$(uptime | cut -d: -f5)nn cat << EOFn【系统信息】n系统: ${ sys_os}n发行版本: ${ sys_release}n系统内核: ${ sys_kernel}n主机名: ${ sys_hostname}nselinux状态: ${ sys_selinux}n系统语言: ${ sys_lang}n系统当前时间: ${ sys_time}n系统最后重启时间: ${ sys_lastreboot}n系统运行时间: ${ sys_runtime}n系统负载: ${ sys_load}nEOFn}nn# 获取CPU信息nget_cpu_info() { n Physical_CPUs=$(grep "physical id" /proc/cpuinfo | sort | uniq | wc -l)n Virt_CPUs=$(grep "processor" /proc/cpuinfo | wc -l)n CPU_Kernels=$(grep "cores" /proc/cpuinfo | uniq | awk -F ': ' '{ print $2}')n CPU_Type=$(grep "model name" /proc/cpuinfo | awk -F ': ' '{ print $2}' | sort | uniq)n CPU_Arch=$(uname -m)n cat << EOFn【CPU信息】n物理CPU个数:$Physical_CPUsn逻辑CPU个数:$Virt_CPUsn每CPU核心数:$CPU_KernelsnCPU型号:$CPU_TypenCPU架构:$CPU_ArchnEOFn}nn# 获取服务信息nget_service_info() { n port_listen=$(netstat -lntup | grep -v "Active Internet")n kernel_config=$(sysctl -p 2> /dev/null)n if [[ ${ sysversion} -gt 6 ]]; thenn service_config=$(systemctl list-unit-files --type=service --state=enabled | grep "enabled")n run_service=$(systemctl list-units --type=service --state=running | grep ".service")n elsen service_config=$(/sbin/chkconfig | grep -E ":on|:启用" | column -t)n run_service=$(/sbin/service --status-all | grep -E "running")n fin cat << EOFn【服务信息】n${ service_config}n ${ line}n运行的服务:n${ run_service}n ${ line}n监听端口:n${ port_listen}n ${ line}n内核参考配置:n${ kernel_config}nEOFn}nn# 获取系统内存信息nget_mem_info() { n check_mem=$(free -m)n MemTotal=$(grep MemTotal /proc/meminfo | awk '{ print $2}') #KBn MemFree=$(grep MemFree /proc/meminfo | awk '{ print $2}') #KBn let MemUsed=MemTotal-MemFreen MemPercent=$(awk "BEGIN { if($MemTotal==0){ printf 100}else{ printf "%.2f",$MemUsed*100/$MemTotal}}")n report_MemTotal="$((MemTotal/1024))" "MB" #内存总容量(MB)n report_MemFree="$((MemFree/1024))" "MB" #内存剩余(MB)n report_MemUsedPercent=$(free | sed -n '2p' | gawk 'x = int(( $3 / $2 ) * 100) { print x}' | sed 's/$/%/')nn cat << EOFn【内存信息】n内存总容量(MB): ${ report_MemTotal}n内存剩余量(MB):${ report_MemFree}n内存使用率: ${ report_MemUsedPercent}nEOFn}nn# 获取系统网络信息nget_net_info() { n pri_ipadd=$(ip addr | awk '/^[0-9]+: / { }; /inet.*global/ { print gensub(/(.*)/(.*)/, "1", "g", $2)}')n pub_ipadd=$(curl ifconfig.me -s)n gateway=$(ip route | grep default | awk '{ print $3}')n mac_info=$(ip link | egrep -v "lo" | grep link | awk '{ print $2}')n dns_config=$(egrep -v "^$|^#" /etc/resolv.conf)n route_info=$(route -n)n cat << EOFn【网络信息】n系统公网地址:${ pub_ipadd}n系统私网地址:${ pri_ipadd}n网关地址:${ gateway}nMAC地址:${ mac_info}n路由信息:n${ route_info}nDNS 信息:n${ dns_config}nEOFn}nn# 获取系统磁盘信息nget_disk_info() { n disk_info=$(fdisk -l | grep "Disk /dev" | cut -d, -f1)n disk_use=$(df -hTP | awk '$2!="tmpfs"{ print}')n disk_percent=$(free | sed -n '2p' | gawk 'x = int(( $3 / $2 ) * 100) { print x}' | sed 's/$/%/')n disk_inode=$(df -hiP | awk '$1!="tmpfs"{ print}')nn cat << EOFn【磁盘信息】n${ disk_info}n磁盘使用: ${ disk_use}n磁盘使用百分比: ${ disk_percent}ninode信息: ${ disk_inode}nEOFn}nn# 获取系统用户信息nget_sys_user() { n login_user=$(awk -F: '{ if ($NF=="/bin/bash") print $0}' /etc/passwd)n ssh_config=$(egrep -v "^#|^$" /etc/ssh/sshd_config)n sudo_config=$(egrep -v "^#|^$" /etc/sudoers | grep -v "^Defaults")n host_config=$(egrep -v "^#|^$" /etc/hosts)n crond_config=$(for cronuser in /var/spool/cron/*; don ls ${ cronuser} 2> /dev/null | cut -d/ -f5; egrep -v "^$|^#" ${ cronuser} 2> /dev/null;n echo "";n done)n cat << EOFn【用户信息】n系统登录用户:n${ login_user}n ${ line}nssh 配置信息:n${ ssh_config}n ${ line}nsudo 配置用户:n${ sudo_config}n ${ line}n定时任务配置:n${ crond_config}n ${ line}nhosts 信息:n${ host_config}nEOFn}nn# 获取CPU/内存占用TOP10nget_process_top_info() { nn top_title=$(top -b n1 | head -7 | tail -1)n cpu_top10=$(top -b n1 | head -17 | tail -11)n mem_top10=$(top -b n1 | head -17 | tail -10 | sort -k10 -r)nn cat << EOFn【TOP10】nCPU占用TOP10:n${ cpu_top10}n内存占用TOP10:n${ top_title}n ${ mem_top10}nEOFn}nnshow_dead_process() { n printf "僵尸进程:n"n ps -al | gawk '{ print $2,$4}' | grep Zn}nnget_all_info() { n get_systatus_infon echo ${ double_line}n get_service_infon echo ${ double_line}n get_cpu_infon echo ${ double_line}n get_net_infon echo ${ double_line}n get_mem_infon echo ${ double_line}n get_disk_infon echo ${ double_line}n get_process_top_infon echo ${ double_line}n get_sys_usern}nnmain() { n while [[ 1 ]]n don printMenun read optionn local index=$[ ${ option} - 1 ]n case ${ options[${ index}]} inn "获取系统信息")n get_systatus_info ;;n "获取服务信息")n get_service_info ;;n "获取CPU信息")n get_cpu_info ;;n "获取系统网络信息")n get_net_info ;;n "获取系统内存信息")n get_mem_info ;;n "获取系统磁盘信息")n get_disk_info ;;n "获取CPU/内存占用TOP10")n get_process_top_info ;;n "获取系统用户信息")n get_sys_user ;;n "输出所有信息")n get_all_info > sys.logn printf "${ C_GREEN}信息已经输出到 sys.log 中。${ C_RESET}nn"n ;;n "退出")n exit ;;n *)n clearn echo "抱歉,不支持此选项" ;;n esacn donen}nn######################################## MAIN ########################################nprintHeadInfonmainnprintFootInfonprintf "${ C_RESET}"n

sed进阶

#!/bin/bashnn#多个空格只保留一个n#sed '/./,/^$/!d' testnn#删除开头的空白行n#sed '/./,$!d' testnn#删除结尾的空白行nsed '{ n:startn /^n*$/{ $d; N; b start}n}' testnn#删除html标签n#有问题n#s/<.*>//gnn#sed 's/<[^>]*>//g' test1nn#sed 's/<[^>]*>//g;/^$/d' test1nn#and符号,代表替换命令中的匹配模式,不管预定义模式是什么文本,都可以用and符号替换,and符号会提取匹配替换命令中指定替换模式中的所有字符串necho "The cat sleeps in his hat" | sed 's/.at/"&"/g'nn#替换单独的单词necho "The System Administrator manual" | sed 's/(System) Administrator/1 user/'nn#在长数字中插入逗号necho "1234567" | sed '{ :start; s/(.*[0-9])([0-9]{ 3})/1,2/; t start}'nn#给文件中的行编号nsed '=' test | sed 'N; s/n/ /'

Linux CPU的上下文切换

我们都知道 Linux 是一个多任务操作系统 ,它支持的任务同时运行的数量远远大于 CPU 的数量。当然 ,这些任务实际上并不是同时运行的(Single CPU) ,而是因为系统在短时间内将 CPU 轮流分配给任务,造成了多个任务同时运行的假象。

CPU 上下文(CPU Context)

在每个任务运行之前 ,CPU 需要知道在哪里加载和启动任务 。这意味着系统需要提前帮助设置 CPU 寄存器和程序计数器。

CPU 寄存器是内置于 CPU 中的小型但速度极快的内存。程序计数器用于存储 CPU 正在执行的或下一条要执行指令的位置。

它们都是 CPU 在运行任何任务之前必须依赖的依赖环境,因此也被称为 “CPU 上下文”。如下图所示:

Linux合集之Linux实用运维脚本分享及Linux CPU的上下文切换

图片

知道了 CPU 上下文是什么,我想你理解 CPU 上下文切换就很容易了  。“CPU上下文切换”指的是先保存上一个任务的 CPU 上下文(CPU寄存器和程序计数器),然后将新任务的上下文加载到这些寄存器和程序计数器中,最后跳转到程序计数器。

这些保存的上下文存储在系统内核中 ,并在重新安排任务执行时再次加载。这确保了任务的原始状态不受影响 ,并且任务似乎在持续运行。

CPU 上下文切换的类型

你可能会说 CPU 上下文切换无非就是更新 CPU 寄存器和程序计数器值,而这些寄存器是为了快速运行任务而设计的,那为什么会影响 CPU 性能呢 ?

在回答这个问题之前,请问 ,你有没有想过这些“任务”是什么 ?你可能会说一个任务就是一个进程或者一个线程。是的,进程和线程正是最常见的任务,但除此之外 ,还有其他类型的任务 。

别忘了硬件中断也是一个常见的任务,硬件触发信号 ,会引起中断处理程序的调用。

因此 ,CPU 上下文切换至少有三种不同的类型:

  • 进程上下文切换
  • 线程上下文切换
  • 中断上下文切换

让我们一一来看看 。

进程上下文切换

Linux 按照特权级别将进程的运行空间划分为内核空间和用户空间 ,分别对应下图中 Ring 0 和 Ring 3 的 CPU 特权级别的 。

  • 内核空间(Ring 0)拥有最高权限,可以直接访问所有资源
  • 用户空间(Ring 3)只能访问受限资源 ,不能直接访问内存等硬件设备 。它必须通过系统调用被陷入(trapped)内核中才能访问这些特权资源 。
Linux合集之Linux实用运维脚本分享及Linux CPU的上下文切换

图片

从另一个角度看  ,一个进程既可以在用户空间也可以在内核空间运行。当一个进程在用户空间运行时,称为该进程的用户态 ,当它落入内核空间时  ,称为该进程的内核态。

从用户态到内核态的转换需要通过系统调用来完成。例如 ,当我们查看一个文件的内容时 ,我们需要以下系统调用:

  • open():打开文件
  • read() :读取文件的内容
  • write():将文件的内容写入到输出文件(包括标准输出)
  • close() :关闭文件

那么在上述系统调用过程中是否会发生 CPU 上下文切换呢?当然是的。

这需要先保存 CPU 寄存器中原来的用户态指令的位置 。接下来,为了执行内核态的代码,需要将 CPU 寄存器更新到内核态指令的新位置 。最后是跳转到内核态运行内核任务。

那么系统调用结束后  ,CPU 寄存器需要恢复原来保存的用户状态 ,然后切换到用户空间继续运行进程。

因此  ,在一次系统调用的过程中,实际上有两次 CPU 上下文切换。

但需要指出的是,系统调用进程不会涉及进程切换 ,也不会涉及虚拟内存等系统资源切换 。这与我们通常所说的“进程上下文切换”不同。进程上下文切换是指从一个进程切换到另一个进程,而系统调用期间始终运行同一个进程

系统调用过程通常被称为特权模式切换 ,而不是上下文切换。但实际上,在系统调用过程中 ,CPU 的上下文切换也是不可避免的 。

进程上下文切换 vs 系统调用

那么进程上下文切换和系统调用有什么区别呢?首先 ,进程是由内核管理的,进程切换只能发生在内核态。因此 ,进程上下文不仅包括虚拟内存 、栈和全局变量等用户空间资源,还包括内核栈和寄存器等内核空间的状态 。

所以进程上下文切换比系统调用要多出一步 :

在保存当前进程的内核状态和 CPU 寄存器之前 ,需要保存进程的虚拟内存  、栈等;并加载下一个进程的内核状态 。

根据 Tsuna 的测试报告  ,每次上下文切换需要几十纳秒至微秒的 CPU 时间。这个时间是相当可观的 ,尤其是在大量进程上下文切换的情况下 ,很容易导致 CPU 花费大量时间来保存和恢复寄存器、内核栈 、虚拟内存等资源 。这正是我们在上一篇文章中谈到的,一个导致平均负载上升的重要因素。

那么 ,该进程何时会被调度/切换到在 CPU 上运行?其实有很多场景,下面我为大家总结一下:

  • 当一个进程的 CPU 时间片用完时,它会被系统挂起 ,并切换到其他等待 CPU 运行的进程。
  • 当系统资源不足(如内存不足)时 ,直到资源充足之前 ,进程无法运行 。此时进程也会被挂起,系统会调度其他进程运行 。
  • 当一个进程通过 sleep 函数自动挂起自己时,自然会被重新调度 。
  • 当优先级较高的进程运行时,为了保证高优先级进程的运行,当前进程会被高优先级进程挂起运行。
  • 当发生硬件中断时,CPU 上的进程会被中断挂起 ,转而执行内核中的中断服务程序。

了解这些场景是非常有必要的,因为一旦上下文切换出现性能问题 ,它们就是幕后杀手。

线程上下文切换

线程和进程最大的区别在于,线程是任务调度的基本单位,而进程是资源获取的基本单位。

说白了,内核中所谓的任务调度,实际的调度对象是线程;而进程只为线程提供虚拟内存和全局变量等资源 。所以 ,对于线程和进程 ,我们可以这样理解 :

  • 当一个进程只有一个线程时,可以认为一个进程等于一个线程
  • 当一个进程有多个线程时,这些线程共享相同的资源 ,例如虚拟内存和全局变量 。
  • 此外 ,线程也有自己的私有数据,比如栈和寄存器,在上下文切换时也需要保存。

这样,线程的上下文切换其实可以分为两种情况 :

  • 首先,前后两个线程属于不同的进程。此时,由于资源不共享,切换过程与进程上下文切换相同 。
  • 其次 ,前后两个线程属于同一个进程 。此时,由于虚拟内存是共享的 ,所以切换时虚拟内存的资源保持不变,只需要切换线程的私有数据 、寄存器等未共享的数据。

显然 ,同一个进程内的线程切换比切换多个进程消耗的资源要少。这也是多线程替代多进程的优势  。

中断上下文切换

除了前面两种上下文切换之外,还有另外一种场景也输出 CPU 上下文切换的,那就是中断 。

为了快速响应事件 ,硬件中断会中断正常的调度和执行过程  ,进而调用中断处理程序。

在中断其他进程时 ,需要保存进程的当前状态 ,以便中断后进程仍能从原始状态恢复。

与进程上下文不同 ,中断上下文切换不涉及进程的用户态 。因此  ,即使中断进程中断了处于用户态的进程,也不需要保存和恢复进程的虚拟内存  、全局变量等用户态资源。

另外,和进程上下文切换一样 ,中断上下文切换也会消耗 CPU 。过多的切换次数会消耗大量的 CPU 资源 ,甚至严重降低系统的整体性能 。因此 ,当您发现中断过多时 ,需要注意排查它是否会对您的系统造成严重的性能问题。

结论

综上所述,无论哪种场景导致上下文切换 ,你都应该知道:

CPU 上下文切换是保证 Linux 系统正常运行的核心功能之一 ,一般不需要我们特别关注  。

但是过多的上下文切换会消耗 CPU 的时间来保存和恢复寄存器 、内核栈、虚拟内存等数据,从而缩短进程的实际运行时间,导致系统整体性能显着下降 。

(作者:汽车音响)