10、进程管理,case和函数 学习笔记


ps:显示系统当前进程状态的命令ps a 所有与终端相关的进程 ps x 所有与终端无关的进程 ps u 以用户为中心显示进程相关信息 VSZ: 虚拟内存集,Virutal menmory Size RSS: 常驻内存集 STAT: R:运行或可运行 S:可中断睡眠 D:不可中断睡眠 T:停止 Z:僵死 s:session leader 有子进程 +:前台进程 l:多线程进程 N:低优先级进程 <:>

START:

启动时间

TIME:

累计占用的内存时间

COMMAND

[]表示内核线程

ps [option]

-e 显示所有进程

-f 以进程的长格式显示

-F 显示额外信息

-H 显示进程的层次信息

-o 自定义要显示的信息

ps axo pid,command

ps aux 常用组合

ps -ef 常用组合

ps -eFH 常用组合

pstree:显示进程树

pgrep:

-U Username 仅显示指定用户的进程的进程的PID

-G Groupname 仅显示指定用户组的进程的进程的PID

pidof:显示指定命令所启动的pid

pidof command

top:

top – 10:35:59 up 2 days, 16:26, 3 users, load average: 0.00, 0.00, 0.00

系统当前时间 系统运行时长 登录的用户 平均负载:1分钟,五分钟,15分钟

Tasks: 110 total, 1 running, 109 sleeping, 0 stopped, 0 zombie

总进程数 运行进程数 休眠进程数 停止进程数 僵死进程数

Cpu(s): 0.0%us, 0.1%sy, 0.0%ni, 99.8%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st

用户空间占比 系统占比nice占比 空闲占比等待占比 硬中断占比 软中断占比 被占用占比

Mem: 1918400k total, 406832k used, 1511568k free, 153868k buffers

Swap: 2097144k total, 0k used, 2097144k free, 90524k cached

M: 按内存占用百分比大小排序

P:按cpu占用百分比大小排序,默认

T:按累计占有时长进行排序

1:多CPU时按数字1可以分开显示

l: 是否显示负载信息

t:是否显示cpu和进程的统计信息

m:是否显示内存和交互分区的信息

q:退出

k:kill,杀掉进程

s:改变top刷新频率

常用选项:

-d # :指定刷新时间间隔

-n # :指定刷新的次数

-b :以批次显示top的刷新

htop

u:选择指定用户的进程

l: 显示进程所打开的文件列表

s:显示进程执行的系统调用

a:显示进程的进程的cpu上

#:快速将光标定位之指定的PID进程上

quit

vmstst

procs ———–memory———- —swap– —–io—- –system– —–cpu—–

r b swpd free buff cache si so bi bo in cs us sy id wa st

0 0 0 57460 54564 285520 0 0 30 5 21 14 0 0 99 1

procs

r:运行或等待cpu时间片的进程的个数

b:被阻塞(通常为等待I/O完成)的进程的长度

memory

swpd:从物理内存交互至swap中的数据

free:未使用的内存大小

buffer:buffer空间大小,通常与缓存写操作相关

cache:cache空间大小,通常与缓存读操作相关

swap

si:swap in 数据进入swap中的数据量,通常是速率。kb/s

so:swap out 数据离开swap中的数据量,通常是速率。kb/s

io:

bi:block in:从块设备读入的数据量,通常是速率,kb/s

bo:block out:保存至块设备中的数据量,通常是速率,kb/s

in:中断发生频率。每秒的中断数

cs:context switch 上下文切换,进程切换,通常是速率,kb/s

cpu:

us:用户空间的使用率

sy:内核空间的使用率

id:空闲

wa:等待的

st:被偷走的

使用格式

vmstat [delay [counts]]

-s:显示内存统计数据

nice,renice

进程:nice

用来手动调整进程优先级,默认nice为0.其默认优先级为120

nice值取值范围 :-20,19

nice值对应优先级 :100,139

nice:普通用户只能调大此值

对于尚未启动的程序

nice -n # COMMAND 进程以#的nice值启动

对于运行中的进程:

renice # PID 调整指定PID的nice值

ps axo ni command pid 查看进程的nice值

进程间通信(IPC):

信号:

kill命令:可以实现向其他进程发送信息

