关闭一些无用的进程

闲来无事pstree -a看了一下貌似好几个无用的进程。这几天也是装了很多软件,装一个玩一下又卸掉的节奏。小记录一下。

sendmail,卸载。
exim4,卸载。
rpc也很可疑,跟NFS相关的平时也不用,service stop停掉。
然后就是nfs-common也一样。
除了停掉还要禁止开机启动,用`sysv-rc-conf`关掉。
安装了iftop,一个流量的实时监控工具。
安装了mutt msmtp,发邮件用的。

Mac软件之iTerm2

本来,在Mac下我一直是在用的原生的terminal,倒也是没什么感觉凑合用了几年。不知是最近住处的网络还是国内的网络不稳定,老是断连,搞得各种郁闷。于是乎又是改配置啦sshd_config配置握手时间,用screen命令保存状态什么的,然后就用上了iTerms了。也是用了一两个星期了,看到文章才发现原来有这么多好的功能。

最主要的还是口水它的屏幕切割功能,配合linux的screen命令+alias之后简直神器再临人间。


shell入门

这篇文章主要是网上搜集整理的资料,在shell的在平时使用中需要的最基本的入门知识,没有涉及grep、sed、awk以及各种正则表达式。

hello world

#!/bin/bash 
echo Hello World

脚本写完之后在shell中运行

$ chmod u+x hello
$ ./hello

就可以看到结果了。

输入输出

在 Linux 系统中:标准输入(stdin)默认为键盘输入;标准输出(stdout)默认为屏幕输出;标准错误输出(stderr)默认也是输出到屏幕(上面的 std 表示 standard)。

在 BASH 中使用这些概念时一般将标准输出表示为 1,将标准错误输出表示为 2。

$ ls > ls_result			# 写入
$ ls -l >> ls_result		# 追加写入
$ find /home -name lost* 2> err_result 	# 重定向错误输出到文件
$ find /home -name lost* > all_result 2>& 1	# 标准输出连同错误输出重定向到文件
$ find /home -name lost* 2> /dev/null	# 不显示错误信息

变量

  • 变量赋值时,’=’左右两边都不能有空格;
  • BASH 中的语句结尾不需要分号(”;”);
  • 除了在变量赋值和在FOR循环语句头中,BASH 中的变量使用必须在变量前加”$”符号,可一个使用更为标准的变量引用方式${STR}

BASH 中的变量既不需要定义,也就没有类型一说,一个变量即可以被定义为一个字符串,也可以被再定义为整数。如果对该变量进行整数运算,他就被解释为整数;如果对他进行字符串操作,他就被看作为一个字符串。

整数运算一般通过 let 和 expr 这两个指令来实现,如对变量 x 加 1 可以写作:let "x = $x + 1" 或者 x=expr $x + 1

比较操作符

整数变量和字符串变量

对应的操作 整数操作 字符串操作
相同 -eq =
不同 -ne !=
大于 -gt >
小于 -lt <
大于或等于 -ge  
小于或等于 -le  
为空 -z  
不为空 -n  

比较字符串 a 和 b 是否相等就写作:if [ $a = $b ]
判断字符串 a 是否为空就写作: if [ -z $a ]
判断整数变量 a 是否大于 b 就写作:if [ $a -gt $b ]
更细致的文档推荐在字符串比较时尽量不要使用 -n ,而用 ! -z 来代替。

判断文件属性

运算符 含义( 满足下面要求时返回 TRUE )
-e file 文件 file 已经存在
-f file 文件 file 是普通文件
-s file 文件 file 大小不为零
-d file 文件 file 是一个目录
-r file 文件 file 对当前用户可以读取
-w file 文件 file 对当前用户可以写入
-x file 文件 file 对当前用户可以执行
-g file 文件 file 的 GID 标志被设置
-u file 文件 file 的 UID 标志被设置
-O file 文件 file 是属于当前用户的
-G file 文件 file 的组 ID 和当前用户相同
file1 -nt file2 文件 file1 比 file2 更新
file1 -ot file2 文件 file1 比 file2 更老

if [ -x /root ] 可以用于判断 /root 目录是否可以被当前用户进入。

