网络知识 娱乐 Linux合集之Linux实用运维脚本分享及Linux CPU的上下文切换

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 的时间来保存和恢复寄存器、内核栈、虚拟内存等数据,从而缩短进程的实际运行时间,导致系统整体性能显着下降。