kill -l 或 man 7 signal 可以查看可以向进程发送的所有信息

kill -SIGNAL PID 杀死指定进程(SINGAL可以使数字代号也可以是信号名称)

1) SIGHUP 让程序重读配置文件,而不用重启程序

2) SIGINT 中断信号。Ctrl+c即发送此信号

9) SIGKILL 杀死进程

15) SIGTERM 终止进程,比较优雅(默认)

killall -SIGNAL 进程名 杀死指定程序的所有进程

Linux的作业控制

前台作业:占据着一个终端

后台作业:作业执行时不占据终端,作业启动后就释放终端

非守护进程类的程序,启动以后都在前台工作

如果已经启动:前台–>后台。ctrl+z把前台作业送往后台,作业被”停止“

如果尚未启动:COMMAND &

退出当前会话,作业也会终止,因为作业与当前终端相关,如果把作业送往后台后,不期望作业随终止结束而停止

nohup COMMAND &

如何让送往后台的作业继续执行:

fg [[%]作业号码]:将作业调回前台继续进行

bg [[%]作业号码]:让作业在后台继续进行

默认的为最后一个进入后台的任务

kill %作业号码:终止作业

查看作业号:

jobs

pmap pid 查看进程的内存占用情况

00007fb60640d000 4K rw— /sbin/init

起始地址 空间 权限

bash脚本编程:之case语句

case语句的语法格式:

case expression in

pattern1)

suite1

;;

pattern2)

suite2

;;

patternn)

suiten

;;

*)

other_suite

;;

esac

case中各pattern可以使用模式:

a|b a或者b

* 匹配任意长度的任意字符;

? 匹配任意单个字符;

[-] 范围匹配

练习:写一个脚本,接受如此格式

script.sh {start|stop|restart|status}

1、如是start,那么创建/var/lock/subsys/script.sh,显示启动成功;

2、如果参数是stop,则删除/var/lock/subsys/script.sh,显示停止成功

3、如果restart,则删除,再创建,显示成功;

4、如果status, 如果文件存在,则显示running,否则,显示stopped

#!/bin/bash

#

myService=`basename $0`

lockFile=”/var/lock/subsys/$myService”

[ $# -lt 1 ] && echo “Usage: $myService {start|stop|restart|status}” && exit 4

case $1 in

‘start’)

touch $lockFile

echo “Starting $myService OK”

;;

‘stop’)

rm -f $lockFile

echo “Stopping $myService OK”

;;

‘restart’)

rm -f $lockFile

touch $lockFile

echo “Restarting $myService OK”

;;

‘status’)

if [ -f $lockFile ]; then

echo “$myService is running”

else

echo “$myService is stopped”

fi

;;

*)

echo “Usage: $myService {start|stop|restart|status}”

exit 3

;;

esac

练习:写一个脚本,能对/etc/目录进行打包备份,备份位置为/backup/etc-日期.后缀

1、显示如下菜单给用户:

xz) xz compress

gzip) gzip compress

bip2) bzip2 compress

2、根据用户指定的压缩工具使用tar打包压缩;

3、默认为xz;输入错误则需要用户重新输入;

#!/bin/bash

#

[ -d /backup ] || mkdir /backup

cat

Plz choose a compress tool:

xz) xz compress

gzip) gzip compress

bip2) bzip2 compress

EOF

while true; do

read -p “Your option: ” option

option=${option:-xz}

case $option in

xz)

compressTool=’J’

suffix=’xz’

break ;;

gzip)

compressTool=’z’

suffix=’gz’

break ;;

bzip2)

compressTool=’j’

suffix=’bz2′

break ;;

*)

echo “wrong option.” ;;

esac

done