基本流程控制

if…then…else

if 条件语句 [ ] 左右两个都要有一个空格。

if [ $1 -gt 90 ] 
then 
    echo "Good, $1" 
elif [ $1 -gt 70 ] && [ $1 -lt 90]
then 
    echo "OK, $1" 
else 
    echo "Bad, $1" 
fi

当shell提醒integer expression expected时,可使用字符串比较,使得程序得以正确地运行通过。例如
if [ $cpuLoad > '50' ] || [ $memUsed > '800' ] || [ $ioSumRate > '25' ];

for

for day in Sun Mon Tue Wed Thu Fri Sat 
do 
	echo $day 
done 

while

while & until

while [ condition ]
do
	statments
done

until [ condition is TRUE ]
do
	statments
done

case

echo "Hit a key, then hit return." 
read Keypress 

case "$Keypress" in 
[a-z] ) echo "Lowercase letter";; 
[A-Z] ) echo "Uppercase letter";; 
[0-9] ) echo "Digit";; 
* ) echo "Punctuation, whitespace, or other";; 
esac 

函数

square() { 
	let "res = $1 * $1" 
	return $res 
} 

特殊保留字

保留变量

$IFS  这个变量中保存了用于分割输入参数的分割字符,默认识空格。 
$HOME  这个变量中存储了当前用户的根目录路径。 
$PATH  这个变量中存储了当前 Shell 的默认路径字符串。 
$PS1  表示第一个系统提示符。 
$PS2  表示的二个系统提示符。 
$PWD  表示当前工作路径。 
$EDITOR 表示系统的默认编辑器名称。 
$BASH  表示当前 Shell 的路径字符串。
$0, $1, $2, ... 
表示系统传给脚本程序或脚本程序传给函数的第0个、第一个、第二个等参数。
$#   表示脚本程序的命令参数个数或函数的参数个数。
$$   表示该脚本程序的进程号,常用于生成文件名唯一的临时文件。 
$?   表示脚本程序或函数的返回状态值,正常为 0,否则为非零的错误号。
$*   表示所有的脚本参数或函数参数。
$@   和 $* 涵义相似,但是比 $* 更安全。
$!   表示最近一个在后台运行的进程的进程号。
$RANDOM 一个大小在 1 到 65536 之间的随机整数

符号

算术运算符 
	+ - * / % 表示加减乘除和取余运算
	+= -= *= /= 同 C 语言中的含义
位操作符
	<< <<= >> >>= 表示位左右移一位操作
	& &= | |= 表示按位与、位或操作
	~ ! 表示非操作
	^ ^= 表示异或操作
关系运算符 
	< > <= >= == != 表示大于、小于、大于等于、小于等于、等于、不等于操作
	&& || 逻辑与、逻辑或操作

变量的特殊操作

${var-default} 表示如果变量 $var 还没有设置,则保持 $var 没有设置的状态,并返回后面的默认值 default。
${var=default} 表示如果变量 $var 还没有设置,则取后面的默认值 default。 
${var+otherwise} 表示如果变量 $var 已经设置,则返回 otherwise 的值,否则返回空( null )。
${var?err_msg} 表示如果变量 $var 已经设置,则返回该变量的值,否则将后面的 err_msg 输出到标准错误输出上。

还有下面一些用法,这些用法主要用于从文件路径字符串中提取有用信息:

${var#pattern}, ${var##pattern} 用于从变量 $var 中剥去最短(最长)的和 pattern 相匹配的最左侧的串。
${var%pattern}, ${var%%pattern} 用于从变量 $var 中剥去最短(最长)的和 pattern 相匹配的最右侧的串。
${var:pos} 表示去掉变量 $var 中前 pos 个字符。
${var:pos:len} 表示变量 $var 中去掉前 pos 个字符后的剩余字符串的前 len 个字符。
${var/pattern/replacement} 表示将变量 $var 中第一个出现的 pattern 模式替换为 replacement 字符串。
${var//pattern/replacement} 表示将变量 $var 中出现的所有 pattern 模式全部都替换为 replacment 字符串。

程序界面

BASH 中提供了一个小的语句格式,可以让程序快速的设计出一个字符界面的用户交互选择的菜单,该功能就是由 select 语句来实现的。

OPTIONS="Hello Quit" 
select opt in $OPTIONS; do 
if [ "$opt" = "Quit" ]; then 
echo done 
exit 
elif [ "$opt" = "Hello" ]; then 
echo Hello World 
else 
clear 
echo bad option 
fi 
done 

BASH 中通过 read 函数来实现读取用户输入的功能

echo Please enter your name
read NAME 
echo "Hi! $NAME !"

也可以通过文本输入。要求在需要键盘输入的命令后,直接加上 « 符号,然后跟上一个自定义的字符串,在该串后按顺序输入本来应该由键盘输入的所有字符,在所有需要输入的字符都结束后,重复一遍自定义的字符串,表示该输入到此结束。

passwd="aka@tsinghua" 
ftp -n localhost <<(U •́ .̫ •̀ U)
user anonymous $passwd
(U •́ .̫ •̀ U)

一些特殊的惯用法

  • 在 BASH 中 () 一对括号一般被用于求取括号中表达式的值或命令的执行结果,如:(a=hello; echo $a) ,其作用相当于 ...

  • : 有两个含义,一是表示空语句,有点类似于 C 语言中的单个 “;” 。表示该行是一个空命令,如果被用在 while/until 的头结构中,则表示值 0,会使循环一直进行下去

      while : 
      do 
      operation
      done
    
  • : 还可以用于求取后面变量的值

      : ${HOSTNAME?} {USER?} {MAIL?} 
      echo $HOSTNAME 
      echo $USER 
      echo $MAIL 
    
  • 在 BASH 中 export 命令用于将系统变量输出到外层的 Shell 中。
  • bash -x bash-script 命令,可以查看一个出错的 BASH 脚本到底错在什么地方,可以帮助程序员找出脚本中的错误。
  • trap 语句可以在 BASH 脚本出错退出时打印出一些变量的值,以供程序员检查。trap 语句必须作为继 “#!/bin/bash” 后的第一句非注释代码,一般 trap 命令被写作: trap ‘message $checkvar1 $checkvar2’ EXIT 。

Linux命令之netstat命令和一些 TCP 知识

在Internet RFC标准中,Netstat的定义是: Netstat是在内核中访问网络及相关信息的程序,它能提供TCP连接,TCP和UDP监听,进程内存管理的相关报告。 Netstat是是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表、实际的网络连接以及每一个网络接口设备的状态信息。Netstat用于显示与IP、TCP、UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况。

格式

该命令的一般格式为 :
netstat [-a][-e][-n][-o][-p Protocol][-r][-s][Interval]
命令中各选项的含义如下:
  
-a 显示所有socket,包括正在监听的。
-c 每隔1秒就重新显示一遍,直到用户中断它。
-i 显示所有网络接口的信息,再加上-e,内容便和ifconfig一样。
-n 禁用反向域名解析,加快查询速度
-r 显示核心路由表,格式同“route -e”。
-t 显示TCP协议的连接情况
-u 显示UDP协议的连接情况。
-v 显示正在进行的工作。
-l 只列出监听中的连接.(LISTEN)
-p 选项查看进程信息
-g 会输出 IPv4 和 IPv6 的多播组信息。

常用选项

netstat -s
	——本选项能够按照各个协议分别显示其统计数据。如果你的应用程序(如Web浏览器)运行速度比较慢,或者不能显示Web页之类的数据,那么你就可以用本选项来查看一下所显示的信息。你需要仔细查看统计数据的各行,找到出错的关键字,进而确定问题所在。
netstat -e
	——本选项用于显示关于以太网的统计数据,它列出的项目包括传送数据报的总字节数、错误数、删除数,包括发送和接收量(如发送和接收的字节数、数据包数),或有广播的数量。可以用来统计一些基本的网络流量。
netstat -r
	——本选项可以显示关于路由表的信息,类似于后面所讲使用route print命令时看到的信息。除了显示有效路由外,还显示当前有效的连接。
netstat -a
	——本选项显示一个所有的有效连接信息列表,包括已建立的连接(ESTABLISHED),也包括监听连接请求(LISTENING)的那些连接。
netstat -n
	——显示所有已建立的有效连接。
netstat -nlpt
	——查看端口和连接的信息时,能查看到它们对应的进程名和进程号对系统管理员来说是非常有帮助的。举个栗子,Apache 的 httpd 服务开启80端口,如果你要查看 http 服务是否已经启动,或者 http 服务是由 apache 还是 nginx 启动的,这时候你可以看看进程名。
netstat -ltpe
	——使用 -ep 选项可以同时查看进程名和用户名。
netstat -ant
	——查看已建立的tcp端口情况。

一些其它TCP的知识

TCP连接

先上一下客户端与服务器进行TCP连接的过程。TCP连接的的过程有很多状态,不同的连接状态,都有想对应的状态码:

LISTEN:侦听来自远方的TCP端口的连接请求
SYN-SENT:再发送连接请求后等待匹配的连接请求
SYN-RECEIVED:再收到和发送一个连接请求后等待对方对连接请求的确认
ESTABLISHED:代表一个打开的连接
FIN-WAIT-1:等待远程TCP连接中断请求,或先前的连接中断请求的确认
FIN-WAIT-2:从远程TCP等待连接中断请求
CLOSE-WAIT:等待从本地用户发来的连接中断请求
CLOSING:等待远程TCP对连接中断的确认
LAST-ACK:等待原来的发向远程TCP的连接中断请求的确认
TIME-WAIT:等待足够的时间以确保远程TCP接收到连接中断请求的确认
CLOSED:没有任何连接状态

相对应的就是下图: vim

连接状态

在原模式中没有状态,在用户数据报协议中也经常没有状态,于是状态列可以空出来。若有状态,可以对应TCP的三次握手四次挥手过程,通常取值为:

LISTEN
	侦听来自远方的TCP端口的连接请求
SYN-SENT
	再发送连接请求后等待匹配的连接请求
SYN-RECEIVED
	再收到和发送一个连接请求后等待对方对连接请求的确认
ESTABLISHED
	代表一个打开的连接 
FIN-WAIT-1
	等待远程TCP连接中断请求,或先前的连接中断请求的确认
FIN-WAIT-2
	从远程TCP等待连接中断请求
CLOSE-WAIT
	等待从本地用户发来的连接中断请求
CLOSING
	等待远程TCP对连接中断的确认
LAST-ACK
	等待原来的发向远程TCP的连接中断请求的确认
TIME-WAIT
	等待足够的时间以确保远程TCP接收到连接中断请求的确认
CLOSED
	没有任何连接状态

基于三次握手的SYN洪水攻击(摘自百度百科)

建设一个小型的模仿环境假设有3台接入互联网的机器。A为攻击者操纵的攻击机。B为中介跳板机器(受信任的服务器)。C为受害者使用的机器(多是服务器),这里把C机器锁定为目标机器。A机器向B机器发送SYN包,请求建立连接,这时已经响应请求的B机器会向A机器回应SYN/ACK表明同意建立连接,当A机器接受到B机器发送的SYN/ACK回应时,发送应答ACK建立A机器与B机器的网络连接。这样一个两台机器之间的TCP通话信道就建立成功了。 B终端受信任的服务器向C机器发起TCP连接,A机器对服务器C发起SYN信息,使C机器不能响应B机器。在同时A机器也向B机器发送虚假的C机器回应的SYN数据包,接收到SYN数据包的B机器(被C机器信任)开始发送应答连接建立的SYN/ACK数据包,这时C机器正在忙于响应以前发送的SYN数据而无暇回应B机器,A机器的攻击者预测出B机器包的序列号(TCP序列号预测难度有些大)假冒C机器向B机器发送应答ACK这时攻击者骗取B机器的信任,假冒C机器与B机器建立起TCP协议的对话连接。这个时候的C机器还是在响应攻击者A机器发送的SYN数据。

TCP协议栈的弱点

TCP连接的资源消耗,其中包括:数据包信息、条件状态、序列号等。通过故意不完成建立连接所需要的三次握手过程,造成连接一方的资源耗尽。 通过攻击者有意的不完成建立连接所需要的三次握手的全过程,从而造成了C机器的资源耗尽。序列号的可预测性,目标主机应答连接请求时返回的SYN/ACK的序列号时可预测的。


debian登陆信息修改

一般我们ssh登陆debian会出现以下的信息。

Linux kelu.org 3.18.1-x86_64-linode50 #1 SMP Tue Jan 6 12:14:10 EST 2015 x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Thu Jan 15 23:16:37 2015 from xxx.xxx.xxx.xxx

修改和添加的方法很多。在此记录一下。

登陆前提示信息文件是 /etc/issue 和 /etc/issue.net. 登陆前的信息我们不管了,就来看登陆后的信息好了。

##start######## /etc/update-motd.d/10-uname #######################
Linux kelu.org 3.18.1-x86_64-linode50 #1 SMP Tue Jan 6 12:14:10 EST 2015 x86_64
##end###############################################

##start######## 以下是/etc/motd #######################
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
##end###############################################

##start######## 以下是/etc/ssh/sshd_config 的 PrintLastLog 配置######
###################### PrintLastLog ##################
Last login: Thu Jan 15 23:16:37 2015 from xxx.xxx.xxx.xxx
##end###############################################

motd的意思是message of the day——每日消息

接下来是

/etc/ssh/sshrc ssh登陆之后会加载里面的内容。

/etc/bash.bashrc 值得注意的是,screen时候也会加载这个文件。

在/etc中的配置文件,会对所有用户生效。如果只希望对当前用户做自定义的配置,就在用户目录下进行配置。

我最后改成了这样:

image-20230905152603077

/etc/update-motd.d/10-uname 文件:

echo "YUKI.N > SELECT シリアルコード \n         FROM データべース \n         WHERE コードデータ \n         ORDER BY 攻性情報戦闘 \n         HAVING ターミネートモ
ード"

/etc/motd文件:


YUKI.N > If you are reading this,
         then I'm probably no longer myself

YUKI.N > When this message apprears,
         it means that you, me, Suzumiya Haruhi, Asahina Mikuru and
         Koizumi Itsuki are all present.

YUKI.N > That's the key.

YUKI.N > This is ermegency escape program.
         To activate it, press enter.
         Otherwise press any other key.

         If you activate it,
         you will be a given time to repair space-time continuum.
         However there's no guarantee of your safe return.

YUKI.N > This program can be start only once.
         Once execute it will be erased.

         If you choose not to activate it, it will also be erased.
         READY?


备份你的Linux ——tar 打包和 rsync 同步

做好系统备份对系统管理员来说是件很重要的事情。可使用两种方法进行备份系统。一种是直接打tar包备份,另一种是使用增量备份工具,下面我来记录一下。

1. tar打包备份

tar打包备份很简单,就是一条tar命令。为了增强备份文件的可读性,我们将备份的时间设置为备份文件名。

#!/bin/bash

function bksys() {
    filename=`date --date="-24 hour" +%Y-%m-%d_%H-%M`;
    tar cvpzf /kelu/Backup/$filename.tar.gz --exclude=/proc --exclude=/tmp --exclude=/lost+found --exclude=/mnt --exclude=/sys --exclude=/kelu/Backup/ --exclude=/pub /;
}

bksys 2>&1 | tee -a /var/log/bksys.log

其中tar的-p的意思在man中的解释是: -p 恢复字段到它们的原始方式,忽略现有的用户权限屏蔽位(umask)。 setuid、setgid 和 tacky 位许可权也恢复给拥有 kelu 用户权限的用户。这个标志恢复文件到其原始方式,但不恢复目录到其原始方式。

意思也就是说打包时保持该文件夹的相关属性,使解压的时候得以恢复。

2. rsync备份

rsync 是一个快速增量文件传输工具,它可以用于在同一主机备份内部的备份,我们还可以把它作为不同主机网络备份工具之用。本文主要讲述的是如何自架rsync服务器,以实现文件传输、备份和镜像。相对tar和wget来说,rsync 也有其自身的优点,比如速度快、安全、高效。

安装

debian安装使用apt-get install rsync安装。有的是系统自带的,自带的话就自己建好文件夹/etc/rsyncd,在文件夹里添加几个文件rsyncd.motd rsyncd.password rsyncd.secrets。 这三个文件的内容分别是:

YUKI.N> cat rsyncd.motd
+++++++++++++++++++++++++++
+     kelu.org  2015      +
+++++++++++++++++++++++++++
YUKI.N> cat rsyncd.password
12345678
YUKI.N> cat rsyncd.secrets
kelu:12345678

secrets和password的权限必须设为600,不然备份时候也会提醒也会拒绝备份= = secrets是用户密码文件,password是为了方便自动化备份时的密码文件。交互式地备份的话会提醒你输入密码。

配置

配置rsyncd.conf

# Distributed under the terms of the GNU General Public License v2
# Minimal configuration file for rsync daemon
# See rsync(1) and rsyncd.conf(5) man pages for help

# This line is required by the /etc/init.d/rsyncd script
pid file = /var/run/rsyncd.pid
port = 873
# 你的IP地址!
address = 12.34.56.78 
#uid = nobody
#gid = nobody
uid = kelu
gid = kelu

use chkelu = yes
read only = yes

#limit access to private LANs 注意要把自己的IP添加进去!
hosts allow=192.168.1.0/255.255.255.0 10.0.1.0/255.255.255.0 
hosts deny=*

max connections = 5
# motd文件,欢迎语来着,在里面随便写点东西。当用户登录时会看到这个信息。
motd file = /etc/rsyncd/rsyncd.motd

#This will give you a separate log file
log file = /var/log/rsync.log

#This will log every file transferred - up to 85,000+ per user, per sync
transfer logging = yes

log format = %t %a %m %f %b
syslog facility = local3
timeout = 300

# 模块定义啦
[模块名称]
path = /
list=yes
ignore errors
auth users = kelu
secrets file = /etc/rsyncd/rsyncd.secrets
comment = YUKI.N>
exclude = proc/ tmp/ lost+found/ mnt/ sys/ kelu/Backup/ pub/

​ 做完这些,已经可以开始同步数据了。由于是本机备份,所以我没有看得很仔细,以后需要了再来看啦。

/usr/bin/rsync --daemon 				# 启动服务
rsync --list-only kelu@kelu.org:: 		# 备份信息
rsync -avzP kelu@kelu.org::kelu.org /kelu/Dropbox/kelu.org/
										# 备份

写一个脚本,方便自动化。要记得chmod +x哦

#!/bin/sh
# /usr/bin/rsync --daemon;
# 全量备份
# rsync -avzP --password-file=/etc/rsyncd/rsyncd.secrets kelu@kelu.org::kelu.org /kelu/Dropbox/kelu.org/$(date + '%m-%d-%y')
rsync -avzP --password-file=/etc/rsyncd/rsyncd.password kelu@kelu.org::kelu.org /kelu/Dropbox/kelu.org/											

3. 自动化

crontab -e

按照提示添加就好了。比如:

# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.

# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/

40 2 * * * rsync -avzP --password-file=/etc/rsyncd/rsyncd.password kelu@kelu.org::kelu.org /kelu/Dropbox/kelu.org/

或者你也可以按照系统的方法,新建一个自动化运行的文件夹,定时运行文件夹中的文件。

10 4 * * * /usr/bin/run-parts   /etc/cron.daily.kelu    1> /dev/null

在你的Debian上连接到Github

整个过程都是参考的github的官方文档。在这稍微做一个记录。

$ apt-get install git
$ git config --global user.name "YOUR NAME"
$ git config --global user.email "YOUR EMAIL ADDRESS"
$ ssh-keygen -t rsa -C "YOUR EMAIL ADDRESS"

将你的公钥添加到github上。

$ ssh-agent bash
$ ssh-agent -s
$ ssh-add ~/.ssh/id_rsa
$ ssh -T git@github.com

出现以下这行就说明连接上了。

Hi username! You've successfully authenticated, but GitHub does not # provide shell access.

把自己的项目下载到本地,就可以任意编辑了。

$ git clone git@github.com:YOUR NAME/PROJECT.github.com.git

安装完成。


1 2 3 4 5 156 157 158 159 160