一、Puppet master/agent模型
puppet通過在master端啟動puppetmaster服務來接受agent用戶端的請,在/etc/puppet/manifest/site.pp中通過用戶端的FQDN來定義每個agent所有應用的class,首次啟動puppet守護程序時,其會自動進行運作環境的初始化,建立一個本地CA及伺服器端相關的證書和密鑰等。初始化操作完成後,puppet就會監聽指定的套接字并等待用戶端的連接配接請求。預設情況下,其證書和密鑰等檔案位于/var/lib/puppet/ssl/目錄中。
MCollective簡介
MCollective是一個排程器,可以解決多個puppet agent同時向master提出請求造成性能,速度下降的問題,它可以根據不同的屬性對節點進行分類,對不同的分類執行不同的任務;它是一個控制終端,可以使用它控制用戶端和伺服器,是以不需要puppet agent定時運作了。
MCollective也是C/S架構,而且client和server使用Midware(中間件)進行通信
Puppet架構與叢集
Puppet通常部署為C/S架構,當agent過多時會面臨性能問題
常見的叢集方案:
puppet + nginx
puppet + passenger + apache
Puppet叢集的建構機制
puppetmaster叢集:
Active/Active模式高可用叢集,分攤puppetmaster上來自于agent的請求壓力
反向代理模式,将針對于8140端口請求分散到多台puppetmaster
下面是master/agent模型的原理圖:
<a href="http://s3.51cto.com/wyfs02/M02/24/06/wKiom1NLUozTRlYgAAG4a7z9xTg354.jpg" target="_blank"></a>
二、實驗環境
192.168.30.116 OS:CentOS 6.4 x86_64 node1.luojianlong.com
192.168.30.117 OS:CentOS 6.4 x86_64 node2.luojianlong.com
192.168.30.119 OS:CentOS 6.4 x86_64 node3.luojianlong.com
需要的軟體包:
puppet-2.7.23-1.el6.noarch.rpm
puppet-server-2.7.23-1.el6.noarch.rpm
facter-1.7.3-1.el6.x86_64.rpm
puppet-dashboard-1.2.23-1.el6.noarch.rpm
mysql-5.5.33-linux2.6-x86_64.tar.gz
<a href="http://s3.51cto.com/wyfs02/M01/24/06/wKioL1NLU_Pijiq8AADrfQoe5Ms157.jpg" target="_blank"></a>
首先在node1安裝master端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<code>#設定各節點的hosts檔案</code>
<code>[root@node1 ~]</code><code># cat /etc/hosts</code>
<code>192.168.30.116 node1.luojianlong.com</code>
<code>192.168.30.117 node2.luojianlong.com</code>
<code>192.168.30.119 node3.luojianlong.com</code>
<code># 更新facter</code>
<code>[root@node1 ~]</code><code># rpm -Uvh facter-1.7.3-1.el6.x86_64.rpm</code>
<code># 配置epel源</code>
<code>[root@node1 ~]</code><code># cat /etc/yum.repos.d/epel.repo</code>
<code>[epel]</code>
<code>name=epel</code>
<code>baseurl=http:</code><code>//mirrors</code><code>.sohu.com</code><code>/fedora-epel/6/</code><code>$basearch/</code>
<code>gpgcheck=1</code>
<code>gpgkey=http:</code><code>//mirrors</code><code>.sohu.com</code><code>/fedora-epel/RPM-GPG-KEY-EPEL-6</code>
<code># 安裝puppet,puppet-server</code>
<code>[root@node1 ~]</code><code># yum -y localinstall puppet-2.7.23-1.el6.noarch.rpm</code>
<code>[root@node1 ~]</code><code># yum -y localinstall puppet-server-2.7.23-1.el6.noarch.rpm</code>
在node2,node3安裝puppet-agent
<code>[root@node2 ~]</code><code># rpm -Uvh facter-1.7.3-1.el6.x86_64.rpm</code>
<code>[root@node2 ~]</code><code># yum -y localinstall puppet-2.7.23-1.el6.noarch.rpm</code>
<code>[root@node3 ~]</code><code># rpm -Uvh facter-1.7.3-1.el6.x86_64.rpm</code>
<code>[root@node3 ~]</code><code># yum -y localinstall puppet-2.7.23-1.el6.noarch.rpm</code>
在node1建立并配置子產品
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<code>[root@node1 ~]</code><code># mkdir -pv /etc/puppet/modules/nginx/{manifests,files,lib,templates,tests,spec}</code>
<code>mkdir</code><code>: created directory `</code><code>/etc/puppet/modules/nginx</code><code>'</code>
<code>mkdir</code><code>: created directory `</code><code>/etc/puppet/modules/nginx/manifests</code><code>'</code>
<code>mkdir</code><code>: created directory `</code><code>/etc/puppet/modules/nginx/files</code><code>'</code>
<code>mkdir</code><code>: created directory `</code><code>/etc/puppet/modules/nginx/lib</code><code>'</code>
<code>mkdir</code><code>: created directory `</code><code>/etc/puppet/modules/nginx/templates</code><code>'</code>
<code>mkdir</code><code>: created directory `</code><code>/etc/puppet/modules/nginx/tests</code><code>'</code>
<code>mkdir</code><code>: created directory `</code><code>/etc/puppet/modules/nginx/spec</code><code>'</code>
<code>[root@node1 ~]</code><code># puppet module list</code>
<code>/etc/puppet/modules</code>
<code>└── nginx (???)</code>
<code>/usr/share/puppet/modules</code> <code>(no modules installed)</code>
<code># 在nginx子產品中定義init.pp</code>
<code>[root@node1 ~]</code><code># vi /etc/puppet/modules/nginx/manifests/init.pp</code>
<code>class nginx {</code>
<code> </code><code>package {</code><code>'nginx'</code><code>:</code>
<code> </code><code>ensure => installed,</code>
<code> </code><code>}</code>
<code>}</code>
<code># 定義nginx_web.pp檔案</code>
<code>[root@node1 ~]</code><code># vi /etc/puppet/modules/nginx/manifests/nginx_web.pp</code>
<code>class nginx::nginx_web inherits nginx {</code>
<code> </code><code>file</code> <code>{</code><code>'/etc/nginx/nginx.conf'</code><code>:</code>
<code> </code><code>ensure => </code><code>file</code><code>,</code>
<code> </code><code>source</code> <code>=> </code><code>'puppet:///modules/nginx/nginx-web.conf'</code><code>,</code>
<code> </code><code>mode => </code><code>'0644'</code><code>,</code>
<code> </code><code>owner => </code><code>'root'</code><code>,</code>
<code> </code><code>group => </code><code>'root'</code><code>,</code>
<code> </code><code>notify => Service[</code><code>'nginx'</code><code>],</code>
<code> </code><code>require => Package[</code><code>'nginx'</code><code>],</code>
<code> </code><code>service {</code><code>'nginx'</code><code>:</code>
<code> </code><code>ensure => running,</code>
<code># 準備source檔案</code>
<code>[root@node1 ~]</code><code># cp /tmp/nginx.conf /etc/puppet/modules/nginx/files/nginx-web.conf</code>
<code># 建立site.pp檔案調用前面定義的class</code>
<code>[root@node1 ~]</code><code># vi /etc/puppet/manifests/site.pp</code>
<code>node </code><code>'node2.luojianlong'</code> <code>{</code>
<code> </code><code>include nginx::nginx_web</code>
<code>node </code><code>'node3.luojianlong'</code> <code>{</code>
首次啟動puppet服務程序可以以非守護程序方式進行,并讓其輸出詳解資訊以便于觀察初始化過程。如下所示過程,其逐漸展示了建立本地CA、作為puppet伺服器的本地主機向CA申請證書、獲得證書以及CA移出證書簽署請求的過程等,而後啟動服務程序并準備接受各agent的連接配接請求。為下面的指令額外使用--debug選項,還可以獲得更為詳細的輸出資訊。
<code>[root@node1 ~]</code><code># puppet master --verbose --no-daemonize</code>
<code>info: Creating a new SSL key </code><code>for</code> <code>ca</code>
<code>info: Creating a new SSL certificate request </code><code>for</code> <code>ca</code>
<code>info: Certificate Request fingerprint (md5): E0:74:ED:BA:83:EC:6E:A7:1A:1F:89:B1:CC:81:C3:CE</code>
<code>notice: Signed certificate request </code><code>for</code> <code>ca</code>
<code>notice: Rebuilding inventory </code><code>file</code>
<code>info: Creating a new certificate revocation list</code>
<code>info: Creating a new SSL key </code><code>for</code> <code>node1.luojianlong.com</code>
<code>info: Creating a new SSL certificate request </code><code>for</code> <code>node1.luojianlong.com</code>
<code>info: Certificate Request fingerprint (md5): 05:F1:37:DE:6E:13:CA:32:46:5B:07:2A:05:DE:D1:12</code>
<code>notice: node1.luojianlong.com has a waiting certificate request</code>
<code>notice: Signed certificate request </code><code>for</code> <code>node1.luojianlong.com</code>
<code>notice: Removing </code><code>file</code> <code>Puppet::SSL::CertificateRequest node1.luojianlong.com at </code><code>'/var/lib/puppet/ssl/ca/requests/node1.luojianlong.com.pem'</code>
<code>notice: Removing </code><code>file</code> <code>Puppet::SSL::CertificateRequest node1.luojianlong.com at </code><code>'/var/lib/puppet/ssl/certificate_requests/node1.luojianlong.com.pem'</code>
<code>notice: Starting Puppet master version 2.7.23</code>
注意:如果此前曾以其它主機名或各種原因啟動過puppet用戶端程序并完成過初始化,其證書檔案将無法符合本此啟動的需要;此時,需要先清空/var/lib/puppet/ssl/目錄方可完成後續的初始化操作。
如果上述的測試啟動沒有問題,可中止目前的啟動後将之啟動守護程序了,在CentOS6上,通常會使用如下指令進行。
<code>[root@node1 ~]</code><code># service puppetmaster start</code>
<code>Starting puppetmaster: [ OK ]</code>
<code>[root@node1 ~]</code><code># chkconfig puppetmaster on</code>
啟動puppet用戶端
puppet agent在首次啟動時,會向為其指定的puppet server申請證書,并完成後續連接配接請求。同樣地理由,出于測試的目的,接入目前puppet叢集中的首個agent節點可以以非守護程序的方式進行,以觀察其初始化過程,如下面的指令所示
<code>[root@node2 ~]</code><code># puppet agent --server=node1.luojianlong.com --no-daemonize --verbose</code>
<code>info: Creating a new SSL key </code><code>for</code> <code>node2.luojianlong.com</code>
<code>info: Caching certificate </code><code>for</code> <code>ca</code>
<code>info: Creating a new SSL certificate request </code><code>for</code> <code>node2.luojianlong.com</code>
<code>info: Certificate Request fingerprint (md5): 11:56:36:0D:A5:92:11:69:AC:66:46:1B:86:D9:B4:ED</code>
<code>[root@node3 ~]</code><code># puppet agent --server=node1.luojianlong.com --no-daemonize --verbose</code>
<code>info: Creating a new SSL key </code><code>for</code> <code>node3.luojianlong.com</code>
<code>info: Creating a new SSL certificate request </code><code>for</code> <code>node3.luojianlong.com</code>
<code>info: Certificate Request fingerprint (md5): A3:70:BF:52:F9:11:DA:0F:09:8B:35:C6:FC:EB:87:14</code>
此時,在puppet伺服器端使用puppet cert指令管理用戶端的證書請求,其--list選項能夠檢視等待簽署證書的用戶端清單,而--sign選項可用于為指定指定節點簽署證書,如果要一次性地為多個節點的證書申請進行簽署可同時使用--all選項。
<code>[root@node1 ~]</code><code># puppet cert --list</code>
<code> </code><code>"node2.luojianlong.com"</code> <code>(11:56:36:0D:A5:92:11:69:AC:66:46:1B:86:D9:B4:ED)</code>
<code> </code><code>"node3.luojianlong.com"</code> <code>(A3:70:BF:52:F9:11:DA:0F:09:8B:35:C6:FC:EB:87:14)</code>
<code>[root@node1 ~]</code><code># puppet cert --sign node2.luojianlong.com</code>
<code>notice: Signed certificate request </code><code>for</code> <code>node2.luojianlong.com</code>
<code>notice: Removing </code><code>file</code> <code>Puppet::SSL::CertificateRequest node2.luojianlong.com at </code><code>'/var/lib/puppet/ssl/ca/requests/node2.luojianlong.com.pem'</code>
<code>[root@node1 ~]</code><code># puppet cert --sign node3.luojianlong.com</code>
<code>notice: Signed certificate request </code><code>for</code> <code>node3.luojianlong.com</code>
<code>notice: Removing </code><code>file</code> <code>Puppet::SSL::CertificateRequest node3.luojianlong.com at </code><code>'/var/lib/puppet/ssl/ca/requests/node3.luojianlong.com.pem'</code>
一旦agent節點收到簽署過的證書時,其就會顯示類似如下資訊。
<code>info: Caching certificate </code><code>for</code> <code>node2.luojianlong.com</code>
<code>notice: Starting Puppet client version 2.7.23</code>
<code>info: Caching certificate_revocation_list </code><code>for</code> <code>ca</code>
<code>info: Caching catalog </code><code>for</code> <code>node2.luojianlong.com</code>
<code>info: Applying configuration version </code><code>'1389325340'</code>
<code>notice: </code><code>/Stage</code><code>[main]</code><code>/Nginx/Package</code><code>[nginx]</code><code>/ensure</code><code>: created</code>
<code>notice: </code><code>/Stage</code><code>[main]</code><code>/Nginx</code><code>::Nginx_web</code><code>/Service</code><code>[nginx]</code><code>/ensure</code><code>: ensure changed </code><code>'stopped'</code> <code>to </code><code>'running'</code>
<code>info: Creating state </code><code>file</code> <code>/var/lib/puppet/state/state</code><code>.yaml</code>
<code>notice: Finished catalog run </code><code>in</code> <code>10.22 seconds</code>
<code>info: Caching certificate </code><code>for</code> <code>node3.luojianlong.com</code>
<code>info: Caching catalog </code><code>for</code> <code>node3.luojianlong.com</code>
<code>notice: Finished catalog run </code><code>in</code> <code>17.83 seconds</code>
確定上述agent相關的操作不存在問題後,便可以将--server選項指定的資訊存儲于agent的配置檔案中,并以服務程序的方式啟動puppet agent了。其配置檔案為/etc/puppet/puppet.conf,server指令定義于[main]段中。配置完成,即可以服務方式啟動puppet。
<code>[root@node2 ~]</code><code># vi /etc/puppet/puppet.conf</code>
<code>server = node1.luojianlong.com</code>
<code>[root@node3 ~]</code><code># vi /etc/puppet/puppet.conf</code>
<code>[root@node2 ~]</code><code># service puppet start</code>
<code>Starting puppet: [ OK ]</code>
<code>[root@node3 ~]</code><code># service puppet start</code>
再次通過用戶端測試。
<code>[root@node2 ~]</code><code># puppet agent --server=node1.luojianlong.com --no-daemonize --verbose --test</code>
<code>notice: Finished catalog run </code><code>in</code> <code>0.97 seconds</code>
<code>[root@node3 ~]</code><code># puppet agent --server=node1.luojianlong.com --no-daemonize --verbose --test</code>
<code>notice: Finished catalog run </code><code>in</code> <code>0.95 seconds</code>
如上的資訊顯示其已經能正常與master建立連接配接
檢視node2,node3 nginx是否安裝并啟動
<code>[root@node2 ~]</code><code># rpm -q nginx</code>
<code>nginx-1.0.15-5.el6.x86_64</code>
<code>[root@node2 ~]</code><code># ps aux | grep nginx</code>
<code>root 19233 0.0 0.0 96432 1968 ? Ss 12:18 0:00 nginx: master process </code><code>/usr/sbin/nginx</code> <code>-c </code><code>/etc/nginx/nginx</code><code>.conf</code>
<code>nginx 19234 0.0 0.0 96780 2612 ? S 12:18 0:00 nginx: worker process </code>
<code>root 19515 0.0 0.0 103248 820 pts</code><code>/0</code> <code>S+ 12:22 0:00 </code><code>grep</code> <code>nginx</code>
<code>[root@node3 ~]</code><code># rpm -q nginx</code>
<code>[root@node3 ~]</code><code># ps aux | grep nginx</code>
<code>root 3082 0.0 0.0 96432 1968 ? Ss 12:18 0:00 nginx: master process </code><code>/usr/sbin/nginx</code> <code>-c </code><code>/etc/nginx/nginx</code><code>.conf</code>
<code>nginx 3083 0.0 0.0 96780 2612 ? S 12:18 0:00 nginx: worker process </code>
<code>root 3242 0.0 0.0 103248 824 pts</code><code>/0</code> <code>S+ 12:22 0:00 </code><code>grep</code> <code>nginx</code>
正常安裝啟動
自動簽發證書
可以設定master自動簽發所有的證書,我們隻需要在/etc/puppet 目錄下建立 autosign.conf 檔案,修改 /etc/puppet/puppet.conf檔案
<code>[root@node1 ~]</code><code># cat > /etc/puppet/autosign.conf << EOF</code>
<code>> *.luojianlong.com</code>
<code>> EOF</code>
<code>[root@node1 ~]</code><code># vi /etc/puppet/puppet.conf</code>
<code># 添加[master]</code>
<code>[master]</code>
<code>autosign = </code><code>/etc/puppet/autosign</code><code>.conf</code>
<code>[root@node1 ~]</code><code># service puppetmaster restart</code>
<code>Stopping puppetmaster: [ OK ]</code>
這樣就會對所有來自luojianlong.com 的機器的請求,都自動簽名,puppet每半個小時檢查一次更新,如果想修改檢查時間,可以修改用戶端配置檔案/etc/puppet/puppet.conf,在[agent]中添加runinterval的值,然後重新開機puppet預設為600,機關秒。
在node1上安裝配置puppet-dashboard:
<code>[root@node1 ~]</code><code># yum -y install rubygem-rake ruby-mysql</code>
<code>[root@node1 ~]</code><code># yum localinstall puppet-dashboard-1.2.23-1.el6.noarch.rpm -y</code>
<code>[root@node1 ~]</code><code># gem install rake</code>
在node1上安裝mysql
<code>[root@node1 ~]</code><code># tar zxvf mysql-5.5.33-linux2.6-x86_64.tar.gz -C /usr/local/</code>
<code>[root@node1 ~]</code><code># ln -s /usr/local/mysql-5.5.33-linux2.6-x86_64 /usr/local/mysql</code>
<code>[root@node1 ~]</code><code># cd /usr/local/mysql</code>
<code>[root@node1 mysql]</code><code># useradd -r mysql</code>
<code>[root@node1 mysql]</code><code># mkdir /mydata/data -p</code>
<code>[root@node1 mysql]</code><code># chown -R root.mysql ./*</code>
<code>[root@node1 mysql]</code><code># chown -R mysql.mysql /mydata/data/</code>
<code>[root@node1 mysql]</code><code># cp support-files/mysql.server /etc/rc.d/init.d/mysqld</code>
<code>[root@node1 mysql]</code><code># chkconfig --add mysqld</code>
<code>[root@node1 mysql]</code><code># chkconfig mysqld on</code>
<code>[root@node1 mysql]</code><code># cp support-files/my-large.cnf /etc/my.cnf</code>
<code>[root@node1 mysql]</code><code># ./scripts/mysql_install_db --user=mysql --datadir=/mydata/data</code>
<code>[root@node1 mysql]</code><code># vi /etc/profile.d/mysql.sh</code>
<code>export</code> <code>PATH=</code><code>/usr/local/mysql/bin</code><code>:$PATH</code>
<code>[root@node1 mysql]</code><code># . /etc/profile.d/mysql.sh</code>
<code>[root@node1 mysql]</code><code># vi /etc/my.cnf</code>
<code>datadir = </code><code>/mydata/data</code>
<code>innodb_file_per_table = 1</code>
<code>[root@node1 mysql]</code><code># service mysqld start</code>
<code>Starting MySQL..... SUCCESS!</code>
建立資料庫并完成授權
<code>mysql> create database dashboard character </code><code>set</code> <code>utf8;</code>
<code>Query OK, 1 row affected (0.00 sec)</code>
<code>mysql> grant all privileges on dashboard.* to </code><code>'dashboard'</code><code>@</code><code>'localhost'</code> <code>identified by </code><code>'123456'</code><code>;</code>
<code>Query OK, 0 rows affected (0.00 sec)</code>
<code>mysql> flush privileges;</code>
修改/usr/share/puppet-dashboard/config/database.yml中的production段。
<code>[root@node1 ~]</code><code># vi /usr/share/puppet-dashboard/config/database.yml</code>
<code>production:</code>
<code> </code><code>host: 127.0.0.1</code>
<code> </code><code>database: dashboard</code>
<code> </code><code>username: dashboard</code>
<code> </code><code>password: 123456</code>
<code> </code><code>encoding: utf8</code>
<code> </code><code>adapter: mysql</code>
<code>[root@node1 ~]</code><code># cd /usr/share/puppet-dashboard/</code>
<code>[root@node1 puppet-dashboard]</code><code># rake gems:refresh_specs</code>
<code># 為dashboard依賴的資料庫導入所需要的表:</code>
<code>[root@node1 puppet-dashboard]</code><code># rake RAILS_ENV=production db:migrate</code>
測試伺服器是否能正常工作
<code>[root@node1 ~]</code><code># /usr/share/puppet-dashboard/script/server -e production</code>
<code>=> Booting WEBrick</code>
<code>=> Rails 2.3.17 application starting on http:</code><code>//0</code><code>.0.0.0:3000</code>
<code>=> Call with -d to detach</code>
<code>=> Ctrl-C to </code><code>shutdown</code> <code>server</code>
<code>[2014-01-10 12:37:34] INFO WEBrick 1.3.1</code>
<code>[2014-01-10 12:37:34] INFO ruby 1.8.7 (2011-06-30) [x86_64-linux]</code>
<code>[2014-01-10 12:37:34] INFO WEBrick::HTTPServer</code><code>#start: pid=20641 port=3000</code>
<a href="http://s3.51cto.com/wyfs02/M02/24/0C/wKiom1NLaFbxFJTJAAGmfJmhvx0564.jpg" target="_blank"></a>
配置puppet服務端和用戶端
<code>#在[master]段中添加</code>
<code>reports = store, http</code>
<code>reporturl = http:</code><code>//192</code><code>.168.30.116:3000</code><code>/reports/upload</code>
<code># 在[agent]段中添加</code>
<code>report = </code><code>true</code>
<code>[root@node2 ~]</code><code># service puppet restart</code>
<code>Stopping puppet: [ OK ]</code>
<code># node3也一樣,添加并重新開機puppet</code>
然後啟動dashboard
<code>[root@node1 ~]</code><code># /usr/share/puppet-dashboard/script/server -e production -d</code>
<a href="http://s3.51cto.com/wyfs02/M02/24/11/wKioL1NLe3_DCQ0_AAHhDS_Y99s840.jpg" target="_blank"></a>
看到“# pending task”類的資訊,且數字大于0,則表示已經正常接收報告了,一旦有使用者任務延遲就會記錄在dashboard中。
puppet kick 功能實作
puppet用戶端預設每30分鐘跟伺服器通訊一次,但是有時,我們希望服務端能給用戶端緊急推送一些任務,于是就有了puppet kick(puppet 2.6以前叫puppetrun)。
編輯用戶端/etc/puppet/puppet.conf
<code>listen = </code><code>true</code>
<code># 編輯或建立檔案/etc/puppet/namespaceauth.conf</code>
<code>[root@node2 ~]</code><code># vi /etc/puppet/namespaceauth.conf</code>
<code>[puppetrunner]</code>
<code>allow *.luojianlong.com</code>
編輯檔案auth.conf
<code>[root@node2 ~]</code><code># vi /etc/puppet/auth.conf</code>
<code># 添加如下幾行</code>
<code>path </code><code>/run</code>
<code>method save</code>
<code>allow node1.luojianlong.com</code>
<code>[root@node2 ~]</code><code># netstat -anptl | grep ruby</code>
<code>tcp 0 0 0.0.0.0:8139 0.0.0.0:* LISTEN 27053</code><code>/ruby</code>
node3做上述一樣的操作
在服務端運作指令
<code>[root@node1 ~]</code><code># puppet kick -a --host=node2.luojianlong.com</code>
<code>Triggering node2.luojianlong.com</code>
<code>Getting status</code>
<code>status is success</code>
<code>node2.luojianlong.com finished with </code><code>exit</code> <code>code 0</code>
<code>Finished</code>
<code>[root@node1 ~]</code><code># puppet kick -a --host=node3.luojianlong.com</code>
<code>Triggering node3.luojianlong.com</code>
<code>node3.luojianlong.com finished with </code><code>exit</code> <code>code 0</code>
發現可以正常推送
本文轉自ljl_19880709 51CTO部落格,原文連結:http://blog.51cto.com/luojianlong/1395260,如需轉載請自行聯系原作者