tar ${compressTool}cf /backup/etc-`date +%F-%H-%M-%S`.tar.$suffix /etc/*

练习:写一个脚本,完成如下功能

说明:此脚本能够为指定网卡创建别名,指定地址;使用格式:mkethalias.sh -v|–verbose -i|–interface ethX

1、-i选项用于指定网卡;

2、如果网卡存在:在命令行,请用户指定一个别名;

3、让用户指定IP和掩码;

4、用户可以同时使用-v或–verbose选项:如果使用了,则在配置完成后,显示配置结果;否则,则不予显示;

#!/bin/bash

#

debug=0

while [ $# -ge 1 ]; do

case $1 in

-i|–interface)

ethcard=”$2″

shift 2 ;;

-v|–verbose)

debug=1

shift

;;

*)

echo “Wrong options or arguments.”

echo “Usage: `basename $0` [-v|–verbose] -i|–interface Interface”

shift $#

;;

esac

done

# echo “Interface: $ethcard , Verbose Flag: $debug “

! ifconfig $ethcard &> /dev/null && echo “No this interface…” && exit 3

read -p “Enter an alias: ” ethAlias

read -p “Enter IP: ” ipAddr

read -p “Mask: ” netMask

ifconfig $ethAlias $ipAddr netmask $netMask

[ $debug -eq 1 ] && ifconfig $ethAlias

bash脚本编程之函数

可被调用:函数有函数名

函数出现的地方,会自动被替换成函数定义的代码

函数定义

语法:

FuncName() {

函数体

}

function FuncName {

函数体

}

函数有两种返回值:

正常返回的数据:

函数中的打印语句,如echo或print

函数中命令的执行结果

执行状态返回值:

取决于函数中执行的最后一条语句

自定义:return N

函数可以接受参数:

在函数体可以使用类似脚本调用位置参数一样的参数

$1, $2, …

$#

$*, $@

练习:写一个脚本,完成如下功能

1、显示如下菜单

disk) show disk info

mem) show memory info

cpu) show cpuinfo

2、显示用户选定的内容;

#!/bin/bash

#

ShowMenu() {

cat

disk) show disk info

mem) show memory info

cpu) show cpuinfo

EOF

}

main() {

ShowMenu

read -p “Plz choose an option: ” option

case $option in

disk)

df -h

;;

mem)

free -m

;;

cpu)

cat /proc/cpuinfo

;;

*)

echo “Wrong option”

esac

}

main

如果在函数中使用变量:变量作用域

在函数中使用了在主程序中声明的变量,重新赋值会直接修改主程序中的变量;

如果不期望函数与主程序中的变量冲突,函数中使用变量都用local修饰;即使用局部变量;

在函数中使用了在主程序中没有声明的变量,在函数执行结束后即被撤消,无论是否使用local修饰符;

如果想把脚本的全部位置参数,统统传递给脚本中某函数使用,怎么办?

使用$*传递

练习:写一个脚本,判定172.16.0.0网络内有哪些主机在线,在线的用绿色显示,不在线的用红色显示;要求,编程中使用函数;

#!/bin/bash

Ping(){

ipAddr=172.16.$1.$2

ping -c 1 -w 1 $ipAddr >> /dev/null

if [ $? -eq 0 ];then

echo -e “33[32m$ipAddr33[0m”

else

echo -e “33[31m$ipAddr33[0m”

fi

}

for i in `seq 0 255`;do

for j in `seq 1 254`;do

Ping $i $j

done

done

练习:写一个脚本,完成如下功能(使用函数):

1、提示用户输入一个可执行命令;

2、获取这个命令所依赖的所有库文件(使用ldd命令);

3、复制命令至/mnt/sysroot/对应的目录中

解释:假设,如果复制的是cat命令,其可执行程序的路径是/bin/cat,那么就要将/bin/cat复制到/mnt/sysroot/bin/目录中,如果复制的是useradd命令,而useradd的可执行文件路径为/usr/sbin/useradd,那么就要将其复制到/mnt/sysroot/usr/sbin/目录中;

4、复制各库文件至/mnt/sysroot/对应的目录中,其要求命令;

#!/bin/bash

#

target=/mnt/sysroot

clearCmd() {

if which $cmd &> /dev/null; then

cmdPath=`which –skip-alias $cmd`

else

echo “No such command”

return 5

fi

}

cmdCopy() {

cmdDir=`dirname $1`

[ -d ${target}${cmdDir} ] || mkdir -p ${target}${cmdDir}

[ -f ${target}${1} ] || cp $1 ${target}${cmdDir}

}

libCopy() {

for lib in `ldd $1 | grep -o “/[^[:space:]]{1,}”`; do

libDir=`dirname $lib`

[ -d ${target}${libDir} ] || mkdir -p ${target}${libDir}

[ -f ${target}${lib} ] || cp $lib ${target}${libDir}

done

}

while true; do

read -p “Enter a command: ” cmd

if [ “$cmd” == ‘quit’ ] ;then

echo “quit”

exit 0

fi

clearCmd $cmd

[ $? -eq 5 ] && continue

cmdCopy $cmdPath

libCopy $cmdPath

done

START: 启动时间 TIME: 累计占用的内存时间 COMMAND []表示内核线程

ps [option] -e 显示所有进程 -f 以进程的长格式显示 -F 显示额外信息 -H 显示进程的层次信息-o 自定义要显示的信息 ps axo pid,command
ps aux 常用组合 ps -ef 常用组合 ps -eFH 常用组合

pstree:显示进程树
pgrep: -U Username 仅显示指定用户的进程的进程的PID -G Groupname 仅显示指定用户组的进程的进程的PID

pidof:显示指定命令所启动的pid pidof commandtop:
top – 10:35:59 up 2 days, 16:26, 3 users, load average: 0.00, 0.00, 0.00系统当前时间 系统运行时长 登录的用户 平均负载:1分钟,五分钟,15分钟
Tasks: 110 total, 1 running, 109 sleeping, 0 stopped, 0 zombie总进程数 运行进程数 休眠进程数 停止进程数 僵死进程数
Cpu(s): 0.0%us, 0.1%sy, 0.0%ni, 99.8%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st用户空间占比 系统占比nice占比 空闲占比等待占比 硬中断占比 软中断占比 被占用占比
Mem: 1918400k total, 406832k used, 1511568k free, 153868k buffersSwap: 2097144k total, 0k used, 2097144k free, 90524k cached

M: 按内存占用百分比大小排序 P:按cpu占用百分比大小排序,默认 T:按累计占有时长进行排序 1:多CPU时按数字1可以分开显示 l: 是否显示负载信息 t:是否显示cpu和进程的统计信息 m:是否显示内存和交互分区的信息 q:退出 k:kill,杀掉进程 s:改变top刷新频率

常用选项: -d # :指定刷新时间间隔 -n # :指定刷新的次数 -b :以批次显示top的刷新 htop u:选择指定用户的进程 l: 显示进程所打开的文件列表 s:显示进程执行的系统调用 a:显示进程的进程的cpu上 #:快速将光标定位之指定的PID进程上 quit
vmststprocs ———–memory———- —swap– —–io—- –system– —–cpu—–r b swpd free buff cache si so bi bo in cs us sy id wa st0 0 0 57460 54564 285520 0 0 30 5 21 14 0 0 99 1 procs r:运行或等待cpu时间片的进程的个数 b:被阻塞(通常为等待I/O完成)的进程的长度 memory swpd:从物理内存交互至swap中的数据量 free:未使用的内存大小 buffer:buffer空间大小,通常与缓存写操作相关 cache:cache空间大小,通常与缓存读操作相关 swap si:swap in 数据进入swap中的数据量,通常是速率。kb/s so:swap out 数据离开swap中的数据量,通常是速率。kb/s io: bi:block in:从块设备读入的数据量,通常是速率,kb/s bo:block out:保存至块设备中的数据量,通常是速率,kb/s in:中断发生频率。每秒的中断数 cs:context switch 上下文切换,进程切换,通常是速率,kb/s cpu: us:用户空间的使用率 sy:内核空间的使用率 id:空闲 wa:等待的 st:被偷走的 使用格式 vmstat [delay [counts]] -s:显示内存统计数据

nice,renice
进程:nice 用来手动调整进程优先级,默认nice为0.其默认优先级为120 nice值取值范围 :-20,19 nice值对应优先级 :100,139 nice:普通用户只能调大此值
对于尚未启动的程序 nice -n # COMMAND 进程以#的nice值启动
对于运行中的进程: renice # PID 调整指定PID的nice值
ps axo ni command pid 查看进程的nice值

进程间通信(IPC): 信号:
kill命令:可以实现向其他进程发送信息 kill -l 或 man 7 signal 可以查看可以向进程发送的所有信息 kill -SIGNAL PID 杀死指定进程(SINGAL可以使数字代号也可以是信号名称) 1) SIGHUP 让程序重读配置文件,而不用重启程序 2) SIGINT 中断信号。Ctrl+c即发送此信号 9) SIGKILL 杀死进程 15) SIGTERM 终止进程,比较优雅(默认) killall -SIGNAL 进程名 杀死指定程序的所有进程

Linux的作业控制 前台作业:占据着一个终端 后台作业:作业执行时不占据终端,作业启动后就释放终端
非守护进程类的程序,启动以后都在前台工作 如果已经启动:前台–>后台。ctrl+z把前台作业送往后台,作业被”停止“ 如果尚未启动:COMMAND &
退出当前会话,作业也会终止,因为作业与当前终端相关,如果把作业送往后台后,不期望作业随终止结束而停止 nohup COMMAND & 如何让送往后台的作业继续执行: fg [[%]作业号码]:将作业调回前台继续进行 bg [[%]作业号码]:让作业在后台继续进行 默认的为最后一个进入后台的任务 kill %作业号码:终止作业 查看作业号: jobs
pmap pid 查看进程的内存占用情况
00007fb60640d000 4K rw— /sbin/init起始地址 空间 权限

bash脚本编程:之case语句
case语句的语法格式:case expression inpattern1) suite1 ;;pattern2) suite2 ;;…patternn) suiten ;;*) other_suite ;;esac

case中各pattern可以使用模式: a|b a或者b * 匹配任意长度的任意字符; ? 匹配任意单个字符; [-] 范围匹配

练习:写一个脚本,接受如此格式 script.sh {start|stop|restart|status}1、如是start,那么创建/var/lock/subsys/script.sh,显示启动成功;2、如果参数是stop,则删除/var/lock/subsys/script.sh,显示停止成功3、如果restart,则删除,再创建,显示成功;4、如果status, 如果文件存在,则显示running,否则,显示stopped
#!/bin/bash#myService=`basename $0`lockFile=”/var/lock/subsys/$myService”
[ $# -lt 1 ] && echo “Usage: $myService {start|stop|restart|status}” && exit 4
case $1 in’start’) touch $lockFile echo “Starting $myService OK” ;;’stop’) rm -f $lockFile echo “Stopping $myService OK” ;;’restart’) rm -f $lockFile touch $lockFile echo “Restarting $myService OK” ;;’status’) if [ -f $lockFile ]; then echo “$myService is running” else echo “免费云主机域名$myService is stopped” fi ;;*) echo “Usage: $myService {start|stop|restart|status}” exit 3 ;;esac

练习:写一个脚本,能对/etc/目录进行打包备份,备份位置为/backup/etc-日期.后缀1、显示如下菜单给用户:xz) xz compressgzip) gzip compressbip2) bzip2 compress2、根据用户指定的压缩工具使用tar打包压缩;3、默认为xz;输入错误则需要用户重新输入;
#!/bin/bash#[ -d /backup ] || mkdir /backup
cat
Plz choose a compress tool:
xz) xz compressgzip) gzip compressbip2) bzip2 compressEOF
while true; do read -p “Your option: ” option option=${option:-xz}
case $option in xz) compressTool=’J’ suffix=’xz’ break ;; gzip) compressTool=’z’ suffix=’gz’ break ;; bzip2) compressTool=’j’ suffix=’bz2′ break ;; *) echo “wrong option.” ;; esacdone
tar ${compressTool}cf /backup/etc-`date +%F-%H-%M-%S`.tar.$suffix /etc/*
练习:写一个脚本,完成如下功能说明:此脚本能够为指定网卡创建别名,指定地址;使用格式:mkethalias.sh -v|–verbose -i|–interface ethX1、-i选项用于指定网卡;2、如果网卡存在:在命令行,请用户指定一个别名;3、让用户指定IP和掩码;4、用户可以同时使用-v或–verbose选项:如果使用了,则在配置完成后,显示配置结果;否则,则不予显示;
#!/bin/bash#debug=0
while [ $# -ge 1 ]; do case $1 in -i|–interface) ethcard=”$2″ shift 2 ;; -v|–verbose) debug=1 shift ;; *) echo “Wrong options or arguments.” echo “Usage: `basename $0` [-v|–verbose] -i|–interface Interface” shift $# ;; esacdone
# echo “Interface: $ethcard , Verbose Flag: $debug “
! ifconfig $ethcard &> /dev/null && echo “No this interface…” && exit 3
read -p “Enter an alias: ” ethAlias
read -p “Enter IP: ” ipAddr
read -p “Mask: ” netMask
ifconfig $ethAlias $ipAddr netmask $netMask
[ $debug -eq 1 ] && ifconfig $ethAlias

bash脚本编程之函数
可被调用:函数有函数名 函数出现的地方,会自动被替换成函数定义的代码
函数定义

语法: FuncName() { 函数体 }
function FuncName { 函数体 }

函数有两种返回值: 正常返回的数据: 函数中的打印语句,如echo或print 函数中命令的执行结果 执行状态返回值: 取决于函数中执行的最后一条语句 自定义:return N
函数可以接受参数: 在函数体可以使用类似脚本调用位置参数一样的参数 $1, $2, … $# $*, $@

练习:写一个脚本,完成如下功能1、显示如下菜单disk) show disk infomem) show memory infocpu) show cpuinfo2、显示用户选定的内容;
#!/bin/bash#ShowMenu() {cat
disk) show disk infomem) show memory infocpu) show cpuinfoEOF}
main() { ShowMenu read -p “Plz choose an option: ” option case $option in disk) df -h ;; mem) free -m ;; cpu) cat /proc/cpuinfo ;; *) echo “Wrong option” esac}
main
如果在函数中使用变量:变量作用域 在函数中使用了在主程序中声明的变量,重新赋值会直接修改主程序中的变量; 如果不期望函数与主程序中的变量冲突,函数中使用变量都用local修饰;即使用局部变量; 在函数中使用了在主程序中没有声明的变量,在函数执行结束后即被撤消,无论是否使用local修饰符;

如果想把脚本的全部位置参数,统统传递给脚本中某函数使用,怎么办? 使用$*传递

练习:写一个脚本,判定172.16.0.0网络内有哪些主机在线,在线的用绿色显示,不在线的用红色显示;要求,编程中使用函数;
#!/bin/bash
Ping(){ ipAddr=172.16.$1.$2 ping -c 1 -w 1 $ipAddr >> /dev/null if [ $? -eq 0 ];then echo -e “33[32m$ipAddr33[0m” else echo -e “33[31m$ipAddr33[0m” fi}

for i in `seq 0 255`;do for j in `seq 1 254`;do Ping $i $j donedone

练习:写一个脚本,完成如下功能(使用函数):1、提示用户输入一个可执行命令;2、获取这个命令所依赖的所有库文件(使用ldd命令);3、复制命令至/mnt/sysroot/对应的目录中 解释:假设,如果复制的是cat命令,其可执行程序的路径是/bin/cat,那么就要将/bin/cat复制到/mnt/sysroot/bin/目录中,如果复制的是useradd命令,而useradd的可执行文件路径为/usr/sbin/useradd,那么就要将其复制到/mnt/sysroot/usr/sbin/目录中;4、复制各库文件至/mnt/sysroot/对应的目录中,其要求命令;
#!/bin/bash#target=/mnt/sysroot
clearCmd() { if which $cmd &> /dev/null; then cmdPath=`which –skip-alias $cmd` else echo “No such command” return 5 fi}
cmdCopy() { cmdDir=`dirname $1` [ -d ${target}${cmdDir} ] || mkdir -p ${target}${cmdDir} [ -f ${target}${1} ] || cp $1 ${target}${cmdDir}}
libCopy() { for lib in `ldd $1 | grep -o “/[^[:space:]]{1,}”`; do libDir=`dirname $lib` [ -d ${target}${libDir} ] || mkdir -p ${target}${libDir} [ -f ${target}${lib} ] || cp $lib ${target}${libDir} done}
while true; do read -p “Enter a command: ” cmd if [ “$cmd” == ‘quit’ ] ;then echo “quit” exit 0 fi clearCmd $cmd [ $? -eq 5 ] && continue
cmdCopy $cmdPath libCopy $cmdPathdone

相关推荐: linux如何查看是否安装rsync

本篇内容主要讲解“linux如何查看是否安装rsync”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“linux如何查看是否安装rsync”吧! 查看方法:1、利用“rpm -qa”查看,该命令可以查找某软件包是否安…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 01/26 22:52
下一篇 01/26 22:52