概述
CentOS7 部署 cobbler
简介
Cobbler是一个Linux服务器安装的服务,可以通过网络启动(PXE)的方式来快速安装、重装物理服务器和虚拟机,同时还可以管理
DHCP,
DNS`等。
Cobbler
可以使用命令行方式管理,也提供了基于Web的界面管理工具(cobbler-web),还提供了API接口,可以方便二次开发使用。
Cobbler
是较早前的kickstart的升级版,优点是比较容易配置,还自带web界面比较易于管理。
Cobbler
内置了一个轻量级配置管理系统,但它也支持和其它配置管理系统集成,如Puppet,暂时不支持SaltStack。
Cobbler
官网
cobbler集成的服务
- PXE服务支持
- DHCP服务管理
- DNS服务管理(可选bind,dnsmasq)
- 电源管理
- Kickstart服务支持
- YUM仓库管理
- TFTP(PXE启动时需要)
- Apache(提供kickstart的安装源,并提供定制化的kickstart配置)
cobbler配置文件详解
cobbler
配置文件目录在/etc/cobbler
配置文件 | 作用 |
---|---|
/etc/cobbler/settings | cobbler 主配置文件 |
/etc/cobbler/iso/ | iso模板配置文件 |
/etc/cobbler/pxe | pxe模板配置文件 |
/etc/cobbler/power | 电源配置文件 |
/etc/cobbler/user.conf | web服务授权配置文件 |
/etc/cobbler/users.digest | web访问的用户名密码配置文件 |
/etc/cobbler/dhcp.template | dhcp服务器的的配置模板 |
/etc/cobbler/dnsmasq.template | dns服务器的配置模板 |
/etc/cobbler/tftpd.template | tftp服务的配置模板 |
/etc/cobbler/modules.conf | 模块的配置文件 |
cobbler数据目录
目录 | 作用 |
---|---|
/var/lib/cobbler/config/ | 用于存放distros,system,profiles等信息配置文件 |
/var/lib/cobbler/triggers/ | 用于存放用户定义的cobbler命令 |
/var/lib/cobbler/kickstart/ | 默认存放kickstart文件 |
/var/lib/cobbler/loaders/ | 存放各种引导程序以及镜像目录 |
/var/www/cobbler/ks_mirror/ | 导入的发行版系统的所有数据 |
/var/www/cobbler/images/ | 导入发行版的kernel和initrd镜像用于远程网络启动 |
/var/www/cobbler/repo_mirror/ | yum仓库存储目录 |
cobbler日志文件
日志文件路径 | 说明 |
---|---|
/var/log/cobbler/installing | 客户端安装日志 |
/var/log/cobbler/cobbler.log | cobbler日志 |
//关闭防火墙并将selinux状态设为disabled
[root@localhost ~]# systemctl disable --now firewalld
Removed /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@localhost ~]# sed -ri 's/^(SELINUX=).*/1disabled/' /etc/selinux/config
[root@localhost ~]# reboot
[root@localhost ~]# getenforce
Disabled
//下载依托源
[root@localhost ~]# yum -y install epel-release
//下载软件和依赖包
[root@localhost ~]# yum -y install httpd dhcp tftp python-ctypes cobbler xinetd cobbler-web pykickstart fence-agents net-tools
/启动httpd cobbler 并设置开机自启
[root@localhost ~]# systemctl enable --now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
[root@localhost ~]# systemctl enable --now cobblerd
Created symlink /etc/systemd/system/multi-user.target.wants/cobblerd.service → /usr/lib/systemd/system/cobblerd.service.
//查看状态是否正常
[root@localhost ~]# systemctl status cobblerd
● cobblerd.service - Cobbler Helper Daemon
Loaded: loaded (/usr/lib/systemd/system/cobblerd.service; enabled; vendor preset: disabl>
Active: active (running) since Wed 2021-10-13 08:46:07 EDT; 6min ago
Main PID: 933 (cobblerd)
Tasks: 1 (limit: 23485)
Memory: 41.8M
CGroup: /system.slice/cobblerd.service
└─933 /usr/bin/python3.6 -s /usr/bin/cobblerd -F
Oct 13 08:46:07 localhost.localdomain systemd[1]: Starting Cobbler Helper Daemon...
Oct 13 08:46:07 localhost.localdomain systemd[1]: Started Cobbler Helper Daemon.
[root@localhost ~]# systemctl status httpd
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2021-10-13 08:46:08 EDT; 6min ago
Docs: man:httpd.service(8)
Main PID: 943 (httpd)
Status: "Running, listening on: port 443, port 80"
Tasks: 231 (limit: 23485)
Memory: 68.4M
CGroup: /system.slice/httpd.service
├─ 943 /usr/sbin/httpd -DFOREGROUND
├─1005 /usr/sbin/httpd -DFOREGROUND
├─1006 (wsgi:cobbler_w -DFOREGROUND
├─1007 /usr/sbin/httpd -DFOREGROUND
├─1008 /usr/sbin/httpd -DFOREGROUND
└─1009 /usr/sbin/httpd -DFOREGROUND
[root@localhost ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 5 127.0.0.1:25151 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 :::80 :::*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
LISTEN 0 128 :::443
生成加密密码
[root@localhost cobbler]# openssl passwd -1
Password:
Verifying - Password:
$1$PnOUVvMh$oP8uNllTP18xT.83kO9uD.
修改配置文件
[root@localhost cobbler]# ls
auth.conf import_rsync_whitelist pxe users.conf
cheetah_macros iso reporting users.digest
cobbler_bash ldap rsync.exclude version
completions modules.conf rsync.template zone.template
dhcp.template mongodb.conf secondary.template zone_templates
dnsmasq.template named.template settings
genders.template power tftpd.template
[root@localhost cobbler]# vim settings
100 # and put the output between the "" below.
101 default_password_crypted: "$1$PnOUVvMh$oP8uNllTP18xT.83kO9uD." (修改成生成的密码,cobbler认证用的)
102
......
389 # of the manpage for how that works.
390 server: 192.168.220.22 (本机IP)
391
277 # if you do not set this correctly, this will be manifested in TFTP open timeouts.
278 next_server: 192.168.220.22 (本机IP)
279
......
设置rsyncd开机自启并启动
[root@localhost cobbler]# systemctl enable --now rsyncd
[root@localhost cobbler]# systemctl status rsyncd
● rsyncd.service - fast remote file copy program daemon
Loaded: loaded (/usr/lib/systemd/system/rsyncd.service; enabled; vendor preset: disabled)
Active: active (running) since 三 2021-10-13 09:02:59 EDT; 3s ago
Main PID: 108769 (rsync)
CGroup: /system.slice/rsyncd.service
└─108769 /usr/bin/rsync --daemon --no-detach
10月 13 09:02:59 localhost.localdomain systemd[1]: Started fast remote file copy progra....
10月 13 09:02:59 localhost.localdomain systemd[1]: Starting fast remote file copy progr....
10月 13 09:02:59 localhost.localdomain rsyncd[108769]: rsyncd version 3.1.2 starting, l...3
Hint: Some lines were ellipsized, use -l to show in full.
重启cobblerd(因为修改了配置文件)
[root@localhost cobbler]# systemctl restart cobblerd
修改tftp配置文件
[root@localhost ~]# cd /etc/xinetd.d
[root@localhost xinetd.d]# ls
chargen-dgram daytime-dgram discard-dgram echo-dgram tcpmux-server time-dgram
chargen-stream daytime-stream discard-stream echo-stream tftp time-stream
[root@localhost xinetd.d]# vim tftp
12 server = /usr/sbin/in.tftpd
13 server_args = -s /var/lib/tftpboot
14 disable = no (把yes改为no)
15 per_source = 11
因为Centos7使用 cobbler get-loaders 获取网络包失败,但是CentOS8可以成功,所以在8上把需要的文件获取到然后传到7里面来
//Centos8里面使用命令获取到的内容
[root@localhost loaders]# ls
COPYING.syslinux README grub-x86_64.efi pxelinux.0
COPYING.yaboot grub-x86.efi menu.c32 yaboot
//在7上面将8获取到的内容传到7来
[root@localhost loaders]# cd /var/lib/cobbler/
[root@localhost cobbler]# rm -rf loaders/*
[root@localhost ~]# cd /var/lib/cobbler/loaders/
[root@localhost loaders]# scp 192.168.220.17(8的IP):/var/lib/cobbler/loaders/* .
[root@localhost cobbler]# scp 192.168.220.17:/var/lib/cobbler/loaders/* loaders/
root@192.168.220.17's password:
COPYING.syslinux 100% 9339 8.6MB/s 00:00
COPYING.yaboot 100% 9339 13.7MB/s 00:00
grub-x86_64.efi 100% 9339 14.9MB/s 00:00
grub-x86.efi 100% 9339 16.0MB/s 00:00
menu.c32 100% 9339 17.8MB/s 00:00
pxelinux.0 100% 9339 17.0MB/s 00:00
README 100% 9339 17.1MB/s 00:00
yaboot 100% 9339 15.2MB/s 00:00
检查错误
[root@localhost cobbler]# cobbler check
The following are potential configuration items that you may want to fix:
1 : Some network boot-loaders are missing from /var/lib/cobbler/loaders, you may run 'cobbler get-loaders' to download them, or, if you only want to handle x86/x86_64 netbooting, you may ensure that you have installed a *recent* version of the syslinux package installed and can ignore this message entirely. Files in this directory, should you want to support all architectures, should include pxelinux.0, menu.c32, elilo.efi, and yaboot. The 'cobbler get-loaders' command is the easiest way to resolve these requirements.
2 : debmirror package is not installed, it will be required to manage debian deployments and repositories
Restart cobblerd and then run 'cobbler sync' to apply changes.
# 错误1 先忽略,因为需要的文件已经放入目录/var/lib/cobbler/loaders/,错误2直接忽略,Ubuntu系统需要解决
重启cobblerd并进行同步
[root@localhost cobbler]# systemctl restart cobblerd
[root@localhost cobbler]# cobbler sync
task started: 2021-10-13_093026_sync
task started (id=Sync, time=Wed Oct 13 09:30:26 2021)
running pre-sync triggers
cleaning trees
......
running python trigger cobbler.modules.manage_genders
running python trigger cobbler.modules.scm_track
running shell triggers from /var/lib/cobbler/triggers/change/*
*** TASK COMPLETE ***(任务完成)
修改dhcp文件
[root@localhost ~]# cd /etc/cobbler/
[root@localhost cobbler]# ls
auth.conf import_rsync_whitelist pxe users.conf
cheetah_macros iso reporting users.digest
cobbler_bash ldap rsync.exclude version
completions modules.conf rsync.template zone.template
dhcp.template mongodb.conf secondary.template zone_templates
dnsmasq.template named.template settings
genders.template power tftpd.template
[root@localhost cobbler]# vim settings
......
241 # the choice of DHCP management engine is in /etc/cobbler/modules.conf
242 manage_dhcp: 1 (将0改为1,保存退出)
243
......
[root@localhost cobbler]# vim dhcp.template
20
21 subnet 192.168.220.0(修改当前IP网段,本机IP是192.168.220.22,网段就是192.168.220.0) netmask 255.255.255.0 {
22 option routers 192.168.220.22(将本机IP设置为路由);
23 option domain-name-servers 192.168.220.2(网关);
24 option subnet-mask 255.255.255.0;
25 range dynamic-bootp 192.168.220.100 192.168.220.254;(地址范围,可以分配多少IP)
26 default-lease-time 21600;
再重启cobblerd,并同步(因为修改了配置文件)
[root@localhost cobbler]# systemctl restart cobblerd
[root@localhost cobbler]# cobbler sync
task started: 2021-10-13_093905_sync
task started (id=Sync, time=Wed Oct 13 09:39:05 2021)
running pre-sync triggers
cleaning trees
......
running python trigger cobbler.modules.scm_track
running shell triggers from /var/lib/cobbler/triggers/change/*
*** TASK COMPLETE ***
检查dhcp是否正常
[root@localhost cobbler]# netstat -anulp|grep dhcp
udp 0 0 0.0.0.0:67 0.0.0.0:* 56297/dhcpd
本地已经有了ISO镜像,但是必须是dvd1.iso结尾的
开始挂载
[root@localhost cobbler]# df -h
文件系统 容量 已用 可用 已用% 挂载点
/dev/mapper/centos-root 36G 1.7G 35G 5% /
devtmpfs 1.4G 0 1.4G 0% /dev
tmpfs 1.4G 0 1.4G 0% /dev/shm
tmpfs 1.4G 9.5M 1.4G 1% /run
tmpfs 1.4G 0 1.4G 0% /sys/fs/cgroup
/dev/sda1 1014M 142M 873M 14% /boot
tmpfs 283M 0 283M 0% /run/user/0
//挂载
[root@localhost cobbler]# mount /dev/sr0 /mnt
mount: /dev/sr0 写保护,将以只读方式挂载
[root@localhost cobbler]# ls /mnt
CentOS_BuildTag GPL LiveOS RPM-GPG-KEY-CentOS-7
EFI images Packages RPM-GPG-KEY-CentOS-Testing-7
EULA isolinux repodata TRANS.TBL
运行导入镜像
[root@localhost ~]# cobbler import(导入) --name=centos-stream --arch=x86_64(平台) --path=/mnt
task started: 2021-10-13_094631_import
task started (id=Media import, time=Wed Oct 13 09:46:31 2021)
......
need to process repo/comps: /var/www/cobbler/ks_mirror/centos-stream-x86_64
looking for /var/www/cobbler/ks_mirror/centos-stream-x86_64/repodata/*comps*.xml
Keeping repodata as-is :/var/www/cobbler/ks_mirror/centos-stream-x86_64/repodata
*** TASK COMPLETE ***(任务完成)
[root@localhost cobbler]# pwd
/var/www/cobbler
[root@localhost cobbler]# ls ks_mirror/centos-stream-x86_64/
CentOS_BuildTag GPL LiveOS RPM-GPG-KEY-CentOS-7
EFI images Packages RPM-GPG-KEY-CentOS-Testing-7
EULA isolinux repodata TRANS.TBL
[root@localhost ~]# cobbler list
distros:(发行版)
centos-stream-x86_64
profiles:(配置文件)
centos-stream-x86_64
systems:
repos:
images:
mgmtclasses:
packages:
files:
//说明:
--path //挂载镜像路径
--name //为安装源定义一个名字
--arch //指定安装源平台
创建kickstarts自动安装脚本
[root@localhost ~]# ls
anaconda-ks.cfg # 此文件中记录着本机安装的过程,我们创建一个.ks文件来对照进行修改
[root@localhost cobbler]# cd /var/lib/cobbler/kickstarts
[root@localhost kickstarts]# ls
default.ks legacy.ks sample_esx4.ks sample.ks
esxi4-ks.cfg pxerescue.ks sample_esxi4.ks sample_old.seed
esxi5-ks.cfg sample_autoyast.xml sample_esxi5.ks sample.seed
install_profiles sample_end.ks sample_esxi6.ks sample.seed.28
[root@localhost kickstarts]# vi centos-7-x86_64.ks
auth --enableshadow --passalgo=sha512
bootloader --location=mbr
clearpart --all --initlabel
part /boot --asprimary --fstype="ext4" --size=500
part swap --fstype="swap" --size=4096
part / --fstype="ext4" --grow --size=15000
text
firewall --disabled
firstboot --disable
keyboard us
lang en_US
url --url=http://192.168.220.22(本机IP)/cobbler/ks_mirror/centos-stream-x86_64(yum源位置为)
$yum_repo_stanza
reboot
rootpw --iscrypted $6$.fasUGkm1e.2FZkl$LmrzUEcrryyoBeplqgqgKKSwN6rj0pxTRfDr8jG00sFW8FhUxHcizCoR5wHOjcIv.zVdBTMDbkejaC5C0gaIT0 (将这段改为anaconda-ks.cfg文件中的密码,就是装自己这台机器时自己设置的密码)
selinux --disabled
skipx
timezone Asia/Shanghai --isUtc --nontp
install
zerombr
%packages
@^minimal
@core
kexec-tools
%end
%addon com_redhat_kdump --enable --reserve-mb='auto'
%end
%anaconda
pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty
pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok
pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty
%end
检查ks文件语法是否有误
[root@localhost kickstarts]# cobbler validateks
task started: 2021-10-13_100544_validateks
task started (id=Kickstart Validation, time=Wed Oct 13 10:05:44 2021)
----------------------------
osversion: rhel7
checking url: http://192.168.220.22/cblr/svc/op/ks/profile/centos-stream-x86_64
running: /usr/bin/ksvalidator -v "rhel7" "http://192.168.220.22/cblr/svc/op/ks/profile/centos-stream-x86_64"
received on stdout:
received on stderr:
*** all kickstarts seem to be ok ***
*** TASK COMPLETE ***(任务成功)
查看
[root@localhost ~]# cobbler profile report centos_stream-x86_64
Name : centos-stream-x86_64
TFTP Boot Files : {}
Comment :
DHCP Tag : default
Distribution : centos-stream-x86_64
Enable gPXE? : 0
Enable PXE Menu? : 1
Fetchable Files : {}
Kernel Options : {}
Kernel Options (Post Install) : {}
Kickstart : /var/lib/cobbler/kickstarts/sample_end.ks(修改)
Kickstart Metadata : {}
Management Classes : []
Management Parameters : <<inherit>>
Name Servers : []
Name Servers Search Path : []
Owners : ['admin']
Parent Profile :
Internal proxy :
Red Hat Management Key : <<inherit>>
Red Hat Management Server : <<inherit>>
Repos : []
Server Override : <<inherit>>
Template Files : {}
Virt Auto Boot : 1
Virt Bridge : xenbr0
Virt CPUs : 1
Virt Disk Driver Type : raw
Virt File Size(GB) : 5
Virt Path :
Virt RAM (MB) : 512
Virt Type : kvm
//修改profile,将我们新建的ks文件设为默认的kickstarts安装文件
[root@localhost ~]# cobbler profile edit --name centos-stream-x86_64 --kickstart=/var/lib/cobbler/kickstarts/centos-7-x86_64.ks
//配置网卡名称为传统网卡名称eth0
[root@localhost ~]# cobbler profile edit --name centos-stream-x86_64 --kopts='net.ifnames=0 biosdevname=0'
//查看
[root@localhost ~]# cobbler profile report
Name : centos-stream-x86_64
TFTP Boot Files : {}
Comment :
DHCP Tag : default
Distribution : centos-stream-x86_64
Enable gPXE? : 0
Enable PXE Menu? : 1
Fetchable Files : {}
Kernel Options : {'biosdevname': '0', 'net.ifnames': '0'} (成功)
Kernel Options (Post Install) : {}
Kickstart : /var/lib/cobbler/kickstarts/centos-7-x86_64.ks (成功)
Kickstart Metadata : {}
Management Classes : []
Management Parameters : <<inherit>>
Name Servers : []
Name Servers Search Path : []
Owners : ['admin']
Parent Profile :
Internal proxy :
Red Hat Management Key : <<inherit>>
Red Hat Management Server : <<inherit>>
Repos : []
Server Override : <<inherit>>
Template Files : {}
Virt Auto Boot : 1
Virt Bridge : xenbr0
Virt CPUs : 1
Virt Disk Driver Type : raw
Virt File Size(GB) : 5
Virt Path :
Virt RAM (MB) : 512
Virt Type : kvm
同步
[root@localhost ~]# cobbler sync
task started: 2021-10-13_102946_sync
task started (id=Sync, time=Wed Oct 13 10:29:46 2021)
running pre-sync triggers
cleaning trees
......
running python triggers from /var/lib/cobbler/triggers/change/*
running python trigger cobbler.modules.manage_genders
running python trigger cobbler.modules.scm_track
running shell triggers from /var/lib/cobbler/triggers/change/*
*** TASK COMPLETE ***
重启服务
[root@localhost ~]# systemctl restart cobblerd httpd
启动xinetd服务,因为tftp是它管的
[root@localhost ~]# systemctl enable --now xinetd
[root@localhost ~]# systemctl status xinetd
● xinetd.service - Xinetd A Powerful Replacement For Inetd
Loaded: loaded (/usr/lib/systemd/system/xinetd.service; enabled; vendor preset: enabled)
Active: active (running) since 三 2021-10-13 10:31:59 EDT; 20s ago
Process: 48527 ExecStart=/usr/sbin/xinetd -stayalive -pidfile /var/run/xinetd.pid $EXTRAOPTIONS (code=exited, status=0/SUCCESS)
Main PID: 48528 (xinetd)
CGroup: /system.slice/xinetd.service
└─48528 /usr/sbin/xinetd -stayalive -pidfile /var/run/xinetd.pid
..........
文件替换
[root@localhost ~]# cd /var/lib/cobbler/loaders/
[root@localhost loaders]# ls
COPYING.syslinux grub-x86_64.efi menu.c32 README
COPYING.yaboot grub-x86.efi pxelinux.0 yaboot
[root@localhost loaders]# find / -name menu.c32
/var/lib/tftpboot/menu.c32
/var/lib/cobbler/loaders/menu.c32
/usr/share/syslinux/menu.c32
[root@localhost loaders]# ll /usr/share/syslinux/menu.c32 menu.c32
-rw-r--r-- 2 root root 9339 10月 13 09:26 menu.c32
-rw-r--r-- 1 root root 55140 10月 30 2018 /usr/share/syslinux/menu.c32
[root@localhost loaders]# cp /usr/share/syslinux/menu.c32 .
[root@localhost loaders]# ls
COPYING.syslinux grub-x86_64.efi menu.c32 README
COPYING.yaboot grub-x86.efi pxelinux.0 yaboot
[root@localhost loaders]# ll menu.c32 /usr/share/syslinux/menu.c32
-rw-r--r-- 2 root root 55140 10月 13 10:39 menu.c32
-rw-r--r-- 1 root root 55140 10月 30 2018 /usr/share/syslinux/menu.c32
[root@localhost loaders]# find / -name pxelinux.0
/var/lib/tftpboot/pxelinux.0
/var/lib/cobbler/loaders/pxelinux.0
/usr/share/syslinux/pxelinux.0
[root@localhost loaders]# ll /usr/share/syslinux/pxelinux.0 pxelinux.0
-rw-r--r-- 2 root root 9339 10月 13 09:26 pxelinux.0
-rw-r--r-- 1 root root 26759 10月 30 2018 /usr/share/syslinux/pxelinux.0
[root@localhost loaders]# cp /usr/share/syslinux/pxelinux.0 .
[root@localhost loaders]# ll /usr/share/syslinux/pxelinux.0 pxelinux.0
-rw-r--r-- 2 root root 26759 10月 13 10:42 pxelinux.0
-rw-r--r-- 1 root root 26759 10月 30 2018 /usr/share/syslinux/pxelinux.0
新建虚拟机测试(内存设为2G),选择第二个开始安装
定制安装步骤:
- 统计服务器mac地址
- 配置cobbler
- 安装
浏览器地址栏输入https:// IP /cobbler_web 默认登录用户和密码都是 cobbler
同步一下,重启服务
[root@localhost ~]# cobbler sync
task started: 2021-10-13_113654_sync
task started (id=Sync, time=Wed Oct 13 11:36:54 2021)
running pre-sync triggers
cleaning trees
......
running python trigger cobbler.modules.scm_track
running shell triggers from /var/lib/cobbler/triggers/change/*
*** TASK COMPLETE ***
[root@localhost ~]# systemctl restart httpd
[root@localhost ~]# systemctl restart xinetd
[root@localhost ~]# systemctl restart cobblerd
[root@localhost systems.d]# ls
node1.json
[root@localhost systems.d]# pwd
/var/lib/cobbler/config/systems.d
最后开机我们新建的手动生成的MAC地址的虚拟机自动会安装系统
最后
以上就是着急雨为你收集整理的CentOS7 部署cobbler的全部内容,希望文章能够帮你解决CentOS7 部署cobbler所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复