<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>LPC影子技术分享</title>
	<atom:link href="https://www.mudbest.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.mudbest.com</link>
	<description>行影不离,忘之却步.</description>
	<lastBuildDate>Wed, 15 Apr 2026 19:58:27 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1</generator>
	<item>
		<title>针对近期遇到的full gc问题的解决思路做一个笔记</title>
		<link>https://www.mudbest.com/%e9%92%88%e5%af%b9%e8%bf%91%e6%9c%9f%e9%81%87%e5%88%b0%e7%9a%84full-gc%e9%97%ae%e9%a2%98%e7%9a%84%e8%a7%a3%e5%86%b3%e6%80%9d%e8%b7%af%e5%81%9a%e4%b8%80%e4%b8%aa%e7%ac%94%e8%ae%b0/</link>
		
		<dc:creator><![CDATA[hkshadow]]></dc:creator>
		<pubDate>Mon, 01 Aug 2022 03:30:00 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[分享]]></category>
		<guid isPermaLink="false">https://www.mudbest.com/?p=2369</guid>

					<description><![CDATA[针对近期遇到的full gc问题的解决思路做一个笔记 找到最近FULL GC的机器，ssh登录上去之后通过以下 ... <a title="针对近期遇到的full gc问题的解决思路做一个笔记" class="read-more" href="https://www.mudbest.com/%e9%92%88%e5%af%b9%e8%bf%91%e6%9c%9f%e9%81%87%e5%88%b0%e7%9a%84full-gc%e9%97%ae%e9%a2%98%e7%9a%84%e8%a7%a3%e5%86%b3%e6%80%9d%e8%b7%af%e5%81%9a%e4%b8%80%e4%b8%aa%e7%ac%94%e8%ae%b0/" aria-label="阅读 针对近期遇到的full gc问题的解决思路做一个笔记">阅读更多</a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">针对近期遇到的full gc问题的解决思路做一个笔记</p>



<p class="wp-block-paragraph">找到最近FULL GC的机器，ssh登录上去之后通过以下命令得到java的运行进程id。</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
ps -ef|grep java
</pre></div>


<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">然后打印JVM dump文件和jstack线程日志(有的服务器会对java进程进行权限隔离，也就是指定用户运行，root权限可能还无法导出dump，可通过)</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
sudo -u 服务账号 项目JAVA路径 -dump:format=b,file=dump文件名 java进程id
</pre></div>


<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">我这里执行的是</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
sudo -u deplpy /usr/java/jdk1.8/bin/jmap -dump:format=b,file=/tmp/log/heap.fprof 39
</pre></div>


<p class="wp-block-paragraph">再将dump文件下载至本地，通过MAT分析工具打开。</p>



<p class="wp-block-paragraph">打开后，可以从MAT引导的Actions里面进行相关指标查看，分别作用介绍如下：</p>



<pre class="wp-block-preformatted">Shallow Heap指标：对象本身占用内存的大小，不包含对其他对象的引用，也就是对象头加成员变量（不是成员变量的值）的总和
Retained Heap指标：是该对象自己的shallow size，加上从该对象能直接或间接访问到对象的shallow size之和。换句话说，retained size是该对象被GC之后所能回收到内存的总和。
Histogram动作：列出每个类的实例数
Dominator Tree动作：列出最大的对象以及它们保存的内容
Top Consumers动作: 按照类和包分组打印花费最高的实例
Duplicate Classes动作: 检测由多个类加载器加载的类
Leak Suspects报告: 包括泄密嫌疑人和系统概述
Top Components报告：列出大于总堆的1％的组件的报告</pre>



<h2 class="wp-block-heading">通过Leak Suspects排查内存泄露</h2>



<p class="wp-block-paragraph">在Ecplise Memory Analyzer导入JVM dump文件，点击工具栏上的 Leak Suspects 菜单项来生成内存泄露分析报告，也可以直接点击饼图下方的 Reports->Leak Suspects链接来生成报告。如图：</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1363" height="835" src="https://www.mudbest.com/wp-content/uploads/2022/08/7-1024x627.png" alt="" class="wp-image-2385" srcset="https://www.mudbest.com/wp-content/uploads/2022/08/7-1024x627.png 1024w, https://www.mudbest.com/wp-content/uploads/2022/08/7-610x374.png 610w, https://www.mudbest.com/wp-content/uploads/2022/08/7-768x470.png 768w, https://www.mudbest.com/wp-content/uploads/2022/08/7.png 1363w" sizes="(max-width: 1363px) 100vw, 1363px" /></figure>



<p class="wp-block-paragraph">MAT工具分析了heap dump后在界面上非常直观的展示了一个饼图，该图深色区域被怀疑有内存泄漏，可以发现整个heap才2G内存，深色区域就占了80.45%，接下来是一个简短的描述，MAT告诉我们存在两个可疑问题</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Problem Suspect 1：告诉我们类加载器&#8221;sun.misc.Launcher$ExtClassLoader&#8221;占用了901,934,832 (80.45%) bytes，内存积累在&#8221;java.util.WeakHashMap$Entry&#8221;的一个实例中，由&#8221;&#8221;加载，占用888,798,328 (79.28%) bytes。</p></blockquote>



<figure class="wp-block-image size-full"><img decoding="async" width="948" height="695" src="https://www.mudbest.com/wp-content/uploads/2022/08/8.png" alt="" class="wp-image-2387" srcset="https://www.mudbest.com/wp-content/uploads/2022/08/8.png 948w, https://www.mudbest.com/wp-content/uploads/2022/08/8-587x430.png 587w, https://www.mudbest.com/wp-content/uploads/2022/08/8-768x563.png 768w" sizes="(max-width: 948px) 100vw, 948px" /></figure>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>通过Shortest Paths To the Accumulation Point可查看到其中&#8221;java.util.WeakHashMap$Entry&#8221;的Shallow Heap 16,400条，Retained Heap占用字节888,798,328。</p></blockquote>



<figure class="wp-block-image size-full"><img decoding="async" width="1022" height="786" src="https://www.mudbest.com/wp-content/uploads/2022/08/9.png" alt="" class="wp-image-2388" srcset="https://www.mudbest.com/wp-content/uploads/2022/08/9.png 1022w, https://www.mudbest.com/wp-content/uploads/2022/08/9-559x430.png 559w, https://www.mudbest.com/wp-content/uploads/2022/08/9-768x591.png 768w" sizes="(max-width: 1022px) 100vw, 1022px" /></figure>



<p class="wp-block-paragraph"></p>



<h2 class="wp-block-heading">通过Top Consumers定位大对象</h2>



<p class="wp-block-paragraph">通过鼠标左键点击&#8221;sun.misc.Launcher$ExtClassLoader @ 0x4e0800440<br>First 10 of 634 objects&#8221; ，弹出 选项，选择 list objects -> with incoming references</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="922" height="286" src="https://www.mudbest.com/wp-content/uploads/2022/08/11.png" alt="" class="wp-image-2391" srcset="https://www.mudbest.com/wp-content/uploads/2022/08/11.png 922w, https://www.mudbest.com/wp-content/uploads/2022/08/11-610x189.png 610w, https://www.mudbest.com/wp-content/uploads/2022/08/11-768x238.png 768w" sizes="auto, (max-width: 922px) 100vw, 922px" /></figure>



<p class="wp-block-paragraph">发现class jdk.nashorn.internal.scripts.JO @ 0x4e61db098下面加载的大对象关键字有&#8221;class jdk.nashorn.internal.scripts.JO @ 0x4e61db098&#8243;，到此处该问题已经有些眉目了，印象里项目中有一处java处理script的代码，剩下的就是修改代码了。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="907" height="803" src="https://www.mudbest.com/wp-content/uploads/2022/08/10.png" alt="" class="wp-image-2389" srcset="https://www.mudbest.com/wp-content/uploads/2022/08/10.png 907w, https://www.mudbest.com/wp-content/uploads/2022/08/10-486x430.png 486w, https://www.mudbest.com/wp-content/uploads/2022/08/10-768x680.png 768w" sizes="auto, (max-width: 907px) 100vw, 907px" /></figure>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">再分析第二个dump文件</p>



<h2 class="wp-block-heading">通过Leak Suspects排查内存泄露</h2>



<p class="wp-block-paragraph">dump导出方法上面已经讲过，这里就不再赘述。直入正题，通过分析可发现几处关键字&#8221;apache&#8221;，&#8221;HashMap&#8221;。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="943" height="802" src="https://www.mudbest.com/wp-content/uploads/2022/08/12.png" alt="" class="wp-image-2392" srcset="https://www.mudbest.com/wp-content/uploads/2022/08/12.png 943w, https://www.mudbest.com/wp-content/uploads/2022/08/12-506x430.png 506w, https://www.mudbest.com/wp-content/uploads/2022/08/12-768x653.png 768w" sizes="auto, (max-width: 943px) 100vw, 943px" /></figure>



<p class="wp-block-paragraph">根据Problem Suspect 1提示 可得知；</p>



<p class="wp-block-paragraph">The classloader/component “org.apache.catalina.loader.WebappClassLoader @ 0x4e08000c8” occupies 45,773,960 (23.97%) bytes. The memory is accumulated in one instance of “java.util.concurrent.ConcurrentHashMap$Node[]”, loaded by “”, which occupies 37,810,784 (19.80%) bytes.</p>



<pre class="wp-block-preformatted">关键字：
org.apache.catalina.loader.WebappClassLoader @ 0x4e08000c8
java.util.concurrent.ConcurrentHashMap$Node[]</pre>



<p class="wp-block-paragraph">点击Details进入详情</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>查阅Accumulated Objects in Dominator Tree可发现 &#8220;org.apache.catalina.loader.WebappClassLoader @ 0x4e08000c8&#8221; 下 Shallow Heap占了 131,088 条，Retained Heap占 37,810,784字节。</p></blockquote>



<p class="wp-block-paragraph">继续通过鼠标左键 点击 &#8220;org.apache.catalina.loader.WebappClassLoader @ 0x4e08000c8&#8221; 弹出 选项，选择 list objects -> with outcoming references，然后点击一下 Retained Heap，进行倒叙排序，再展开&#8221;java.util.concurrent.ConcurrentHashMap @ 0x4e0e3cf00&#8243;可查看到Shallow Heap占了 131,088 条。</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="854" height="699" src="https://www.mudbest.com/wp-content/uploads/2022/08/13.png" alt="" class="wp-image-2393" srcset="https://www.mudbest.com/wp-content/uploads/2022/08/13.png 854w, https://www.mudbest.com/wp-content/uploads/2022/08/13-525x430.png 525w, https://www.mudbest.com/wp-content/uploads/2022/08/13-768x629.png 768w" sizes="auto, (max-width: 854px) 100vw, 854px" /></figure>



<p class="wp-block-paragraph">然后根据提供的关键字&#8221;apache&#8221;以及&#8221;hashMap&#8221;大致问题出现在了 api层，再根据调用日志定位，基本上也有眉目了。</p>



<h2 class="wp-block-heading">问题分析：</h2>



<pre id="block-de19a5ec-20bb-455c-bb77-d3f2cf5711f5" class="wp-block-preformatted">1、大量jdk.nashorn.internal._和javax.script._相关实例，而jdk.nashorn.*这个包是Nashorn JavaScript引擎的包，主要是nashorn用于在JVM上以原生方式运行动态的JavaScript代码来扩展Java的功能，javax.script包用于javascript与java交互操作。于是可以基本断定这是跟javascript脚本相关操作有关，应该是有地方不断创建javascript脚本相关对象没有被回收。</pre>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="652" height="144" src="https://www.mudbest.com/wp-content/uploads/2022/08/14.png" alt="" class="wp-image-2394" srcset="https://www.mudbest.com/wp-content/uploads/2022/08/14.png 652w, https://www.mudbest.com/wp-content/uploads/2022/08/14-610x135.png 610w" sizes="auto, (max-width: 652px) 100vw, 652px" /></figure>



<pre class="wp-block-preformatted">2、org.apache.catalina.loader.WebappClassLoader加载了大量hashMap，也说明了一直再创建没有被回收或者说回收不及时。</pre>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="989" height="191" src="https://www.mudbest.com/wp-content/uploads/2022/08/15.png" alt="" class="wp-image-2395" srcset="https://www.mudbest.com/wp-content/uploads/2022/08/15.png 989w, https://www.mudbest.com/wp-content/uploads/2022/08/15-610x118.png 610w, https://www.mudbest.com/wp-content/uploads/2022/08/15-768x148.png 768w" sizes="auto, (max-width: 989px) 100vw, 989px" /></figure>



<h2 class="wp-block-heading">解决方案：</h2>



<pre class="wp-block-preformatted">如果JavaScript代码是固定不变，只是根据接受参数不通进行返回，那么可以尝试通过关键字 static、final，避免每次了每次调用都会new。
</pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="83" src="https://www.mudbest.com/wp-content/uploads/2022/08/16-1024x83.png" alt="" class="wp-image-2396" srcset="https://www.mudbest.com/wp-content/uploads/2022/08/16-1024x83.png 1024w, https://www.mudbest.com/wp-content/uploads/2022/08/16-610x49.png 610w, https://www.mudbest.com/wp-content/uploads/2022/08/16-768x62.png 768w, https://www.mudbest.com/wp-content/uploads/2022/08/16.png 1481w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">通过修正后，观察前后JMX指标，可看出FULL GC已经完全消失，同时新生代与老年代与之前相比明显好了许多，元数据空间占用也变得平滑 (<strong>虚线绿色 之前为 未优化指标，虚线绿色  之后 为优化后发布指标</strong>)。</p>



<p class="wp-block-paragraph">优化前：</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="573" height="177" src="https://www.mudbest.com/wp-content/uploads/2022/08/1-1.png" alt="" class="wp-image-2400"/></figure>



<p class="wp-block-paragraph">优化后：</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="570" height="187" src="https://www.mudbest.com/wp-content/uploads/2022/08/2.png" alt="" class="wp-image-2398"/></figure>



<p class="wp-block-paragraph">优化前：</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="878" height="184" src="https://www.mudbest.com/wp-content/uploads/2022/08/5.png" alt="" class="wp-image-2401" srcset="https://www.mudbest.com/wp-content/uploads/2022/08/5.png 878w, https://www.mudbest.com/wp-content/uploads/2022/08/5-610x128.png 610w, https://www.mudbest.com/wp-content/uploads/2022/08/5-768x161.png 768w" sizes="auto, (max-width: 878px) 100vw, 878px" /></figure>



<p class="wp-block-paragraph">优化后：</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="886" height="183" src="https://www.mudbest.com/wp-content/uploads/2022/08/3.png" alt="" class="wp-image-2399" srcset="https://www.mudbest.com/wp-content/uploads/2022/08/3.png 886w, https://www.mudbest.com/wp-content/uploads/2022/08/3-610x126.png 610w, https://www.mudbest.com/wp-content/uploads/2022/08/3-768x159.png 768w" sizes="auto, (max-width: 886px) 100vw, 886px" /></figure>



<p class="wp-block-paragraph">优化前：</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="577" height="191" src="https://www.mudbest.com/wp-content/uploads/2022/08/2-1.png" alt="" class="wp-image-2402"/></figure>



<p class="wp-block-paragraph">优化后：</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="572" height="185" src="https://www.mudbest.com/wp-content/uploads/2022/08/1.png" alt="" class="wp-image-2397"/></figure>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">至此FULL GC已经解决，做个笔记make一下，根据指标监控还是有优化空间，后续再按照此思路进一步对JVM优化。</p>



<h2 class="wp-block-heading">后续优化效果(<strong>绿色虚线为发布时间点</strong>)：</h2>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">右键新窗口打开图片可放大</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1821" height="810" src="https://www.mudbest.com/wp-content/uploads/2022/08/mm1.png" alt="" class="wp-image-2410" srcset="https://www.mudbest.com/wp-content/uploads/2022/08/mm1.png 1821w, https://www.mudbest.com/wp-content/uploads/2022/08/mm1-610x271.png 610w, https://www.mudbest.com/wp-content/uploads/2022/08/mm1-1024x455.png 1024w, https://www.mudbest.com/wp-content/uploads/2022/08/mm1-768x342.png 768w, https://www.mudbest.com/wp-content/uploads/2022/08/mm1-1536x683.png 1536w" sizes="auto, (max-width: 1821px) 100vw, 1821px" /></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1821" height="834" src="https://www.mudbest.com/wp-content/uploads/2022/08/mm2.png" alt="" class="wp-image-2411" srcset="https://www.mudbest.com/wp-content/uploads/2022/08/mm2.png 1821w, https://www.mudbest.com/wp-content/uploads/2022/08/mm2-610x279.png 610w, https://www.mudbest.com/wp-content/uploads/2022/08/mm2-1024x469.png 1024w, https://www.mudbest.com/wp-content/uploads/2022/08/mm2-768x352.png 768w, https://www.mudbest.com/wp-content/uploads/2022/08/mm2-1536x703.png 1536w" sizes="auto, (max-width: 1821px) 100vw, 1821px" /></figure>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>php5.4升php7.3踩坑之路</title>
		<link>https://www.mudbest.com/php5-4%e5%8d%87php7-3%e8%b8%a9%e5%9d%91%e4%b9%8b%e8%b7%af/</link>
		
		<dc:creator><![CDATA[hkshadow]]></dc:creator>
		<pubDate>Fri, 12 Mar 2021 18:24:51 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[分享]]></category>
		<category><![CDATA[Mysql]]></category>
		<category><![CDATA[mysql5.7]]></category>
		<category><![CDATA[php5升级php7]]></category>
		<category><![CDATA[php7]]></category>
		<guid isPermaLink="false">https://www.mudbest.com/?p=2200</guid>

					<description><![CDATA[6年没有更新博客了，近期计划内项目有一些web服务底层基于php7+、mysql5.7+开发的，而服务器的ph ... <a title="php5.4升php7.3踩坑之路" class="read-more" href="https://www.mudbest.com/php5-4%e5%8d%87php7-3%e8%b8%a9%e5%9d%91%e4%b9%8b%e8%b7%af/" aria-label="阅读 php5.4升php7.3踩坑之路">阅读更多</a>]]></description>
										<content:encoded><![CDATA[
<blockquote class="wp-block-quote is-style-default is-layout-flow wp-block-quote-is-layout-flow">
<p>6年没有更新博客了，近期计划内项目有一些web服务底层基于php7+、mysql5.7+开发的，而服务器的php版本停留在了5.4一直未更新(mysql.5.5)，导致环境无法部署，考虑到运行的服务比较关键致使升级的计划一而再被拖延。</p>
</blockquote>

<p>&nbsp;</p>
<p>&nbsp;</p>

<p class="wp-block-paragraph">这次决定将php5.4和mysql5.5升级至php7.3和mysq5.7做个记录，希望能帮助到其他类似需要升级的人。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>先说一下版本情况：</p>
<cite>centos6.8，php5.4，mysql5.7</cite></blockquote>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph"><strong>升级php7.3过程比较简单。</strong></p>



<p class="wp-block-paragraph">1、安装epel源</p>


<pre><pre class="brush: bash; title: ; notranslate">
yum install epel-release
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">2、加载remirepo的php源(注意：centos7不是用这个源)</p>


<pre><pre class="brush: bash; title: ; notranslate">
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">2、安装php7.3</p>


<pre><pre class="brush: bash; title: ; notranslate">
yum --enablerepo=remi-php73 install php
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">3、安装主要扩展包</p>


<pre><pre class="brush: bash; title: ; notranslate">
yum --enablerepo=remi-php73 install php-xml php-soap php-xmlrpc php-mbstring php-json php-gd php-mcrypt php-fpm
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">4、安装完成后，重启php-fpm</p>


<pre><pre class="brush: bash; title: ; notranslate">
kill -USR2 `cat /var/run/php-fpm/php-fpm.pid`
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">5、以下非必要</p>


<pre><pre class="brush: bash; title: ; notranslate">
yum update
</pre>



<p class="wp-block-paragraph">至此，php7.3安装完成，此处我遇到1个关于mysqli扩展的问题，默认php-fpm的配置是加载了mysqli的，但是不知道为什么我查看phpinfo是没有mysqli扩展信息的，后来在php.ini里开启了mysqli扩展才识别了，不知道其他人有没有遇到。</p>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph"><strong>接着就是升级mysql5.4至mysql5.7了。</strong></p>



<p class="wp-block-paragraph">首先备份数据库，升级MySQL通常不会丢失数据，但保险起见，我们需要做这一步。</p>



<p class="wp-block-paragraph">这种方式备份的侧重点是库与表，备份文件里面会有use db_name这样的语句，方便于恢复数据时知道要把表创建到哪个数据库。</p>


<pre><pre class="brush: bash; title: ; notranslate">
mysqldump -uroot -p &#x5B;--no-data] --databases db_name1 db_name2 &amp;amp;amp;amp;gt; /dir/backup.sql;  //--no-data指不备份数据，只备份库与表结构。
</pre>


<pre><pre class="brush: bash; title: ; notranslate">
mysqldump -u xxx -h xxx -P 3306 -p --all-databases &amp;amp;amp;amp;gt; databases.sql;   // 备份所有库
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">1、备份完数据库之后，开始卸载旧版本 MySQL</p>


<pre><pre class="brush: bash; title: ; notranslate">
yum remove mysql mysql-*
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">2、确认mysql是否卸载完全</p>


<pre><pre class="brush: bash; title: ; notranslate">
yum list installed | grep mysql
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">3、上面的情况是没有未删除部分，如果有的话可通过下面的命令删除：</p>


<pre><pre class="brush: bash; title: ; notranslate">
yum remove mysql－libs
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">4、查看系统版本</p>


<pre><pre class="brush: bash; title: ; notranslate">
&#x5B;root@iZbp18bpfv23id1yoiv3f0Z include]# uname -r
2.6.32-754.35.1.el6.x86_64
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">5、mysql官方源太慢了，这里用第三方源(<a href="http://mirrors.sohu.com/mysql/MySQL-5.7/" target="_blank" rel="noreferrer noopener" data-type="URL" data-id="http://mirrors.sohu.com/mysql/MySQL-5.7/">传送门</a>)</p>



<p class="wp-block-paragraph">//贴图</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="824" height="635" class="wp-image-2203" src="https://www.mudbest.com/wp-content/uploads/2021/03/mysql-1.png" alt="" srcset="https://www.mudbest.com/wp-content/uploads/2021/03/mysql-1.png 824w, https://www.mudbest.com/wp-content/uploads/2021/03/mysql-1-558x430.png 558w, https://www.mudbest.com/wp-content/uploads/2021/03/mysql-1-768x592.png 768w" sizes="auto, (max-width: 824px) 100vw, 824px" /></figure>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">6、然后根据自己系统配置选择对应的 rpm 包(我这里下载的是5.7.23)，鼠标右键打开复制链接，然后到软件包目录执行下载命令</p>


<pre><pre class="brush: bash; title: ; notranslate">
wget http://mirrors.sohu.com/mysql/MySQL-5.7/mysql-5.7.23-1.el6.x86_64.rpm-bundle.tar
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">7、解压包</p>


<pre><pre class="brush: bash; title: ; notranslate">
tar -zcvf mysql-5.7.23-1.el6.x86_64.rpm-bundle.tar
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">8、安装rpm以及相关依赖</p>


<pre><pre class="brush: bash; title: ; notranslate">
yum localinstall mysql-community-common-5.7.23-1.el6.x86_64.rpm
</pre>


<pre><pre class="brush: bash; title: ; notranslate">
yum localinstall mysql-community-libs-5.7.23-1.el6.x86_64.rpm
</pre>


<pre><pre class="brush: bash; title: ; notranslate">
yum localinstall mysql-community-client-5.7.23-1.el6.x86_64.rpm
</pre>


<pre><pre class="brush: bash; title: ; notranslate">
yum localinstall mysql-community-server-5.7.23-1.el6.x86_64.rpm
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">9、OK安装完成，查看版本</p>


<pre><pre class="brush: bash; title: ; notranslate">
&#x5B;root@*** include]# mysql -V
mysql  Ver 14.14 Distrib 5.7.23, for Linux (x86_64) using  EditLine wrapper
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">10、重启mysql</p>


<pre><pre class="brush: bash; title: ; notranslate">
service mysqld start
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">11、如果重启mysql失败，初始化数据库。</p>


<pre><pre class="brush: bash; title: ; notranslate">
mysqld --initialize
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">12、基于mysql5.7的安全机制有变更，默认mysql是有密码的，查看默认密码。</p>


<pre><pre class="brush: bash; title: ; notranslate">
&#x5B;root@******************* include]# grep 'temporary password' /var/log/mysqld.log
2021-03-09T10:52:05.394381Z 1 &#x5B;Note] A temporary password is generated for root@localhost: *****?4#v
2021-03-09T10:54:04.766642Z 1 &#x5B;Note] A temporary password is generated for root@localhost: *****zyc6/(
2021-03-09T10:55:15.770123Z 1 &#x5B;Note] A temporary password is generated for root@localhost: *****Vy!y0!h
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">13、还是基于安全，默认登录到mysql命令控制台，执行任何有效命令都会提示重新设置密码。</p>


<pre><pre class="brush: bash; title: ; notranslate">
mysql -&amp;amp;amp;amp;amp;gt; select host from mysql.user where User='root';
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">14、修改密码(5.7的密码验证要求高，密码过于简单会提示错误)</p>


<pre><pre class="brush: bash; title: ; notranslate">
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('123456');
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">15、密码过于简单报错</p>


<pre><pre class="brush: bash; title: ; notranslate">
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">16、最后让修改生效执行</p>


<pre><pre class="brush: bash; title: ; notranslate">
flush privileges;
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">至此，mysql的安装以及配置完成，剩下就是进入控制台 source导入上面备份的数据库就行了。</p>



<p class="wp-block-paragraph">==================================================我是分割线</p>



<p class="wp-block-paragraph">踩坑开始：</p>



<p class="wp-block-paragraph">由于论坛(<a href="https://bbs.mudbest.com" target="_blank" rel="noreferrer noopener">https://bbs.mudbest.com</a>)是基于discuz7.2开发的，很多函数在php7.3被废弃了甚至会报错，php7.3和mysql5.7升级完成之后，然后一脸懵逼。。论坛挂了。。。无法访问。</p>



<p class="wp-block-paragraph">现在回过头看discuz7的代码(无法言喻。。)，打开php-fpm的运行错误，在php-fpm.conf内添加以下内容，然后打开error_log就可以看到运行的错误信息了</p>


<pre><pre class="brush: bash; title: ; notranslate">
&#x5B;www]
catch_workers_output = yes
</pre>



<p class="wp-block-paragraph">坑整理：<br />1、set_magic_quotes_runtime 报致命错误。<br />2、ob_start('ob_gzhandler') 报致命错误。<br />3、preg_replace 带evel的 报致命错误。<br />4、php7 session不能传递的解决方案<br />5、….各种告警(修了70%，剩下30%不想修了，直接改告警登记屏蔽了，哈哈)</p>



<p class="wp-block-paragraph"><strong>关于问题3、4 的解决方式：</strong><br />1、针对 preg_replace evel替代方案就是将 全站用到 evel的换成preg_replace_callback，来个例子。</p>


<pre><pre class="brush: php; title: ; notranslate">
$message = preg_replace(&quot;/\s?&#x5B;code](.+?)&#x5B;\/code]\s?/ies&quot;, &quot;codedisp('\1')&quot;, $message);
</pre>



<p class="wp-block-paragraph">改写成</p>


<pre><pre class="brush: php; title: ; notranslate">
$message = preg_replace_callback(
&quot;/\s?&#x5B;code](.+?)&#x5B;\/code]\s?/is&quot;,
function ($matches) {
return codedisp($matches&#x5B;1]);
},
$message
);
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph"><em>扩展知识：</em></p>


<pre><pre class="brush: php; title: ; notranslate">
//适合单一任务
$template = preg_replace_callback( //处理eval
    &quot;/&#x5B;\n\r\t]*\{eval\s+(.+?)\}&#x5B;\n\r\t]*/is&quot;,
    function ($matches) { return str_replace(&quot;\\\&quot;&quot;, &quot;\&quot;&quot;, preg_replace(&quot;/\&amp;amp;amp;amp;amp;lt;\?\=(\\\$.+?)\?\&amp;amp;amp;amp;amp;gt;/s&quot;, &quot;\\1&quot;, &quot;&amp;amp;amp;amp;amp;lt;? $matches&#x5B;1] ?&amp;amp;amp;amp;amp;gt;&quot;)); },
    $template
);
 
//需要同一正则处理多个任务时  &#x5B;推荐]
function stripvtags($expr) {
    $expr = str_replace(&quot;\\\&quot;&quot;, &quot;\&quot;&quot;, preg_replace(&quot;/\&amp;amp;amp;amp;amp;lt;\?\=(\\\$.+?)\?\&amp;amp;amp;amp;amp;gt;/s&quot;, &quot;\\1&quot;, $expr));
    return $expr;
}
$template = preg_replace_callback( //处理eval
    &quot;/&#x5B;\n\r\t]*\{eval\s+(.+?)\}&#x5B;\n\r\t]*/is&quot;,
    function ($matches) { return stripvtags(&quot;&amp;amp;amp;amp;amp;lt;? $matches&#x5B;1] ?&amp;amp;amp;amp;amp;gt;&quot;); },
    $template
);
$template = preg_replace_callback( //处理echo
    &quot;/&#x5B;\n\r\t]*\{echo\s+(.+?)\}&#x5B;\n\r\t]*/is&quot;,
    function ($matches) { return stripvtags(&quot;&amp;amp;amp;amp;amp;lt;? echo $matches&#x5B;1] ?&amp;amp;amp;amp;amp;gt;&quot;); },
    $template
);
 
//与第一种差不多, 只不过是分开写
class Template {
    public function test() {
        $template = preg_replace_callback( //处理eval
            &quot;/&#x5B;\n\r\t]*\{eval\s+(.+?)\}&#x5B;\n\r\t]*/is&quot;,
            array($this, 'stripvtagsEval'),
            $template
        );
    }
    protected function stripvtagsEval($matches) {
        return str_replace(&quot;\\\&quot;&quot;, &quot;\&quot;&quot;, preg_replace(&quot;/\&amp;amp;amp;amp;amp;lt;\?\=(\\\$.+?)\?\&amp;amp;amp;amp;amp;gt;/s&quot;, &quot;\\1&quot;, &quot;&amp;amp;amp;amp;amp;lt;? $matches&#x5B;1] ?&amp;amp;amp;amp;amp;gt;&quot;)); 
    }
}
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">2、session问题只需要将php.ini内的session.use_trans_sid设置为1，并且将存放session的目录权限改为可写入。</p>


<pre><pre class="brush: bash; title: ; notranslate">
session.use_trans_sid=0
</pre>



<p class="wp-block-paragraph">&nbsp;</p>



<p class="wp-block-paragraph">改为</p>


<pre><pre class="brush: bash; title: ; notranslate">
session.use_trans_sid=1
</pre>

<p>&nbsp;</p>

<p class="wp-block-paragraph">&nbsp;</p>

<p>验证码无法显示的原因，可以看查看一下session.save_path目录的权限，默认这个目录是给apache，如果nginx启动用户非apache则无法写入session 默认session.save_page目录为/var/lib/php</p>
<pre><pre class="brush: bash; title: ; notranslate">
drwxrwx--- 2 root apache   6 Aug  4 02:40 opcache
drwxr-xr-x 2 root root   116 Nov 15 16:43 peclxml
drwxrwx--- 2 root apache   6 Aug  4 02:40 session
drwxrwx--- 2 root apache   6 Aug  4 02:40 wsdlcache
</pre></pre>
<p>我这里nginx改了启动用户，将www改成自己配置的用户组即可。20231116</p>
<pre><pre class="brush: bash; title: ; notranslate">
chown www:www /var/lib/php -R
</pre></pre>

<p class="wp-block-paragraph">至此，从升级配置直至填坑恢复，用了2天，又掉了不少头发，赶紧洗洗睡了。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>redis的hGetAll函数的性能问题</title>
		<link>https://www.mudbest.com/redis%e7%9a%84hgetall%e5%87%bd%e6%95%b0%e7%9a%84%e6%80%a7%e8%83%bd%e9%97%ae%e9%a2%98/</link>
		
		<dc:creator><![CDATA[hkshadow]]></dc:creator>
		<pubDate>Wed, 14 Jan 2015 07:58:51 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[分享]]></category>
		<category><![CDATA[hGetAll]]></category>
		<category><![CDATA[redis]]></category>
		<guid isPermaLink="false">http://www.mudbest.com/?p=2112</guid>

					<description><![CDATA[在没关注这个函数之前，一直用的Memcache的数据存储方式，但是自从更换了redis之后，对于一个hash的 ... <a title="redis的hGetAll函数的性能问题" class="read-more" href="https://www.mudbest.com/redis%e7%9a%84hgetall%e5%87%bd%e6%95%b0%e7%9a%84%e6%80%a7%e8%83%bd%e9%97%ae%e9%a2%98/" aria-label="阅读 redis的hGetAll函数的性能问题">阅读更多</a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">在没关注这个函数之前，一直用的Memcache的数据存储方式，但是自从更换了redis之后，对于一个hash的数据存与取 对于Memcache方便甚多，但是问题来了，一个hash的列表如果量不大的情况，用hGetAll函数几乎看不出问题，一旦这个列表超过50或者更多时，此时用hGetAll函数便能很直观的看到性能问题，这里就不作数据分析了。<br><br>Redis是单线程的！当它处理一个请求时其他的请求只能等着。通常请求都会很快处理完，但是当我们使用HGETALL的时候，必须遍历每个字段来获取数据，这期间消耗的CPU资源和字段数成正比，如果还用了PIPELINING，无疑更是雪上加霜。</p>



<span id="more-2112"></span>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
PERFORMANCE = CPUs / OPERATIONs
</pre></div>


<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">也就是说，此场景下为了提升性能，要么增加运算过程中的CPU数量；要么降低运算过程中的操作数量。在为了继续使用hash结构的数据，又要解决此问题，比较方便的方法就是将hash以序列化字符串存储，取的时候先取出反序列化的数据，再用hGet(key,array(hash..))。</p>



<p class="wp-block-paragraph">例如：</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
$arrKey = array(&#039;dbfba184bef630526a75f2cd073a6098&#039;,&#039;dbfba184bef630526a75f2cd0dswet98&#039;)
$strKey = &#039;test&#039;;
$obj-&gt;hmGet($strKey,$arrKey);
</pre></div>


<p class="wp-block-paragraph">把原本的hGetAll操作简化为hGet，也就是说，不再需要遍历hash中的每一个字段，因此即便不能让多个CPU参与运算，但是却大幅降低了操作数量，所以性能的提升仍然是显著的；当然劣势也很明显，和所有的冗余方式一样，此方案浪费了大量的内存。</p>



<p class="wp-block-paragraph">有人会问，这样虽然没有了遍历字段的过程，但是却增加了反序列化的过程，而反序列化的成本往往也是很高的，难道这样也能提升性能？问题的关键在于开始我们遍历字段的操作是在一个cpu上完成的，后来反序列化的操作，不管是什么语言，都可以通过多进程或多线程来保证是在多个cpu上完成的，所以性能总体上是提升的。</p>



<p class="wp-block-paragraph">另外，很多人直觉是通过运行redis多实例来解决问题。确实，这样可以增加运算过程中的CPU数量，有助于提升性能，但是需要注意的是，hGetAll和PIPELINING往往会让运算过程中的操作数量呈几何级爆炸式增长，相比之下，我们能增加的redis多实例数量简直就是杯水车薪，所以本例中这种方法不能彻底解决问题。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Centos升级gcc4.4.7升级gcc4.8手记</title>
		<link>https://www.mudbest.com/centos%e5%8d%87%e7%ba%a7gcc4-4-7%e5%8d%87%e7%ba%a7gcc4-8%e6%89%8b%e8%ae%b0/</link>
					<comments>https://www.mudbest.com/centos%e5%8d%87%e7%ba%a7gcc4-4-7%e5%8d%87%e7%ba%a7gcc4-8%e6%89%8b%e8%ae%b0/#comments</comments>
		
		<dc:creator><![CDATA[hkshadow]]></dc:creator>
		<pubDate>Sat, 23 Aug 2014 17:25:20 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[centos]]></category>
		<category><![CDATA[gcc]]></category>
		<guid isPermaLink="false">http://www.mudbest.com/?p=2100</guid>

					<description><![CDATA[出于需求系统自带的是gcc4.4.7，版本太低无法编译，被逼无奈只能升级gcc了，碰到很多坑，下载这个玩意就用 ... <a title="Centos升级gcc4.4.7升级gcc4.8手记" class="read-more" href="https://www.mudbest.com/centos%e5%8d%87%e7%ba%a7gcc4-4-7%e5%8d%87%e7%ba%a7gcc4-8%e6%89%8b%e8%ae%b0/" aria-label="阅读 Centos升级gcc4.4.7升级gcc4.8手记">阅读更多</a>]]></description>
										<content:encoded><![CDATA[<p>出于需求系统自带的是gcc4.4.7，版本太低无法编译，被逼无奈只能升级gcc了，碰到很多坑，下载这个玩意就用了不少时间。<span id="more-2100"></span></p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@VM_222_92_centos ~]# gcc -v
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) 
</pre>
<p>1.下载源码包</p>
<pre class="brush: bash; title: ; notranslate">
wget http: //ftp.gnu.org/gnu/gcc/gcc-4.8.0/gcc-4.8.0.tar.bz2
tar -jxvf  gcc-4.8.0.tar.bz2
</pre>
<p>2.下载编译所需依赖库</p>
<pre class="brush: bash; title: ; notranslate">
cd gcc-4.8.0
./contrib/download_prerequisites
cd ..
</pre>
<p>3.建立编译输出目录</p>
<pre class="brush: bash; title: ; notranslate">
mkdir gcc-build-4.8.0
</pre>
<p>4.进入此目录，执行以下命令，生成makefile文件</p>
<pre class="brush: bash; title: ; notranslate">
cd  gcc-build-4.8.0
../gcc-4.8.0/configure --enable-checking=release --enable-languages=c,c++ --disable-multilib
</pre>
<p>5.编译</p>
<pre class="brush: bash; title: ; notranslate">
# j 后面的是核心数，编译速度会比较快
make -j4
</pre>
<p>6.安装</p>
<pre class="brush: bash; title: ; notranslate">
sudo make install
</pre>
<p>7.切换GCC到新版<br />
确定新安装的GCC的路径,一般默认在/usr/local/bin下。可以先updatedb,然后locate gcc-4.8|tail找一下</p>
<pre class="brush: bash; title: ; notranslate">
ls /usr/local/bin | grep gcc
</pre>
<p>添加新GCC到可选项，倒数第三个是名字，倒数第二个参数为新GCC路径，最后一个参数40为优先级，设大一些之后就自动使用新版了 </p>
<pre class="brush: bash; title: ; notranslate">
update-alternatives --install /usr/bin/gcc gcc /usr/local/bin/i686-pc-linux-gnu-gcc 40 
</pre>
<p>8.确认当前版本已经切换为新版(重新连接shell生效).</p>
<pre class="brush: bash; title: ; notranslate">
gcc -v
</pre>
<p><img loading="lazy" decoding="async" src="http://www.mudbest.com/wp-content/uploads/2014/08/71-610x83.jpg" alt="7" width="610" height="83" class="alignnone size-medium wp-image-2107" srcset="https://www.mudbest.com/wp-content/uploads/2014/08/71-610x83.jpg 610w, https://www.mudbest.com/wp-content/uploads/2014/08/71.jpg 906w" sizes="auto, (max-width: 610px) 100vw, 610px" /></p>
<p>近次make的时候提示下面的问题。</p>
<pre class="brush: bash; title: ; notranslate">
../driver: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.18' not found (required by ../driver)
../driver: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.14' not found (required by ../driver)
</pre>
<p>这是因为虽然升级了GCC，生成的动态库没有替换老版本gcc的动态库。</p>
<p>解决方法：</p>
<pre class="brush: bash; title: ; notranslate">
cp /usr/local/lib64/libstdc++.so.6.0.18 /usr/lib64/
rm -f libstdc++.so.6
ln -s libstdc++.so.6.0.18 libstdc++.so.6
</pre>
<p>这里fluffos编译时的环境为libevent-2.1.so.6，为了能直接使用上，需要对应安装。</p>
<p>OK，检查一下</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@iZ237sml740Z ~]# strings /usr/lib64/libstdc++.so.6|grep GLIBCXX
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBCXX_3.4.14
GLIBCXX_3.4.15
GLIBCXX_3.4.16
GLIBCXX_3.4.17
GLIBCXX_3.4.18
GLIBCXX_FORCE_NEW
GLIBCXX_DEBUG_MESSAGE_LENGTH
</pre>
<p>至此，已完成了GCC相关的安装&#038;设置，20170722补充。</p>
<p>现在来说下坑吧，以上的步骤完全不需要画蛇添足，几个步骤不多不少，我之前对第二步进行单独的make,make check，结果悲剧了，各种报错。碰到第二坑就是磁盘问题，上面说系统盘只有8G，编译过程中就报了磁盘不足，刚刚发现这个新服务器的数据盘没有挂载。</p>
<p><strong>挂在部分：</strong></p>
<p>1、查看数据盘<br />
在没有分区和格式化数据盘之前，使用 “df –h”命令，是无法看到数据盘的，可以使用“fdisk -l”命令查看。如下图：<br />
<img loading="lazy" decoding="async" src="http://www.mudbest.com/wp-content/uploads/2014/08/1-610x268.png" alt="1" width="610" height="268" class="alignnone size-medium wp-image-2101" srcset="https://www.mudbest.com/wp-content/uploads/2014/08/1-610x268.png 610w, https://www.mudbest.com/wp-content/uploads/2014/08/1.png 627w" sizes="auto, (max-width: 610px) 100vw, 610px" /><br />
友情提示：若您执行fdisk -l命令，发现没有 /dev/xvdb 标明您的云服务无数据盘，那么您无需进行挂载，此时该教程对您不适用</p>
<p>2、 对数据盘进行分区<br />
<img loading="lazy" decoding="async" src="http://www.mudbest.com/wp-content/uploads/2014/08/2-580x430.png" alt="2" width="580" height="430" class="alignnone size-medium wp-image-2102" srcset="https://www.mudbest.com/wp-content/uploads/2014/08/2-580x430.png 580w, https://www.mudbest.com/wp-content/uploads/2014/08/2.png 672w" sizes="auto, (max-width: 580px) 100vw, 580px" /><br />
执行“fdisk /dev/xvdb”命令，对数据盘进行分区；根据提示，依次输入“n”，“p”“1”，两次回车，“wq”，分区就开始了，很快就会完成。</p>
<p>3、 查看新的分区<br />
使用“fdisk -l”命令可以看到，新的分区xvdb1已经建立完成了。<br />
<img loading="lazy" decoding="async" src="http://www.mudbest.com/wp-content/uploads/2014/08/3-610x262.png" alt="3" width="610" height="262" class="alignnone size-medium wp-image-2103" srcset="https://www.mudbest.com/wp-content/uploads/2014/08/3-610x262.png 610w, https://www.mudbest.com/wp-content/uploads/2014/08/3.png 614w" sizes="auto, (max-width: 610px) 100vw, 610px" /></p>
<p>4、格式化新分区<br />
使用“mkfs.ext3 /dev/xvdb1”命令对新分区进行格式化，格式化的时间根据硬盘大小有所不同。<br />
<img loading="lazy" decoding="async" src="http://www.mudbest.com/wp-content/uploads/2014/08/4-610x350.png" alt="4" width="610" height="350" class="alignnone size-medium wp-image-2104" srcset="https://www.mudbest.com/wp-content/uploads/2014/08/4-610x350.png 610w, https://www.mudbest.com/wp-content/uploads/2014/08/4.png 643w" sizes="auto, (max-width: 610px) 100vw, 610px" /></p>
<p>5、添加分区信息</p>
<p>使用“echo &#8216;/dev/xvdb1 /mnt ext3 defaults 0 0&#8217; >> /etc/fstab”命令写入新分区信息。<br />
然后使用“cat /etc/fstab”命令查看，出现以下信息就表示写入成功。<br />
<img loading="lazy" decoding="async" src="http://www.mudbest.com/wp-content/uploads/2014/08/5-610x129.png" alt="5" width="610" height="129" class="alignnone size-medium wp-image-2105" srcset="https://www.mudbest.com/wp-content/uploads/2014/08/5-610x129.png 610w, https://www.mudbest.com/wp-content/uploads/2014/08/5.png 624w" sizes="auto, (max-width: 610px) 100vw, 610px" /></p>
<p>6、挂载新分区<br />
使用“mount -a”命令挂载新分区，然后用“df -h”命令查看，出现以下信息就说明挂载成功，可以开始使用新的分区了。<br />
<img loading="lazy" decoding="async" src="http://www.mudbest.com/wp-content/uploads/2014/08/6-610x113.png" alt="6" width="610" height="113" class="alignnone size-medium wp-image-2106" srcset="https://www.mudbest.com/wp-content/uploads/2014/08/6-610x113.png 610w, https://www.mudbest.com/wp-content/uploads/2014/08/6.png 624w" sizes="auto, (max-width: 610px) 100vw, 610px" /></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.mudbest.com/centos%e5%8d%87%e7%ba%a7gcc4-4-7%e5%8d%87%e7%ba%a7gcc4-8%e6%89%8b%e8%ae%b0/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>CentOS下的Redis2.8.9编译安装以及相关配置</title>
		<link>https://www.mudbest.com/centos%e4%b8%8b%e7%9a%84redis2-8-9%e7%bc%96%e8%af%91%e5%ae%89%e8%a3%85%e4%bb%a5%e5%8f%8a%e7%9b%b8%e5%85%b3%e9%85%8d%e7%bd%ae/</link>
		
		<dc:creator><![CDATA[hkshadow]]></dc:creator>
		<pubDate>Tue, 06 May 2014 05:19:38 +0000</pubDate>
				<category><![CDATA[分享]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[redis安装]]></category>
		<category><![CDATA[缓存]]></category>
		<guid isPermaLink="false">http://www.mudbest.com/?p=2060</guid>

					<description><![CDATA[前言：Redis 是一个开源、支持网络、基于内存、键值对存储数据库，使用 ANSI C 编写。其开发由 VMw ... <a title="CentOS下的Redis2.8.9编译安装以及相关配置" class="read-more" href="https://www.mudbest.com/centos%e4%b8%8b%e7%9a%84redis2-8-9%e7%bc%96%e8%af%91%e5%ae%89%e8%a3%85%e4%bb%a5%e5%8f%8a%e7%9b%b8%e5%85%b3%e9%85%8d%e7%bd%ae/" aria-label="阅读 CentOS下的Redis2.8.9编译安装以及相关配置">阅读更多</a>]]></description>
										<content:encoded><![CDATA[<p>前言：Redis 是一个开源、支持网络、基于内存、键值对存储数据库，使用 ANSI C 编写。其开发由 VMware 主持。根据月度排行网站 DB-Engines.com 的数据显示，Redis 是最流行的键值对存储数据库。</p>
<p><strong>一、开启6379端口</strong><span id="more-2060"></span></p>
<pre class="brush: bash; title: ; notranslate">
vi /etc/sysconfig/iptables   #编辑防火墙配置文件 
</pre>
<p>-A INPUT -m state &#8211;state NEW -m tcp -p tcp &#8211;dport 6379 -j ACCEPT（允许6379端口通过防火墙）    </p>
<pre class="brush: bash; title: ; notranslate"> 
#特别提示：很多网友把这两条规则添加到防火墙配置的最后一行，导致防火墙启动失败
#正确的应该是添加到默认的22端口这条规则的下面，添加好之后防火墙规则如下所示：
#########################################################    
# Firewall configuration written by system-config-firewall    
# Manual customization of this file is not recommended.    
*filter    
:INPUT ACCEPT &#x5B;0:0]    
:FORWARD ACCEPT &#x5B;0:0]    
:OUTPUT ACCEPT &#x5B;0:0]    
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT    
-A INPUT -p icmp -j ACCEPT    
-A INPUT -i lo -j ACCEPT    
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT    
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT    
-A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT    
-A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT    
-A INPUT -j REJECT --reject-with icmp-host-prohibited    
-A FORWARD -j REJECT --reject-with icmp-host-prohibited    
COMMIT    
#########################################################    
/etc/init.d/iptables restart  #最后重启防火墙使配置生效 
</pre>
<p><strong>二、关闭SELINUX</strong></p>
<pre class="brush: bash; title: ; notranslate">
vim /etc/selinux/config  #编辑
#SELINUX=enforcing       #注释掉 
#SELINUXTYPE=targeted    #注释掉 
SELINUX=disabled         #增加 
:wq #保存退出
shutdown -r now   #重启系统
</pre>
<p><strong>三、系统约定</strong><br />
源码包编译安装位置：/usr/local/软件包名字<br />
源码包编译安装位置：/usr/local/软件包名字</p>
<p><strong>四、源码包下载</strong><br />
http://download.redis.io/releases/redis-2.8.9.tar.gz (最新稳定版本)</p>
<p><a href="http://www.mudbest.com/centos%e4%b8%8b%e7%9a%84redis2-8-9%e7%bc%96%e8%af%91%e5%ae%89%e8%a3%85%e4%bb%a5%e5%8f%8a%e7%9b%b8%e5%85%b3%e9%85%8d%e7%bd%ae/redis-2-8-9-tar/" rel="attachment wp-att-2066" target="_blank">redis-2.8.9.tar</a></p>
<p><strong>五、编译安装</strong></p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local
tar zxvf redis-2.8.9.tar.gz
rm redis-2.8.9.tar.gz
y
cd redis-2.8.9
make #编译 
</pre>
<p>make命令已经包含了redis安装过程，执行完成后，会在src目录下生成5个可执行文件，分别是redis-server、redis-cli、redis-benchmark、redis-check-aof、redis-check-dump，它们的作用如下：<br />
redis-server：Redis服务器的daemon启动程序<br />
redis-cli：Redis命令行操作工具。当然，你也可以用telnet根据其纯文本协议来操作<br />
redis-benchmark：Redis性能测试工具，测试Redis在你的系统及你的配置下的读写性能<br />
redis-check-aof：更新日志检查<br />
redis-check-dump：用于本地数据库检查</p>
<pre class="brush: bash; title: ; notranslate">
mkdir /etc/redis
cp redis.conf /etc/redis/redis.conf
mkdir /data/redis #创建redis数据存放位置
</pre>
<p>1. redis配置文件部分说明</p>
<pre class="brush: plain; title: ; notranslate">
#是否作为守护进程运行

daemonize yes

#如以后台进程运行，则需指定一个pid，默认为/var/run/redis.pid

pidfile redis.pid

#绑定主机IP，默认值为127.0.0.1

#bind 127.0.0.1

#Redis默认监听端口

port 6379

#客户端闲置多少秒后，断开连接，默认为300（秒）

timeout 300

#日志记录等级，有4个可选值，debug，verbose（默认值），notice，warning

loglevel verbose

#指定日志输出的文件名，默认值为stdout，也可设为/dev/null屏蔽日志

logfile stdout

#可用数据库数，默认值为16，默认数据库为0

databases 16

#保存数据到disk的策略

#当有一条Keys数据被改变是，900秒刷新到disk一次

save 900 1

#当有10条Keys数据被改变时，300秒刷新到disk一次

save 300 10

#当有1w条keys数据被改变时，60秒刷新到disk一次

save 60 10000

#当dump .rdb数据库的时候是否压缩数据对象

rdbcompression yes

#本地数据库文件名，默认值为dump.rdb

dbfilename dump.rdb

#本地数据库存放路径，默认值为 ./

dir /var/lib/redis/

########### Replication #####################

#Redis的复制配置

# slaveof &lt;masterip&gt; &lt;masterport&gt; 当本机为从服务时，设置主服务的IP及端口

# masterauth &lt;master-password&gt; 当本机为从服务时，设置主服务的连接密码

#连接密码

# requirepass foobared

#最大客户端连接数，默认不限制

# maxclients 128

#最大内存使用设置，达到最大内存设置后，Redis会先尝试清除已到期或即将到期的Key，当此方法处理后，任到达最大内存设置，将无法再进行写入操作。

# maxmemory &lt;bytes&gt;

#是否在每次更新操作后进行日志记录，如果不开启，可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面save条件来同步的，所以有的数据会在一段时间内只存在于内存中。默认值为no

appendonly no

#更新日志文件名，默认值为appendonly.aof

#appendfilename

#更新日志条件，共有3个可选值。no表示等操作系统进行数据缓存同步到磁盘，always表示每次更新操作后手动调用fsync()将数据写到磁盘，everysec表示每秒同步一次（默认值）。

# appendfsync always

appendfsync everysec

# appendfsync no

################ VIRTUAL MEMORY ###########

#是否开启VM功能，默认值为no

vm-enabled no

# vm-enabled yes

#虚拟内存文件路径，默认值为/tmp/redis.swap，不可多个Redis实例共享

vm-swap-file /tmp/redis.swap

#将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的 (Redis的索引数据就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0。

vm-max-memory 0

vm-page-size 32

vm-pages 134217728

vm-max-threads 4

############# ADVANCED CONFIG ###############

glueoutputbuf yes

hash-max-zipmap-entries 64

hash-max-zipmap-value 512

#是否重置Hash表

activerehashing yes
</pre>
<p>以下配置已修改好：</p>
<pre class="brush: plain; title: ; notranslate">
# Redis configuration file example

# Note on units: when memory size is needed, it is possible to specify
# it in the usual form of 1k 5GB 4M and so forth:
#
# 1k =&gt; 1000 bytes
# 1kb =&gt; 1024 bytes
# 1m =&gt; 1000000 bytes
# 1mb =&gt; 1024*1024 bytes
# 1g =&gt; 1000000000 bytes
# 1gb =&gt; 1024*1024*1024 bytes
#
# units are case insensitive so 1GB 1Gb 1gB are all the same.

################################## INCLUDES ###################################

# Include one or more other config files here.  This is useful if you
# have a standard template that goes to all Redis server but also need
# to customize a few per-server settings.  Include files can include
# other files, so use this wisely.
#
# Notice option &quot;include&quot; won't be rewritten by command &quot;CONFIG REWRITE&quot;
# from admin or Redis Sentinel. Since Redis always uses the last processed
# line as value of a configuration directive, you'd better put includes
# at the beginning of this file to avoid overwriting config change at runtime.
#
# If instead you are interested in using includes to override configuration
# options, it is better to use include as the last line.
#
# include /path/to/local.conf
# include /path/to/other.conf

################################ GENERAL  #####################################

# By default Redis does not run as a daemon. Use 'yes' if you need it.
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
daemonize yes

# When running daemonized, Redis writes a pid file in /var/run/redis.pid by
# default. You can specify a custom pid file location here.
pidfile /var/run/redis.pid

# Accept connections on the specified port, default is 6379.
# If port 0 is specified Redis will not listen on a TCP socket.
port 6379

# TCP listen() backlog.
#
# In high requests-per-second environments you need an high backlog in order
# to avoid slow clients connections issues. Note that the Linux kernel
# will silently truncate it to the value of /proc/sys/net/core/somaxconn so
# make sure to raise both the value of somaxconn and tcp_max_syn_backlog
# in order to get the desired effect.
tcp-backlog 511

# By default Redis listens for connections from all the network interfaces
# available on the server. It is possible to listen to just one or multiple
# interfaces using the &quot;bind&quot; configuration directive, followed by one or
# more IP addresses.
#
# Examples:
#
# bind 192.168.1.100 10.0.0.1
# bind 127.0.0.1

# Specify the path for the Unix socket that will be used to listen for
# incoming connections. There is no default, so Redis will not listen
# on a unix socket when not specified.
#
# unixsocket /tmp/redis.sock
# unixsocketperm 755

# Close the connection after a client is idle for N seconds (0 to disable)
timeout 300

# TCP keepalive.
#
# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence
# of communication. This is useful for two reasons:
#
# 1) Detect dead peers.
# 2) Take the connection alive from the point of view of network
#    equipment in the middle.
#
# On Linux, the specified value (in seconds) is the period used to send ACKs.
# Note that to close the connection the double of the time is needed.
# On other kernels the period depends on the kernel configuration.
#
# A reasonable value for this option is 60 seconds.
tcp-keepalive 0

# Specify the server verbosity level.
# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel verbose

# Specify the log file name. Also the empty string can be used to force
# Redis to log on the standard output. Note that if you use standard
# output for logging but daemonize, logs will be sent to /dev/null
logfile &quot;&quot;

# To enable logging to the system logger, just set 'syslog-enabled' to yes,
# and optionally update the other syslog parameters to suit your needs.
# syslog-enabled no

# Specify the syslog identity.
# syslog-ident redis

# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.
# syslog-facility local0

# Set the number of databases. The default database is DB 0, you can select
# a different one on a per-connection basis using SELECT &lt;dbid&gt; where
# dbid is a number between 0 and 'databases'-1
databases 16

################################ SNAPSHOTTING  ################################
#
# Save the DB on disk:
#
#   save &lt;seconds&gt; &lt;changes&gt;
#
#   Will save the DB if both the given number of seconds and the given
#   number of write operations against the DB occurred.
#
#   In the example below the behaviour will be to save:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed
#
#   Note: you can disable saving at all commenting all the &quot;save&quot; lines.
#
#   It is also possible to remove all the previously configured save
#   points by adding a save directive with a single empty string argument
#   like in the following example:
#
#   save &quot;&quot;

save 900 1
save 300 10
save 60 10000

# By default Redis will stop accepting writes if RDB snapshots are enabled
# (at least one save point) and the latest background save failed.
# This will make the user aware (in a hard way) that data is not persisting
# on disk properly, otherwise chances are that no one will notice and some
# disaster will happen.
#
# If the background saving process will start working again Redis will
# automatically allow writes again.
#
# However if you have setup your proper monitoring of the Redis server
# and persistence, you may want to disable this feature so that Redis will
# continue to work as usual even if there are problems with disk,
# permissions, and so forth.
stop-writes-on-bgsave-error yes

# Compress string objects using LZF when dump .rdb databases?
# For default that's set to 'yes' as it's almost always a win.
# If you want to save some CPU in the saving child set it to 'no' but
# the dataset will likely be bigger if you have compressible values or keys.
rdbcompression yes

# Since version 5 of RDB a CRC64 checksum is placed at the end of the file.
# This makes the format more resistant to corruption but there is a performance
# hit to pay (around 10%) when saving and loading RDB files, so you can disable it
# for maximum performances.
#
# RDB files created with checksum disabled have a checksum of zero that will
# tell the loading code to skip the check.
rdbchecksum yes

# The filename where to dump the DB
dbfilename dump.rdb

# The working directory.
#
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
# 
# The Append Only File will also be created inside this directory.
# 
# Note that you must specify a directory here, not a file name.
dir ./

################################# REPLICATION #################################

# Master-Slave replication. Use slaveof to make a Redis instance a copy of
# another Redis server. Note that the configuration is local to the slave
# so for example it is possible to configure the slave to save the DB with a
# different interval, or to listen to another port, and so on.
#
# slaveof &lt;masterip&gt; &lt;masterport&gt;

# If the master is password protected (using the &quot;requirepass&quot; configuration
# directive below) it is possible to tell the slave to authenticate before
# starting the replication synchronization process, otherwise the master will
# refuse the slave request.
#
# masterauth &lt;master-password&gt;

# When a slave loses its connection with the master, or when the replication
# is still in progress, the slave can act in two different ways:
#
# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will
#    still reply to client requests, possibly with out of date data, or the
#    data set may just be empty if this is the first synchronization.
#
# 2) if slave-serve-stale-data is set to 'no' the slave will reply with
#    an error &quot;SYNC with master in progress&quot; to all the kind of commands
#    but to INFO and SLAVEOF.
#
slave-serve-stale-data yes

# You can configure a slave instance to accept writes or not. Writing against
# a slave instance may be useful to store some ephemeral data (because data
# written on a slave will be easily deleted after resync with the master) but
# may also cause problems if clients are writing to it because of a
# misconfiguration.
#
# Since Redis 2.6 by default slaves are read-only.
#
# Note: read only slaves are not designed to be exposed to untrusted clients
# on the internet. It's just a protection layer against misuse of the instance.
# Still a read only slave exports by default all the administrative commands
# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve
# security of read only slaves using 'rename-command' to shadow all the
# administrative / dangerous commands.
slave-read-only yes

# Slaves send PINGs to server in a predefined interval. It's possible to change
# this interval with the repl_ping_slave_period option. The default value is 10
# seconds.
#
# repl-ping-slave-period 10

# The following option sets the replication timeout for:
#
# 1) Bulk transfer I/O during SYNC, from the point of view of slave.
# 2) Master timeout from the point of view of slaves (data, pings).
# 3) Slave timeout from the point of view of masters (REPLCONF ACK pings).
#
# It is important to make sure that this value is greater than the value
# specified for repl-ping-slave-period otherwise a timeout will be detected
# every time there is low traffic between the master and the slave.
#
# repl-timeout 60

# Disable TCP_NODELAY on the slave socket after SYNC?
#
# If you select &quot;yes&quot; Redis will use a smaller number of TCP packets and
# less bandwidth to send data to slaves. But this can add a delay for
# the data to appear on the slave side, up to 40 milliseconds with
# Linux kernels using a default configuration.
#
# If you select &quot;no&quot; the delay for data to appear on the slave side will
# be reduced but more bandwidth will be used for replication.
#
# By default we optimize for low latency, but in very high traffic conditions
# or when the master and slaves are many hops away, turning this to &quot;yes&quot; may
# be a good idea.
repl-disable-tcp-nodelay no

# Set the replication backlog size. The backlog is a buffer that accumulates
# slave data when slaves are disconnected for some time, so that when a slave
# wants to reconnect again, often a full resync is not needed, but a partial
# resync is enough, just passing the portion of data the slave missed while
# disconnected.
#
# The biggest the replication backlog, the longer the time the slave can be
# disconnected and later be able to perform a partial resynchronization.
#
# The backlog is only allocated once there is at least a slave connected.
#
# repl-backlog-size 1mb

# After a master has no longer connected slaves for some time, the backlog
# will be freed. The following option configures the amount of seconds that
# need to elapse, starting from the time the last slave disconnected, for
# the backlog buffer to be freed.
#
# A value of 0 means to never release the backlog.
#
# repl-backlog-ttl 3600

# The slave priority is an integer number published by Redis in the INFO output.
# It is used by Redis Sentinel in order to select a slave to promote into a
# master if the master is no longer working correctly.
#
# A slave with a low priority number is considered better for promotion, so
# for instance if there are three slaves with priority 10, 100, 25 Sentinel will
# pick the one with priority 10, that is the lowest.
#
# However a special priority of 0 marks the slave as not able to perform the
# role of master, so a slave with priority of 0 will never be selected by
# Redis Sentinel for promotion.
#
# By default the priority is 100.
slave-priority 100

# It is possible for a master to stop accepting writes if there are less than
# N slaves connected, having a lag less or equal than M seconds.
#
# The N slaves need to be in &quot;online&quot; state.
#
# The lag in seconds, that must be &lt;= the specified value, is calculated from
# the last ping received from the slave, that is usually sent every second.
#
# This option does not GUARANTEES that N replicas will accept the write, but
# will limit the window of exposure for lost writes in case not enough slaves
# are available, to the specified number of seconds.
#
# For example to require at least 3 slaves with a lag &lt;= 10 seconds use:
#
# min-slaves-to-write 3
# min-slaves-max-lag 10
#
# Setting one or the other to 0 disables the feature.
#
# By default min-slaves-to-write is set to 0 (feature disabled) and
# min-slaves-max-lag is set to 10.

################################## SECURITY ###################################

# Require clients to issue AUTH &lt;PASSWORD&gt; before processing any other
# commands.  This might be useful in environments in which you do not trust
# others with access to the host running redis-server.
#
# This should stay commented out for backward compatibility and because most
# people do not need auth (e.g. they run their own servers).
# 
# Warning: since Redis is pretty fast an outside user can try up to
# 150k passwords per second against a good box. This means that you should
# use a very strong password otherwise it will be very easy to break.
#
# requirepass foobared

# Command renaming.
#
# It is possible to change the name of dangerous commands in a shared
# environment. For instance the CONFIG command may be renamed into something
# hard to guess so that it will still be available for internal-use tools
# but not available for general clients.
#
# Example:
#
# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
#
# It is also possible to completely kill a command by renaming it into
# an empty string:
#
# rename-command CONFIG &quot;&quot;
#
# Please note that changing the name of commands that are logged into the
# AOF file or transmitted to slaves may cause problems.

################################### LIMITS ####################################

# Set the max number of connected clients at the same time. By default
# this limit is set to 10000 clients, however if the Redis server is not
# able to configure the process file limit to allow for the specified limit
# the max number of allowed clients is set to the current file limit
# minus 32 (as Redis reserves a few file descriptors for internal uses).
#
# Once the limit is reached Redis will close all the new connections sending
# an error 'max number of clients reached'.
#
# maxclients 10000

# Don't use more memory than the specified amount of bytes.
# When the memory limit is reached Redis will try to remove keys
# according to the eviction policy selected (see maxmemory-policy).
#
# If Redis can't remove keys according to the policy, or if the policy is
# set to 'noeviction', Redis will start to reply with errors to commands
# that would use more memory, like SET, LPUSH, and so on, and will continue
# to reply to read-only commands like GET.
#
# This option is usually useful when using Redis as an LRU cache, or to set
# a hard memory limit for an instance (using the 'noeviction' policy).
#
# WARNING: If you have slaves attached to an instance with maxmemory on,
# the size of the output buffers needed to feed the slaves are subtracted
# from the used memory count, so that network problems / resyncs will
# not trigger a loop where keys are evicted, and in turn the output
# buffer of slaves is full with DELs of keys evicted triggering the deletion
# of more keys, and so forth until the database is completely emptied.
#
# In short... if you have slaves attached it is suggested that you set a lower
# limit for maxmemory so that there is some free RAM on the system for slave
# output buffers (but this is not needed if the policy is 'noeviction').
#
# maxmemory &lt;bytes&gt;

# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
# 
# volatile-lru -&gt; remove the key with an expire set using an LRU algorithm
# allkeys-lru -&gt; remove any key accordingly to the LRU algorithm
# volatile-random -&gt; remove a random key with an expire set
# allkeys-random -&gt; remove a random key, any key
# volatile-ttl -&gt; remove the key with the nearest expire time (minor TTL)
# noeviction -&gt; don't expire at all, just return an error on write operations
# 
# Note: with any of the above policies, Redis will return an error on write
#       operations, when there are not suitable keys for eviction.
#
#       At the date of writing this commands are: set setnx setex append
#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
#       getset mset msetnx exec sort
#
# The default is:
#
# maxmemory-policy volatile-lru

# LRU and minimal TTL algorithms are not precise algorithms but approximated
# algorithms (in order to save memory), so you can select as well the sample
# size to check. For instance for default Redis will check three keys and
# pick the one that was used less recently, you can change the sample size
# using the following configuration directive.
#
# maxmemory-samples 3

############################## APPEND ONLY MODE ###############################

# By default Redis asynchronously dumps the dataset on disk. This mode is
# good enough in many applications, but an issue with the Redis process or
# a power outage may result into a few minutes of writes lost (depending on
# the configured save points).
#
# The Append Only File is an alternative persistence mode that provides
# much better durability. For instance using the default data fsync policy
# (see later in the config file) Redis can lose just one second of writes in a
# dramatic event like a server power outage, or a single write if something
# wrong with the Redis process itself happens, but the operating system is
# still running correctly.
#
# AOF and RDB persistence can be enabled at the same time without problems.
# If the AOF is enabled on startup Redis will load the AOF, that is the file
# with the better durability guarantees.
#
# Please check http://redis.io/topics/persistence for more information.

appendonly no

# The name of the append only file (default: &quot;appendonly.aof&quot;)

appendfilename &quot;appendonly.aof&quot;

# The fsync() call tells the Operating System to actually write data on disk
# instead to wait for more data in the output buffer. Some OS will really flush 
# data on disk, some other OS will just try to do it ASAP.
#
# Redis supports three different modes:
#
# no: don't fsync, just let the OS flush the data when it wants. Faster.
# always: fsync after every write to the append only log . Slow, Safest.
# everysec: fsync only one time every second. Compromise.
#
# The default is &quot;everysec&quot;, as that's usually the right compromise between
# speed and data safety. It's up to you to understand if you can relax this to
# &quot;no&quot; that will let the operating system flush the output buffer when
# it wants, for better performances (but if you can live with the idea of
# some data loss consider the default persistence mode that's snapshotting),
# or on the contrary, use &quot;always&quot; that's very slow but a bit safer than
# everysec.
#
# More details please check the following article:
# http://antirez.com/post/redis-persistence-demystified.html
#
# If unsure, use &quot;everysec&quot;.

# appendfsync always
appendfsync everysec
# appendfsync no

# When the AOF fsync policy is set to always or everysec, and a background
# saving process (a background save or AOF log background rewriting) is
# performing a lot of I/O against the disk, in some Linux configurations
# Redis may block too long on the fsync() call. Note that there is no fix for
# this currently, as even performing fsync in a different thread will block
# our synchronous write(2) call.
#
# In order to mitigate this problem it's possible to use the following option
# that will prevent fsync() from being called in the main process while a
# BGSAVE or BGREWRITEAOF is in progress.
#
# This means that while another child is saving, the durability of Redis is
# the same as &quot;appendfsync none&quot;. In practical terms, this means that it is
# possible to lose up to 30 seconds of log in the worst scenario (with the
# default Linux settings).
# 
# If you have latency problems turn this to &quot;yes&quot;. Otherwise leave it as
# &quot;no&quot; that is the safest pick from the point of view of durability.

no-appendfsync-on-rewrite no

# Automatic rewrite of the append only file.
# Redis is able to automatically rewrite the log file implicitly calling
# BGREWRITEAOF when the AOF log size grows by the specified percentage.
# 
# This is how it works: Redis remembers the size of the AOF file after the
# latest rewrite (if no rewrite has happened since the restart, the size of
# the AOF at startup is used).
#
# This base size is compared to the current size. If the current size is
# bigger than the specified percentage, the rewrite is triggered. Also
# you need to specify a minimal size for the AOF file to be rewritten, this
# is useful to avoid rewriting the AOF file even if the percentage increase
# is reached but it is still pretty small.
#
# Specify a percentage of zero in order to disable the automatic AOF
# rewrite feature.

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

################################ LUA SCRIPTING  ###############################

# Max execution time of a Lua script in milliseconds.
#
# If the maximum execution time is reached Redis will log that a script is
# still in execution after the maximum allowed time and will start to
# reply to queries with an error.
#
# When a long running script exceed the maximum execution time only the
# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be
# used to stop a script that did not yet called write commands. The second
# is the only way to shut down the server in the case a write commands was
# already issue by the script but the user don't want to wait for the natural
# termination of the script.
#
# Set it to 0 or a negative value for unlimited execution without warnings.
lua-time-limit 5000

################################## SLOW LOG ###################################

# The Redis Slow Log is a system to log queries that exceeded a specified
# execution time. The execution time does not include the I/O operations
# like talking with the client, sending the reply and so forth,
# but just the time needed to actually execute the command (this is the only
# stage of command execution where the thread is blocked and can not serve
# other requests in the meantime).
# 
# You can configure the slow log with two parameters: one tells Redis
# what is the execution time, in microseconds, to exceed in order for the
# command to get logged, and the other parameter is the length of the
# slow log. When a new command is logged the oldest one is removed from the
# queue of logged commands.

# The following time is expressed in microseconds, so 1000000 is equivalent
# to one second. Note that a negative number disables the slow log, while
# a value of zero forces the logging of every command.
slowlog-log-slower-than 10000

# There is no limit to this length. Just be aware that it will consume memory.
# You can reclaim memory used by the slow log with SLOWLOG RESET.
slowlog-max-len 128

############################# Event notification ##############################

# Redis can notify Pub/Sub clients about events happening in the key space.
# This feature is documented at http://redis.io/topics/keyspace-events
# 
# For instance if keyspace events notification is enabled, and a client
# performs a DEL operation on key &quot;foo&quot; stored in the Database 0, two
# messages will be published via Pub/Sub:
#
# PUBLISH __keyspace@0__:foo del
# PUBLISH __keyevent@0__:del foo
#
# It is possible to select the events that Redis will notify among a set
# of classes. Every class is identified by a single character:
#
#  K     Keyspace events, published with __keyspace@&lt;db&gt;__ prefix.
#  E     Keyevent events, published with __keyevent@&lt;db&gt;__ prefix.
#  g     Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...
#  $     String commands
#  l     List commands
#  s     Set commands
#  h     Hash commands
#  z     Sorted set commands
#  x     Expired events (events generated every time a key expires)
#  e     Evicted events (events generated when a key is evicted for maxmemory)
#  A     Alias for g$lshzxe, so that the &quot;AKE&quot; string means all the events.
#
#  The &quot;notify-keyspace-events&quot; takes as argument a string that is composed
#  by zero or multiple characters. The empty string means that notifications
#  are disabled at all.
#
#  Example: to enable list and generic events, from the point of view of the
#           event name, use:
#
#  notify-keyspace-events Elg
#
#  Example 2: to get the stream of the expired keys subscribing to channel
#             name __keyevent@0__:expired use:
#
#  notify-keyspace-events Ex
#
#  By default all notifications are disabled because most users don't need
#  this feature and the feature has some overhead. Note that if you don't
#  specify at least one of K or E, no events will be delivered.
notify-keyspace-events &quot;&quot;

############################### ADVANCED CONFIG ###############################

# Hashes are encoded using a memory efficient data structure when they have a
# small number of entries, and the biggest entry does not exceed a given
# threshold. These thresholds can be configured using the following directives.
hash-max-ziplist-entries 512
hash-max-ziplist-value 64

# Similarly to hashes, small lists are also encoded in a special way in order
# to save a lot of space. The special representation is only used when
# you are under the following limits:
list-max-ziplist-entries 512
list-max-ziplist-value 64

# Sets have a special encoding in just one case: when a set is composed
# of just strings that happens to be integers in radix 10 in the range
# of 64 bit signed integers.
# The following configuration setting sets the limit in the size of the
# set in order to use this special memory saving encoding.
set-max-intset-entries 512

# Similarly to hashes and lists, sorted sets are also specially encoded in
# order to save a lot of space. This encoding is only used when the length and
# elements of a sorted set are below the following limits:
zset-max-ziplist-entries 128
zset-max-ziplist-value 64

# HyperLogLog sparse representation bytes limit. The limit includes the
# 16 bytes header. When an HyperLogLog using the sparse representation crosses
# this limit, it is convereted into the dense representation.
#
# A value greater than 16000 is totally useless, since at that point the
# dense representation is more memory efficient.
# 
# The suggested value is ~ 3000 in order to have the benefits of
# the space efficient encoding without slowing down too much PFADD,
# which is O(N) with the sparse encoding. Thev value can be raised to
# ~ 10000 when CPU is not a concern, but space is, and the data set is
# composed of many HyperLogLogs with cardinality in the 0 - 15000 range.
hll-sparse-max-bytes 3000

# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in
# order to help rehashing the main Redis hash table (the one mapping top-level
# keys to values). The hash table implementation Redis uses (see dict.c)
# performs a lazy rehashing: the more operation you run into a hash table
# that is rehashing, the more rehashing &quot;steps&quot; are performed, so if the
# server is idle the rehashing is never complete and some more memory is used
# by the hash table.
# 
# The default is to use this millisecond 10 times every second in order to
# active rehashing the main dictionaries, freeing memory when possible.
#
# If unsure:
# use &quot;activerehashing no&quot; if you have hard latency requirements and it is
# not a good thing in your environment that Redis can reply form time to time
# to queries with 2 milliseconds delay.
#
# use &quot;activerehashing yes&quot; if you don't have such hard requirements but
# want to free memory asap when possible.
activerehashing yes

# The client output buffer limits can be used to force disconnection of clients
# that are not reading data from the server fast enough for some reason (a
# common reason is that a Pub/Sub client can't consume messages as fast as the
# publisher can produce them).
#
# The limit can be set differently for the three different classes of clients:
#
# normal -&gt; normal clients
# slave  -&gt; slave clients and MONITOR clients
# pubsub -&gt; clients subscribed to at least one pubsub channel or pattern
#
# The syntax of every client-output-buffer-limit directive is the following:
#
# client-output-buffer-limit &lt;class&gt; &lt;hard limit&gt; &lt;soft limit&gt; &lt;soft seconds&gt;
#
# A client is immediately disconnected once the hard limit is reached, or if
# the soft limit is reached and remains reached for the specified number of
# seconds (continuously).
# So for instance if the hard limit is 32 megabytes and the soft limit is
# 16 megabytes / 10 seconds, the client will get disconnected immediately
# if the size of the output buffers reach 32 megabytes, but will also get
# disconnected if the client reaches 16 megabytes and continuously overcomes
# the limit for 10 seconds.
#
# By default normal clients are not limited because they don't receive data
# without asking (in a push way), but just after a request, so only
# asynchronous clients may create a scenario where data is requested faster
# than it can read.
#
# Instead there is a default limit for pubsub and slave clients, since
# subscribers and slaves receive data in a push fashion.
#
# Both the hard or the soft limit can be disabled by setting them to zero.
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60

# Redis calls an internal function to perform many background tasks, like
# closing connections of clients in timeout, purging expired keys that are
# never requested, and so forth.
#
# Not all tasks are performed with the same frequency, but Redis checks for
# tasks to perform accordingly to the specified &quot;hz&quot; value.
#
# By default &quot;hz&quot; is set to 10. Raising the value will use more CPU when
# Redis is idle, but at the same time will make Redis more responsive when
# there are many keys expiring at the same time, and timeouts may be
# handled with more precision.
#
# The range is between 1 and 500, however a value over 100 is usually not
# a good idea. Most users should use the default of 10 and raise this up to
# 100 only in environments where very low latency is required.
hz 10

# When a child rewrites the AOF file, if the following option is enabled
# the file will be fsync-ed every 32 MB of data generated. This is useful
# in order to commit the file to the disk more incrementally and avoid
# big latency spikes.
aof-rewrite-incremental-fsync yes
</pre>
<p>注意：Redis官方文档对VM的使用提出了一些建议:</p>
<p>当你的key很小而value很大时,使用VM的效果会比较好.因为这样节约的内存比较大.<br />
当你的key不小时,可以考虑使用一些非常方法将很大的key变成很大的value,比如你可以考虑将key,value组合成一个新的value.<br />
最好使用linux ext3 等对稀疏文件支持比较好的文件系统保存你的swap文件.<br />
vm-max-threads这个参数,可以设置访问swap文件的线程数,设置最好不要超过机器的核数.如果设置为0,那么所有对swap文件的操作都是串行的.可能会造成比较长时间的延迟,但是对数据完整性有很好的保证。</p>
<p>2. 调整系统内核参数</p>
<p>如果内存情况比较紧张的话，需要设定内核参数：<br />
echo 1 > /proc/sys/vm/overcommit_memory</p>
<p>这里说一下这个配置的含义：/proc/sys/vm/overcommit_memory<br />
该文件指定了内核针对内存分配的策略，其值可以是0、1、2。<br />
0，表示内核将检查是否有足够的可用内存供应用进程使用；如果有足够的可用内存，内存申请允许；否则，内存申请失败，并把错误返回给应用进程。<br />
1，表示内核允许分配所有的物理内存，而不管当前的内存状态如何。<br />
2，表示内核允许分配超过所有物理内存和交换空间总和的内存<br />
Redis在dump数据的时候，会fork出一个子进程，理论上child进程所占用的内存和parent是一样的，比如parent占用的内存为 8G，这个时候也要同样分配8G的内存给child, 如果内存无法负担，往往会造成redis服务器的down机或者IO负载过高，效率下降。所以这里比较优化的内存分配策略应该设置为 1（表示内核允许分配所有的物理内存，而不管当前的内存状态如何）。</p>
<p><strong>六、运行 Redis</strong></p>
<p>1. 运行服务</p>
<pre class="brush: bash; title: ; notranslate">
redis-server /etc/redis/redis.conf
</pre>
<p>即可在后台启动redis服务，确认运行了之后，可以用redis-benchmark命令测试看看，还可以通过redis-cli命令实际操作一下，比如：</p>
<pre class="brush: bash; title: ; notranslate">
redis-cli set foo bar
OK
redis-cli get foo
bar
</pre>
<p>2. 关闭服务</p>
<pre class="brush: bash; title: ; notranslate">
redis-cli shutdown
</pre>
<p>如果端口变化可以指定端口:</p>
<pre class="brush: bash; title: ; notranslate">
redis-cli -p 6380 shutdown
</pre>
<p>3. 保存/备份<br />
数据备份可以通过定期备份该文件实现。<br />
因为redis是异步写入磁盘的，如果要让内存中的数据马上写入硬盘可以执行如下命令：<br />
redis-cli save 或者 redis-cli -p 6380 save（指定端口）<br />
注意，以上部署操作需要具备一定的权限，比如复制和设定内核参数等。<br />
执行redis-benchmark命令时也会将内存数据写入硬盘。</p>
<p>4. 同步机制<br />
redis实现的同步机制相对简单，缺少同步机制常见的check point和校验机制。<br />
在运行时，如果master -> slave同步请求转发被丢弃, slave将无法恢复该请求的相关信息，直到slave重启时从master全量加载数据时才能修复。因此，建议使用redis尽量利用其 key/value和value支持多种类型的特性，存储一些相对不重要的数据。</p>
<p><strong>六. 自启动</strong></p>
<pre class="brush: bash; title: ; notranslate">
vim /etc/init.d/redis
</pre>
<pre class="brush: bash; title: ; notranslate">
#!/bin/bash
#
# redis - this script starts and stops the redis-server daemon
#
# chkconfig:   - 80 12
# description:  Redis is a persistent key-value database
# processname: redis-server
# config:      /etc/redis/redis.conf
# pidfile:     /var/run/redis.pid

source /etc/init.d/functions

BIN=&quot;/usr/local/bin&quot;
CONFIG=&quot;/etc/redis/redis.conf&quot;
PIDFILE=&quot;/var/run/redis.pid&quot;


### Read configuration
&#x5B; -r &quot;$SYSCONFIG&quot; ] &amp;&amp; source &quot;$SYSCONFIG&quot;

RETVAL=0
prog=&quot;redis-server&quot;
desc=&quot;Redis Server&quot;

start() {

        if &#x5B; -e $PIDFILE ];then
             echo &quot;$desc already running....&quot;
             exit 1
        fi

        echo -n $&quot;Starting $desc: &quot;
        daemon $BIN/$prog $CONFIG

        RETVAL=$?
        echo
        &#x5B; $RETVAL -eq 0 ] &amp;&amp; touch /var/lock/subsys/$prog
        return $RETVAL
}

stop() {
        echo -n $&quot;Stop $desc: &quot;
        killproc $prog
        RETVAL=$?
        echo
        &#x5B; $RETVAL -eq 0 ] &amp;&amp; rm -f /var/lock/subsys/$prog $PIDFILE
        return $RETVAL
}

restart() {
    stop
    start
}

case &quot;$1&quot; in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        restart
        ;;
  condrestart)
        &#x5B; -e /var/lock/subsys/$prog ] &amp;&amp; restart
        RETVAL=$?
        ;;
  status)
        status $prog
        RETVAL=$?
        ;;
   *)
        echo $&quot;Usage: $0 {start|stop|restart|condrestart|status}&quot;
        RETVAL=1
esac

exit $RETVAL
</pre>
<p>用这个脚本管理之前，需要先配置下面的内核参数，否则Redis脚本在重启或停止redis时，将会报错，并且不能自动在停止服务前同步数据到磁盘上：</p>
<pre class="brush: bash; title: ; notranslate">
vi /etc/sysctl.conf
vm.overcommit_memory = 1
</pre>
<p>然后应用生效：</p>
<pre class="brush: bash; title: ; notranslate">
sysctl -p
</pre>
<pre class="brush: plain; title: ; notranslate">
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
error: &quot;net.bridge.bridge-nf-call-ip6tables&quot; is an unknown key
error: &quot;net.bridge.bridge-nf-call-iptables&quot; is an unknown key
error: &quot;net.bridge.bridge-nf-call-arptables&quot; is an unknown key
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
vm.overcommit_memory = 1
</pre>
<p>出现error执行以下2个命令即可：</p>
<pre class="brush: bash; title: ; notranslate">
modprobe bridge
lsmod|grep bridge
</pre>
<p>再次执行</p>
<pre class="brush: bash; title: ; notranslate">
sysctl -p
</pre>
<pre class="brush: plain; title: ; notranslate">
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
vm.overcommit_memory = 1
</pre>
<p>然后增加服务并开机自启动：</p>
<pre class="brush: bash; title: ; notranslate">
chmod 755 /etc/init.d/redis
chkconfig --add redis
chkconfig --level 345 redis on
chkconfig --list redis
</pre>
<p>启动测试：</p>
<pre class="brush: bash; title: ; notranslate">
/etc/init.d/redis start
</pre>
<pre class="brush: plain; title: ; notranslate">
Starting Redis Server: &#x5B;5279] 06 May 13:14:55.499 * Increased maximum number of open files to 10032 (it was originally set to 1024).
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 2.8.9 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in stand alone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 5279
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

&#x5B;5279] 06 May 13:14:55.501 # Server started, Redis version 2.8.9
&#x5B;5279] 06 May 13:14:55.501 * The server is now ready to accept connections on port 6379
&#x5B;5279 | signal handler] (1399353308) Received SIGTERM, scheduling shutdown...
&#x5B;5279] 06 May 13:15:08.925 # User requested shutdown...
&#x5B;5279] 06 May 13:15:08.925 * Saving the final RDB snapshot before exiting.
&#x5B;5279] 06 May 13:15:08.936 * DB saved on disk
&#x5B;5279] 06 May 13:15:08.936 # Redis is now ready to exit, bye bye...
                                                           &#x5B;确定]
</pre>
<p>至此已经完成了redis的配置以及自启动。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>VMware下Centos的lnmp编译安装</title>
		<link>https://www.mudbest.com/vmware%e4%b8%8bcentos%e7%9a%84lnmp%e7%bc%96%e8%be%91%e5%ae%89%e8%a3%85/</link>
		
		<dc:creator><![CDATA[hkshadow]]></dc:creator>
		<pubDate>Tue, 29 Apr 2014 04:36:07 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[Mysql]]></category>
		<category><![CDATA[lnmp]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[PHP]]></category>
		<guid isPermaLink="false">http://www.mudbest.com/?p=2043</guid>

					<description><![CDATA[VMware安装Centos就不说了，接下来是Centos的相关配置，如果Centos有防火墙的话，则需要配置 ... <a title="VMware下Centos的lnmp编译安装" class="read-more" href="https://www.mudbest.com/vmware%e4%b8%8bcentos%e7%9a%84lnmp%e7%bc%96%e8%be%91%e5%ae%89%e8%a3%85/" aria-label="阅读 VMware下Centos的lnmp编译安装">阅读更多</a>]]></description>
										<content:encoded><![CDATA[<p>VMware安装Centos就不说了，接下来是Centos的相关配置，如果Centos有防火墙的话，则需要配置防火墙，非Vm通用。</p>
<p><strong>一、开启80端口、3306端口</strong><span id="more-2043"></span></p>
<pre class="brush: bash; title: ; notranslate">
vi /etc/sysconfig/iptables   #编辑防火墙配置文件 
</pre>
<p>-A INPUT -m state &#8211;state NEW -m tcp -p tcp &#8211;dport 80 -j ACCEPT（允许80端口通过防火墙）<br />
-A INPUT -m state &#8211;state NEW -m tcp -p tcp &#8211;dport 3306 -j ACCEPT（允许3306端口通过防火墙）   </p>
<pre class="brush: bash; title: ; notranslate"> 
#特别提示：很多网友把这两条规则添加到防火墙配置的最后一行，导致防火墙启动失败
#正确的应该是添加到默认的22端口这条规则的下面，添加好之后防火墙规则如下所示：
#########################################################    
# Firewall configuration written by system-config-firewall    
# Manual customization of this file is not recommended.    
*filter    
:INPUT ACCEPT &#x5B;0:0]    
:FORWARD ACCEPT &#x5B;0:0]    
:OUTPUT ACCEPT &#x5B;0:0]    
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT    
-A INPUT -p icmp -j ACCEPT    
-A INPUT -i lo -j ACCEPT    
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT    
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT    
-A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT    
-A INPUT -j REJECT --reject-with icmp-host-prohibited    
-A FORWARD -j REJECT --reject-with icmp-host-prohibited    
COMMIT    
#########################################################    
/etc/init.d/iptables restart  #最后重启防火墙使配置生效 
</pre>
<p><strong>二、关闭SELINUX</strong></p>
<pre class="brush: bash; title: ; notranslate">
vim /etc/selinux/config  #编辑
#SELINUX=enforcing       #注释掉 
#SELINUXTYPE=targeted    #注释掉 
SELINUX=disabled         #增加 
:wq #保存退出
shutdown -r now   #重启系统
</pre>
<p><strong>三、系统约定</strong><br />
软件源代码包存放位置：/usr/local/src<br />
源码包编译安装位置：/usr/local/软件包名字</p>
<p><strong>四、源码包下载</strong><br />
1、pcre下载(支持nginx伪静态)<br />
ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.30.tar.gz</p>
<p>2、mysql下载<br />
http://cdn.mysql.com/Downloads/MySQL-5.6/mysql-5.6.17.tar.gz</p>
<p>3、libmcrypt-2.5.7<br />
ftp://mcrypt.hellug.gr/pub/crypto/mcrypt/attic/libmcrypt/libmcrypt-2.5.7.tar.gz</p>
<p>3.2、libiconv-1.9.2<br />
http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.9.2.tar.gz</p>
<p>3.3、zlib下载<br />
http://zlib.net/zlib-1.2.8.tar.gz</p>
<p>3.4、php下载<br />
http://ar2.php.net/distributions/php-5.5.11.tar.gz<br />
http://ar2.php.net/distributions/php-5.3.28.tar.gz</p>
<p>3.5、phpredis扩展下载<br />
https://github.com/nicolasff/phpredis/archive/master.zip</p>
<p>4、cmake下载(MySQL编译工具)<br />
http://www.cmake.org/files/v2.8/cmake-2.8.8.tar.gz</p>
<p>5、nginx下载(稳定版本)<br />
http://nginx.org/download/nginx-1.4.7.tar.gz</p>
<p>安装编译工具及库文件（使用CentOS yum命令安装）</p>
<pre class="brush: bash; title: ; notranslate">
yum install make apr* autoconf automake curl-devel gcc gcc-c++ zlib-devel openssl openssl-devel pcre-devel gd  kernel keyutils  patch  perl kernel-headers compat* mpfr cpp glibc libgomp libstdc++-devel ppl cloog-ppl keyutils-libs-devel libcom_err-devel libsepol-devel libselinux-devel krb5-devel zlib-devel libXpm* freetype libjpeg* libpng* php-common php-gd ncurses* libtool* libxml2 libxml2-devel patch freetype-devel
</pre>
<p><strong>五、开始编译安装</strong><br />
1、编译准备工作</p>
<pre class="brush: bash; title: ; notranslate">
yum groupinstall &quot;Development tools&quot;
</pre>
<p>1.1、安装cmake</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/src 
tar zxvf cmake-2.8.8.tar.gz 
cd cmake-2.8.8 
./configure make  #编译 
make install   #安装
</pre>
<p>2、安装MySQL</p>
<pre class="brush: bash; title: ; notranslate">
groupadd mysql  #添加mysql组    
useradd -g mysql mysql -s /bin/false  #创建用户mysql并加入到mysql组，不允许mysql用户直接登录系统    
mkdir -p /data/mysql  #创建MySQL数据库存放目录    
chown -R mysql:mysql /data/mysql   #设置MySQL数据库目录权限    
mkdir -p /usr/local/mysql #创建MySQL安装目录    
cd /usr/local/src    
tar zxvf mysql-5.5.25.tar.gz  #解压    
cd mysql-5.5.25    
cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql/ -DMYSQL_DATADIR=/data/mysql/ -DSYSCONFDIR=/etc/  #配置    
make #编译    
make install  #安装    
cd /usr/local/mysql    
cp ./support-files/my-huge.cnf  /etc/my.cnf   #拷贝配置文件（注意：如果/etc目录下面默认有一个my.cnf，直接覆盖即可）    
vim /etc/my.cnf   #编辑配置文件,在 &#x5B;mysqld] 部分增加下面一行    
datadir = /data/mysql  #添加MySQL数据库路径    
:wq!  #保存退出    
cd /usr/local/mysql/ #share 初始化的sql在这里面,下面一句命令默认读取share路径是./share/...
/usr/local/mysql/scripts/mysql_install_db --user=mysql --basedir=/usr/local/mysql/ --datadir=/data/mysql/ &amp; #生成mysql系统数据库,并定义数据data存放位置
cp ./support-files/mysql.server  /etc/rc.d/init.d/mysqld  #把Mysql加入系统启动    
chmod 755 /etc/init.d/mysqld   #增加执行权限    
chkconfig mysqld on  #设置开机启动    
vim /etc/rc.d/init.d/mysqld  #编辑    
basedir = /usr/local/mysql   #MySQL程序安装路径    
datadir = /data/mysql  #MySQl数据库存放目录    
service mysqld start  #启动    
vim /etc/profile   #把mysql服务加入系统环境变量：在最后添加下面这一行    
export PATH=$PATH:/usr/local/mysql/bin    
:wq! #保存退出    
</pre>
<p>下面这两行把myslq的库文件链接到系统默认的位置，在编译类似PHP等软件时可以不用指定mysql的库文件地址。 </p>
<pre class="brush: bash; title: ; notranslate">
ln -s /var/lib/mysql/mysql.sock /tmp/mysql.sock #创建快捷方式

ln -s /usr/local/mysql/lib /usr/lib/mysql    
ln -s /usr/local/mysql/include/mysql /usr/include/mysql    
shutdown -r now     #需要重启系统，等待系统重新启动之后继续在终端命令行下面操作    
mysql_secure_installation    #设置Mysql密码    

mysql --socket=/var/lib/mysql/mysql.sock #指定sock链接


</pre>
<p>根据提示按Y 回车（默认密码为空）<br />
然后输入2次密码<br />
继续按Y 回车，直到设置完成<br />
或者直接修改密码</p>
<pre class="brush: bash; title: ; notranslate">
/usr/local/mysql/bin/mysqladmin -u root -p password &quot;123456&quot; #修改密码    
service mysqld restart  #重启    
</pre>
<p>到此，mysql安装完成。</p>
<p>3、安装pcre</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/src    
mkdir /usr/local/pcre  #创建安装目录    
tar  zxvf pcre-8.30.tar.gz    
cd pcre-8.30    
./configure  --prefix=/usr/local/pcre  #配置    
make    
make install
</pre>
<p>4、安装nginx</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/src    
groupadd  www  #添加www组    
useradd -g  www www -s /bin/false  #创建nginx运行账户www并加入到www组，不允许www用户直接登录系统    
tar  zxvf nginx-1.2.0.tar.gz    
cd nginx-1.2.0    
./configure --prefix=/usr/local/nginx --without-http_memcached_module --user=www --group=www --with-http_stub_status_module --with-openssl=/usr/ --with-pcre=/usr/local/src/pcre-8.30    
#注意:--with-pcre=/usr/local/src/pcre-8.30指向的是源码包解压的路径，而不是安装的路径，否则会报错    
make    
make install    
/usr/local/nginx/sbin/nginx   #启动nginx    
</pre>
<pre class="brush: bash; title: ; notranslate">
vim /etc/rc.d/init.d/nginx    #设置nginx开启启动，编辑启动文件添加下面内容 
</pre>
<pre class="brush: bash; title: ; notranslate">
#################################################################    
#!/bin/bash    
# nginx Startup script for the Nginx HTTP Server    
# it is v.0.0.2 version.    
# chkconfig: - 85 15    
# description: Nginx is a high-performance web and proxy server.    
#              It has a lot of features, but it's not for everyone.    
# processname: nginx    
# pidfile: /var/run/nginx.pid    
# config: /usr/local/nginx/conf/nginx.conf    
nginxd=/usr/local/nginx/sbin/nginx    
nginx_config=/usr/local/nginx/conf/nginx.conf    
nginx_pid=/usr/local/nginx/logs/nginx.pid    
RETVAL=0    
prog=&quot;nginx&quot;    
# Source function library.    
.  /etc/rc.d/init.d/functions    
# Source networking configuration.    
.  /etc/sysconfig/network    
# Check that networking is up.    
&#x5B; ${NETWORKING} = &quot;no&quot; ]  exit 0    
&#x5B; -x $nginxd ] || exit 0    
# Start nginx daemons functions.    
start() {    
if &#x5B; -e $nginx_pid ];then    
  echo &quot;nginx already running....&quot;    
  exit 1    
fi    
  echo -n $&quot;Starting $prog: &quot;    
  daemon $nginxd -c ${nginx_config}    
  RETVAL=$?    
  echo    
  &#x5B; $RETVAL = 0 ]  touch /var/lock/subsys/nginx    
  return $RETVAL    
}    
# Stop nginx daemons functions.    
stop() {    
       echo -n $&quot;Stopping $prog: &quot;    
       killproc $nginxd    
       RETVAL=$?    
       echo    
       &#x5B; $RETVAL = 0 ]  rm -f /var/lock/subsys/nginx /usr/local/nginx/logs/nginx.pid    
}    
reload() {    
   echo -n $&quot;Reloading $prog: &quot;    
   #kill -HUP `cat ${nginx_pid}`    
   killproc $nginxd -HUP    
   RETVAL=$?    
   echo    
}    
# See how we were called.    
case &quot;$1&quot; in    
start)    
       start    
       ;;    
stop)    
       stop    
       ;;    
reload)    
       reload    
       ;;    
restart)    
       stop    
       start    
       ;;    
               
status)    
       status $prog    
       RETVAL=$?    
       ;;    
*)    
       echo $&quot;Usage: $prog {start|stop|restart|reload|status|help}&quot;    
       exit 1    
esac    
exit $RETVAL    
#################################################################  
:wq!  #保存退出 
</pre>
<pre class="brush: bash; title: ; notranslate">   
chmod 775  /etc/rc.d/init.d/nginx  #赋予文件执行权限    
chkconfig nginx on    #设置开机启动    
/etc/rc.d/init.d/nginx restart  #重启    
</pre>
<p>5.1、安装libmcrypt</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/src    
tar zxvf  libmcrypt-2.5.7.tar.gz   #解压    
cd  libmcrypt-2.5.7 #进入目录    
./configure    #配置    
make             #编译    
make install   #安装  
</pre>
<p>5.2、安装libiconv</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/src    
tar -zxvf libiconv-1.9.2.tar.gz   #解压    
cd  libiconv-1.9.2 #进入目录    
./configure --prefix=/usr/local/iconv    #配置    
make             #编译    
make install   #安装  

#重新编译php 增加编译参数--with-iconv=/usr/local/iconv 
</pre>
<p>5.3、安装zlib</p>
<pre class="brush: bash; title: ; notranslate">
yum info zlib
cd /usr/local/src    
tar -zxvf zlib-1.2.8.tar.gz   #解压    
cd  zlib-1.2.8 #进入目录    
./configure --prefix=/usr/local/zlib    #配置    
make             #编译    
make install   #安装  

#重新编译php 增加编译参数--with-iconv=/usr/local/iconv 
</pre>
<p>5.4、php5需要的devel 包：</p>
<pre class="brush: bash; title: ; notranslate">
yum install libxml2-devel gd-devel libmcrypt-devel libcurl-devel openssl-devel
</pre>
<p>6、安装php</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/src    
tar -zvxf php-5.3.13.tar.gz    
cd  php-5.3.13    
mkdir -p /usr/local/php5  #建立php安装目录    
#5.3配置    
./configure --prefix=/usr/local/php5 --with-config-file-path=/usr/local/php5/etc --with-mysql=/usr/local/mysql --with-mysqli=/usr/local/mysql/bin/mysql_config --with-mysql-sock=/tmp/mysql.sock --with-gd --with-iconv=/usr/local/iconv --with-zlib  --enable-xml --enable-magic-quotes --enable-safe-mode --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curlwrappers --enable-mbregex  --enable-fpm --enable-mbstring --enable-ftp --enable-gd-native-ttf --with-openssl --enable-pcntl --enable-sockets --with-xmlrpc --enable-zip --enable-soap --without-pear --with-gettext --enable-session --with-mcrypt --with-curl --with-jpeg-dir --with-freetype-dir    
#5.5配置    
./configure --prefix=/usr/local/php5 --with-config-file-path=/usr/local/php5/etc --with-mysql=/usr/local/mysql --with-mysqli=/usr/local/mysql/bin/mysql_config --with-mysql-sock=/tmp/mysql.sock --with-gd --with-iconv=/usr/local/iconv  --with-zlib --with-zlib-dir=/usr/local/zlib  --enable-xml --enable-magic-quotes --enable-safe-mode --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curlwrappers --enable-fpm --enable-mbstring --enable-ftp --enable-gd-native-ttf --with-openssl --enable-pcntl --enable-sockets --with-xmlrpc --enable-zip --enable-soap --without-pear --with-gettext --enable-session --with-mcrypt --with-curl --with-jpeg-dir --with-freetype-dir 

make   #编译    
make install    #安装    

ln -s -f /usr/local/php5/bin/phar.phar /usr/local/php5/bin/phar
</pre>
<pre class="brush: bash; title: ; notranslate">
cp  php.ini-production   /usr/local/php5/etc/php.ini  #复制php配置文件到安装目录 
</pre>
<pre class="brush: bash; title: ; notranslate">
rm -rf /etc/php.ini   #删除系统自带配置文件    
ln -s /usr/local/php5/etc/php.ini  /etc/php.ini    #添加软链接    
cp  /usr/local/php5/etc/php-fpm.conf.default   /usr/local/php5/etc/php-fpm.conf      #拷贝模板文件为php-fpm配置文件    
vim  /usr/local/php5/etc/php-fpm.conf  #编辑    
user = www    #设置php-fpm运行账号为www    
group = www   #设置php-fpm运行组为www    
pid = run/php-fpm.pid    #取消前面的分号    
cp /usr/local/src/php-5.3.13/sapi/fpm/init.d.php-fpm   /etc/rc.d/init.d/php-fpm  #设置 php-fpm开机启动，拷贝php-fpm到启动目录    
chmod +x /etc/rc.d/init.d/php-fpm  #添加执行权限    
chkconfig php-fpm on    #设置开机启动    
</pre>
<pre class="brush: bash; title: ; notranslate">
vim /usr/local/php5/etc/php.ini    #编辑配置文件  
</pre>
<p>找到：&#8221;disable_functions =&#8221;，修改为：</p>
<pre class="brush: bash; title: ; notranslate">
disable_functions = passthru,exec,system,chroot,scandir,chgrp,chown,shell_exec,proc_open,proc_get_status,ini_alter,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,stream_socket_server,escapeshellcmd,dll,popen,disk_free_space,checkdnsrr,checkdnsrr,getservbyname,getservbyport,disk_total_space,posix_ctermid,posix_get_last_error,posix_getcwd, posix_getegid,posix_geteuid,posix_getgid, posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid, posix_getppid,posix_getpwnam,posix_getpwuid, posix_getrlimit, posix_getsid,posix_getuid,posix_isatty, posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid, posix_setpgid,posix_setsid,posix_setuid,posix_strerror,posix_times,posix_ttyname,posix_uname     
</pre>
<p>#列出PHP可以禁用的函数，如果某些程序需要用到这个函数，可以删除，取消禁用。</p>
<p>找到：&#8221;;date.timezone =&#8221;，修改为：</p>
<pre class="brush: bash; title: ; notranslate">
date.timezone = PRC   #设置时区   
</pre>
<p>找到：&#8221;expose_php = On&#8221;，修改为：</p>
<pre class="brush: bash; title: ; notranslate">
修改为：expose_php = OFF  #禁止显示php版本的信息    
</pre>
<p>注意：在编译PHP的过程中可能会报UNDEFINED REFERENCE TO `LIBICONV_OPEN 无法编译PHP LIBICONV错误</p>
<p>php5.4 php-fpm重启方法</p>
<p>master进程可以理解以下信号<br />
INT, TERM 立刻终止<br />
QUIT 平滑终止<br />
USR1 重新打开日志文件<br />
USR2 平滑重载所有worker进程并重新载入配置和二进制模块</p>
<p>示例：<br />
php-fpm 启动：</p>
<pre class="brush: bash; title: ; notranslate">
/usr/local/php5/sbin/php-fpm
</pre>
<p>php-fpm 关闭：</p>
<pre class="brush: bash; title: ; notranslate">
kill -INT `cat /usr/local/php5/var/run/php-fpm.pid`
</pre>
<p>php-fpm 重启：</p>
<pre class="brush: bash; title: ; notranslate">
kill -USR2 `cat /usr/local/php5/var/run/php-fpm.pid`
</pre>
<p>查看php-fpm进程数：</p>
<pre class="brush: bash; title: ; notranslate">
ps aux | grep -c php-fpm
</pre>
<p>6.1、phpredis扩展安装</p>
<pre class="brush: bash; title: ; notranslate">
cd /usr/local/src/phpredis-master
/usr/local/php5/bin/phpize
./configure --with-php-config=/usr/local/php5/bin/php-config
make
make install
</pre>
<p>增加phpredis扩展</p>
<pre class="brush: bash; title: ; notranslate">
vim /usr/local/php5/etc/php.ini
</pre>
<p>在后面增加</p>
<pre class="brush: bash; title: ; notranslate">
extension=redis.so
</pre>
<p>测试</p>
<pre class="brush: php; title: ; notranslate">
$objRedis = new Redis();
$objRedis&gt;connect('127.0.0.1',6379)
$objRedis-&gt;set('test','ok');
echo $objRedis-&gt;get('test');
</pre>
<p>7、配置nginx支持php</p>
<pre class="brush: bash; title: ; notranslate">
vim /usr/local/nginx/conf/nginx.conf      #编辑配置文件     
</pre>
<pre class="brush: bash; title: ; notranslate">
user   www  www;          #首行user去掉注释,修改Nginx运行组为www www；必须与/usr/local/php5/etc/php-fpm.conf中的user,group配置相同，否则php运行出错    
index  index.php  index.html index.htm;    #添加index.php    
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000    
#    
location ~ \.php$ {    
   root           html;#此处和server下面root保持一致,默认为html    
   fastcgi_pass   127.0.0.1:9000;    
   fastcgi_index  index.php;    
   fastcgi_param  SCRIPT_FILENAME   /usr/local/nginx/html/$fastcgi_script_name;    
   include        fastcgi_params;          
</pre>
<p>注意：取消FastCGI server部分location的注释,并要注意fastcgi_param行的参数,改为/data/webroot/(此为网站根目录绝对路径)$fastcgi_script_name</p>
<pre class="brush: bash; title: ; notranslate">
/etc/init.d/nginx restart  #重启nginx  
</pre>
<p><a href="http://www.mudbest.com/vmware%e4%b8%8bcentos%e7%9a%84lnmp%e7%bc%96%e8%be%91%e5%ae%89%e8%a3%85/cmake-2-8-8-tar/" rel="attachment wp-att-2053">cmake-2.8.8.tar</a></p>
<p><a href="http://www.mudbest.com/vmware%e4%b8%8bcentos%e7%9a%84lnmp%e7%bc%96%e8%be%91%e5%ae%89%e8%a3%85/nginx-1-4-7-tar/" rel="attachment wp-att-2054">nginx-1.4.7.tar</a><br />
<a href="http://www.mudbest.com/vmware%e4%b8%8bcentos%e7%9a%84lnmp%e7%bc%96%e8%be%91%e5%ae%89%e8%a3%85/phpredis-master/" rel="attachment wp-att-2077">phpredis-master扩展</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>PHP下的Redis使用与总结</title>
		<link>https://www.mudbest.com/php%e4%b8%8b%e7%9a%84redis%e4%bd%bf%e7%94%a8%e4%b8%8e%e6%80%bb%e7%bb%93/</link>
		
		<dc:creator><![CDATA[hkshadow]]></dc:creator>
		<pubDate>Thu, 24 Apr 2014 04:21:44 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[分享]]></category>
		<category><![CDATA[redis]]></category>
		<category><![CDATA[缓存]]></category>
		<guid isPermaLink="false">http://www.mudbest.com/?p=2033</guid>

					<description><![CDATA[关于redis的介绍这里就不写了，百科就能查到，Redis是一个开源的使用ANSI C语言编写、支持网络、可基 ... <a title="PHP下的Redis使用与总结" class="read-more" href="https://www.mudbest.com/php%e4%b8%8b%e7%9a%84redis%e4%bd%bf%e7%94%a8%e4%b8%8e%e6%80%bb%e7%bb%93/" aria-label="阅读 PHP下的Redis使用与总结">阅读更多</a>]]></description>
										<content:encoded><![CDATA[<p>关于redis的介绍这里就不写了，百科就能查到，Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库，并提供多种语言的API。</p>
<p><strong>一、利用PHP自带的libredis扩展库进行连接操作</strong><br />
<span id="more-2033"></span><br />
例一：</p>
<pre class="brush: php; title: ; notranslate">
$libredis = Libredis ();
$connection = $libredis-&gt;get_connection ( &quot;127.0.0.1&quot; );
// set a key
$batch = $libredis-&gt;create_batch ();
$batch-&gt;set ( 'hello', 'world' );
$batch-&gt;execute ( $connection );
// now fetch the key
$batch = $libredis-&gt;create_batch ();
$batch-&gt;get ( 'hello' );
$batch-&gt;execute ( $connection );
while ( $batch-&gt;next_reply ( $reply_type, $reply_value, $reply_length ) ) {
	echo $reply_value, PHP_EOL;
}
</pre>
<p>例二：</p>
<pre class="brush: php; title: ; notranslate">
$libredis = Libredis ();
$connection1 = $libredis-&gt;get_connection ( &quot;127.0.0.1:6379&quot; );
$connection2 = $libredis-&gt;get_connection ( &quot;127.0.0.1:6380&quot; );
$batch1 = $libredis-&gt;create_batch ();
$batch1-&gt;set ( 'hello', 'world' ); // add a 'set' command to batch1
$batch2 = $libredis-&gt;create_batch ();
$batch2-&gt;set ( 'hello2', 'world2' );
$executor = $libredis-&gt;create_executor ();
$executor-&gt;add ( $connection1, $batch1 ); // associate connection1 with batch1
$executor-&gt;add ( $connection2, $batch2 ); // associate connection2 with batch2
                                       // execute all batches against their corresponding connections in parallel, with a
                                       // 500 ms timeout on the whole operation.
$executor-&gt;execute ( 500 );
</pre>
<p><strong>二、远程连接redis并给redis加锁</strong></p>
<p>用法：redis-cli [OPTIONS] [cmd [arg [arg &#8230;]]]<br />
-h <主机ip>，默认是127.0.0.1<br />
-p <端口>，默认是6379<br />
-a <密码>，如果redis加锁，需要传递密码<br />
&#8211;help，显示帮助信息</p>
<p>通过对rendis-cli用法介绍，在192.168.99.44上连接192.168.99.39应该很简单：</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@hkshadow001 ~]# redis-cli -h 192.168.99.39 -p 6379 
redis 192.168.1.103:6379&gt; 
</pre>
<p>在192.168.99.44上对192.168.99.39设置个个string值 user.1.name=hkshadow</p>
<pre class="brush: bash; title: ; notranslate">
redis 192.168.1.103:6379&gt; set user.1.name hkshadow 
OK 
</pre>
<p>看到ok，表明设置成功了。然后直接在192.168.99.39上登陆，看能不能获取到这个值。</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@hkshadow001 ~]# redis-cli 
redis 127.0.0.1:6379&gt; get user.1.name 
&quot;hkshadow&quot; 
</pre>
<p>查看链接的用户这里显示的是hkshadow，说明192.168.99.44已经链接上了192.168.99.36，一般在内网进行redis链接相对是安全的，但在外网时需要加一个验证才是比较安全的，在这里设置一个账号验证。</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@hkshadow001 ~]# vim /etc/redis/6379.conf 
</pre>
<p>找到# requirepass foobared，去掉前面的注释&#8221;#&#8221;，并把foobared 替换为你自己的密码：&#8221;hi,redis&#8221;。<br />
保存配置文件之后，重启redis服务。</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@hkshadow001 ~]# /etc/init.d/redis_6379 stop  
Stopping ...  
Waiting for Redis to shutdown ...  
Redis stopped  
&#x5B;root@hkshadow001 ~]# /etc/init.d/redis_6379 start  
Starting Redis server... 
</pre>
<p>这时候再使用192.168.99.44连接192.168.99.39并获取user.1.name的值，看看发生什么。</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@linuxidc001 ~]# redis-cli -h 192.168.1.103 -p 6379  
redis 192.168.1.103:6379&gt; get user.1.name  
(error) ERR operation not permitted  
redis 192.168.1.103:6379&gt; 
</pre>
<p>报错了，因为刚刚增加了一个验证信息，需要以下操作。</p>
<pre class="brush: bash; title: ; notranslate">
redis 192.168.99.39:6379&gt; quit  
&#x5B;root@linuxidc001 ~]# redis-cli -h 192.168.1.103 -p 6379 -a &quot;hi,redis&quot;  //这里的之前配置里改的值
redis 192.168.99.39:6379&gt; get user.1.name  
&quot;hkshadow&quot; 
</pre>
<p><strong>三、redis-cli的使用</strong></p>
<p>TYPE key — 用来获取某key的类型<br />
KEYS pattern — 匹配所有符合模式的key，比如KEYS * 就列出所有的key了，当然，复杂度O(n)<br />
RANDOMKEY &#8211; 返回随机的一个key<br />
RENAME oldkey newkey — 改变key的名字<br />
SELECT: ./redis-cli select 6<br />
# 表示切换到数据库6  </p>
<pre class="brush: bash; title: ; notranslate">
SET: ./redis-cli -n 0 set nid 123456789 
# 表示向数据库0中插入字符串key为nid，value值为123456789  
</pre>
<pre class="brush: bash; title: ; notranslate">
GET: ./redis-cli -n 0 get nid 或者 ./redis-cli get nid 
# 表示获取数据库为0，key为nid的字符串，在不指定数据编号的情况下，默认连接的是0数据库，所以可以省略-n参数 
</pre>
<pre class="brush: bash; title: ; notranslate">
GETSET: ./redis-cli getset nid 987654321 
# 表示返回指定key的原始值，并指定一个新值给他 
</pre>
<pre class="brush: bash; title: ; notranslate">
MGET: ./redis-cli mget nid uid … 
# 表示获取多个key的值 
</pre>
<pre class="brush: bash; title: ; notranslate">
SETNX: ./redis-cli setnx nnid 888888 
# 表示当一个指定的key不存在时，设置这个key指定的value，如果存在，则设置不成功 
</pre>
<pre class="brush: bash; title: ; notranslate">
SETEX: ./redis-cli setex nid 5 666666 
# 表示设置一个key指定的value保存5秒后失效，设置key/value的有效期 
</pre>
<pre class="brush: bash; title: ; notranslate">
MSET: ./redis-cli mset nid0001 &quot;0001&quot; nid0002 &quot;0002&quot; nid0003 &quot;0003&quot;
# 表示多键值对的数据保存 
</pre>
<pre class="brush: bash; title: ; notranslate">
INCR: ./redis-cli incr count 
# 表示对给定key的value进行递增(+1)的操作,当然value必须是一个integer 
</pre>
<pre class="brush: bash; title: ; notranslate">
INCRBY: ./redis-cli incrby count 5 
# 表示对给定key的value进行指定步长的递增操作 
</pre>
<pre class="brush: bash; title: ; notranslate">
DECR: ./redis-cli decr count 
# 表示对给定key的value进行递减(-1)的操作 
</pre>
<pre class="brush: bash; title: ; notranslate">
DECRBY: ./redis-cli decrby count 7 
# 表示对给定key的value进行指定步长的递减操作 
</pre>
<pre class="brush: bash; title: ; notranslate">
APPEND: ./redis-cli append content &quot;bad&quot;   或者  ./redis-cli append content &quot;good&quot;
# 表示追加一个value到指定的key中，如果key不存在，则新建key 
</pre>
<pre class="brush: bash; title: ; notranslate">
SUBSTR: ./redis-cli substr content 0 4 
# 表示返回指定key的value的部分字符串
</pre>
<p># 列表操作，精华<br />
RPUSH key string — 将某个值加入到一个key列表末尾<br />
LPUSH key string — 将某个值加入到一个key列表头部<br />
LLEN key — 列表长度<br />
LRANGE key start end — 返回列表中某个范围的值，相当于mysql里面的分页查询那样<br />
LTRIM key start end — 只保留列表中某个范围的值<br />
LINDEX key index — 获取列表中特定索引号的值，要注意是O(n)复杂度<br />
LSET key index value — 设置列表中某个位置的值<br />
RPOP key </p>
<p># 集合操作<br />
SADD key member — 增加元素<br />
SREM key member — 删除元素<br />
SCARD key — 返回集合大小<br />
SISMEMBER key member — 判断某个值是否在集合中<br />
SINTER key1 key2 &#8230; keyN — 获取多个集合的交集元素<br />
SMEMBERS key — 列出集合的所有元素 </p>
<p><strong>四、删除redis所有KEY</strong><br />
Redis 中有删除单个 Key 的指令 DEL，但好像没有批量删除 Key 的指令，不过我们可以借助 Linux 的 xargs 指令来完成这个动作。</p>
<pre class="brush: bash; title: ; notranslate">
redis-cli keys &quot;*&quot; | xargs redis-cli del
//如果redis-cli没有设置成系统变量，需要指定redis-cli的完整路径
//如：/opt/redis/redis-cli keys &quot;*&quot; | xargs /opt/redis/redis-cli del
</pre>
<p>如果要指定 Redis 数据库访问密码，使用下面的命令：</p>
<pre class="brush: bash; title: ; notranslate">
redis-cli -a password keys &quot;*&quot; | xargs redis-cli -a password del
</pre>
<p>如果要访问 Redis 中特定的数据库，使用下面的命令：</p>
<pre class="brush: bash; title: ; notranslate">
//下面的命令指定数据序号为0，即默认数据库
redis-cli -n 0 keys &quot;*&quot; | xargs redis-cli -n 0 del
</pre>
<p>删除所有Key，可以使用Redis的flushdb和flushall命令</p>
<pre class="brush: bash; title: ; notranslate">
//删除当前数据库中的所有Key
flushdb
//删除所有数据库中的key
flushall
</pre>
<p>注：keys 指令可以进行模糊匹配，但如果 Key 含空格，就匹配不到了，暂时还没发现好的解决办法。</p>
<p><strong>五、redis-cli 命令总结</strong><br />
Redis提供了丰富的命令（command）对数据库和各种数据类型进行操作，这些command可以在Linux终端使用。<br />
在编程时，比如使用Redis 的Java语言包，这些命令都有对应的方法。下面将Redis提供的命令做一总结。</p>
<p><em>1、连接操作相关的命令</em><br />
quit：关闭连接（connection）<br />
auth：简单密码认证</p>
<p><em>2、对value操作的命令</em><br />
exists(key)：确认一个key是否存在<br />
del(key)：删除一个key<br />
type(key)：返回值的类型<br />
keys(pattern)：返回满足给定pattern的所有key<br />
randomkey：随机返回key空间的一个key<br />
rename(oldname, newname)：将key由oldname重命名为newname，若newname存在则删除newname表示的key<br />
dbsize：返回当前数据库中key的数目<br />
expire：设定一个key的活动时间（s）<br />
ttl：获得一个key的活动时间<br />
select(index)：按索引查询<br />
move(key, dbindex)：将当前数据库中的key转移到有dbindex索引的数据库<br />
flushdb：删除当前选择数据库中的所有key<br />
flushall：删除所有数据库中的所有key</p>
<p><em>3、对String操作的命令</em><br />
set(key, value)：给数据库中名称为key的string赋予值value<br />
get(key)：返回数据库中名称为key的string的value<br />
getset(key, value)：给名称为key的string赋予上一次的value<br />
mget(key1, key2,…, key N)：返回库中多个string（它们的名称为key1，key2…）的value<br />
setnx(key, value)：如果不存在名称为key的string，则向库中添加string，名称为key，值为value<br />
setex(key, time, value)：向库中添加string（名称为key，值为value）同时，设定过期时间time<br />
mset(key1, value1, key2, value2,…key N, value N)：同时给多个string赋值，名称为key i的string赋值value i<br />
msetnx(key1, value1, key2, value2,…key N, value N)：如果所有名称为key i的string都不存在，则向库中添加string，<br />
名称key i赋值为value i<br />
incr(key)：名称为key的string增1操作<br />
incrby(key, integer)：名称为key的string增加integer<br />
decr(key)：名称为key的string减1操作<br />
decrby(key, integer)：名称为key的string减少integer<br />
append(key, value)：名称为key的string的值附加value<br />
substr(key, start, end)：返回名称为key的string的value的子串</p>
<p><em>4、对List操作的命令</em><br />
rpush(key, value)：在名称为key的list尾添加一个值为value的元素<br />
lpush(key, value)：在名称为key的list头添加一个值为value的 元素<br />
llen(key)：返回名称为key的list的长度<br />
lrange(key, start, end)：返回名称为key的list中start至end之间的元素（下标从0开始，下同）<br />
ltrim(key, start, end)：截取名称为key的list，保留start至end之间的元素<br />
lindex(key, index)：返回名称为key的list中index位置的元素<br />
lset(key, index, value)：给名称为key的list中index位置的元素赋值为value<br />
lrem(key, count, value)：删除count个名称为key的list中值为value的元素。<br />
count为0，删除所有值为value的元素，count>0从头至尾删除count个值为value的元素，count<0从尾到头删除|count|个值为value的元素。 
lpop(key)：返回并删除名称为key的list中的首元素 rpop(key)：返回并删除名称为key的list中的尾元素 
blpop(key1, key2,… key N, timeout)：lpop命令的block版本。
即当timeout为0时，若遇到名称为key i的list不存在或该list为空，则命令结束。
如果timeout>0，则遇到上述情况时，等待timeout秒，如果问题没有解决，则对keyi+1开始的list执行pop操作。<br />
brpop(key1, key2,… key N, timeout)：rpop的block版本。参考上一命令。<br />
rpoplpush(srckey, dstkey)：返回并删除名称为srckey的list的尾元素，并将该元素添加到名称为dstkey的list的头部</p>
<p><em>5、对Set操作的命令</em><br />
sadd(key, member)：向名称为key的set中添加元素member<br />
srem(key, member) ：删除名称为key的set中的元素member<br />
spop(key) ：随机返回并删除名称为key的set中一个元素<br />
smove(srckey, dstkey, member) ：将member元素从名称为srckey的集合移到名称为dstkey的集合<br />
scard(key) ：返回名称为key的set的基数<br />
sismember(key, member) ：测试member是否是名称为key的set的元素<br />
sinter(key1, key2,…key N) ：求交集<br />
sinterstore(dstkey, key1, key2,…key N) ：求交集并将交集保存到dstkey的集合<br />
sunion(key1, key2,…key N) ：求并集<br />
sunionstore(dstkey, key1, key2,…key N) ：求并集并将并集保存到dstkey的集合<br />
sdiff(key1, key2,…key N) ：求差集<br />
sdiffstore(dstkey, key1, key2,…key N) ：求差集并将差集保存到dstkey的集合<br />
smembers(key) ：返回名称为key的set的所有元素<br />
srandmember(key) ：随机返回名称为key的set的一个元素</p>
<p><em>6、对zset（sorted set）操作的命令</em><br />
zadd(key, score, member)：向名称为key的zset中添加元素member，score用于排序。如果该元素已经存在，则根据score更新该元素的顺序。<br />
zrem(key, member) ：删除名称为key的zset中的元素member<br />
zincrby(key, increment, member) ：如果在名称为key的zset中已经存在元素member，则该元素的score增加increment；<br />
否则向集合中添加该元素，其score的值为increment<br />
zrank(key, member) ：返回名称为key的zset（元素已按score从小到大排序）中member元素的rank（即index，从0开始），<br />
若没有member元素，返回“nil”<br />
zrevrank(key, member) ：返回名称为key的zset（元素已按score从大到小排序）中member元素的rank（即index，从0开始），<br />
若没有member元素，返回“nil”<br />
zrange(key, start, end)：返回名称为key的zset（元素已按score从小到大排序）中的index从start到end的所有元素<br />
zrevrange(key, start, end)：返回名称为key的zset（元素已按score从大到小排序）中的index从start到end的所有元素<br />
zrangebyscore(key, min, max)：返回名称为key的zset中score >= min且score <= max的所有元素 
zcard(key)：返回名称为key的zset的基数 zscore(key, element)：返回名称为key的zset中元素element的
score zremrangebyrank(key, min, max)：删除名称为key的zset中rank >= min且rank <= max的所有元素 
zremrangebyscore(key, min, max) ：删除名称为key的zset中score >= min且score <= max的所有元素
zunionstore / zinterstore(dstkeyN, key1,…,keyN, WEIGHTS w1,…wN, AGGREGATE SUM|MIN|MAX)：对N个zset求并集和交集，
并将最后的集合保存在dstkeyN中。对于集合中每一个元素的score，在进行AGGREGATE运算前，都要乘以对于的WEIGHT参数。
如果没有提供WEIGHT，默认为1。默认的AGGREGATE是SUM，即结果集合中元素的score是所有集合对应元素进行SUM运算的值，而MIN和MAX是指，
结果集合中元素的score是所有集合对应元素中最小值和最大值。

<em>7、对Hash操作的命令</em><br />
hset(key, field, value)：向名称为key的hash中添加元素field<—>value<br />
hget(key, field)：返回名称为key的hash中field对应的value<br />
hmget(key, field1, …,field N)：返回名称为key的hash中field i对应的value<br />
hmset(key, field1, value1,…,field N, value N)：向名称为key的hash中添加元素field i<—>value i<br />
hincrby(key, field, integer)：将名称为key的hash中field的value增加integer<br />
hexists(key, field)：名称为key的hash中是否存在键为field的域<br />
hdel(key, field)：删除名称为key的hash中键为field的域<br />
hlen(key)：返回名称为key的hash中元素个数<br />
hkeys(key)：返回名称为key的hash中所有键<br />
hvals(key)：返回名称为key的hash中所有键对应的value<br />
hgetall(key)：返回名称为key的hash中所有的键（field）及其对应的value</p>
<p><em>8、持久化</em><br />
save：将数据同步保存到磁盘<br />
bgsave：将数据异步保存到磁盘<br />
lastsave：返回上次成功将数据保存到磁盘的Unix时戳<br />
shundown：将数据同步保存到磁盘，然后关闭服务</p>
<p><em>9、远程服务控制</em><br />
info：提供服务器的信息和统计<br />
monitor：实时转储收到的请求<br />
slaveof：改变复制策略设置<br />
config：在运行时配置Redis服务器</p>
<p>redis操作手册下载:<a href="http://www.mudbest.com/php%e4%b8%8b%e7%9a%84redis%e4%bd%bf%e7%94%a8%e4%b8%8e%e6%80%bb%e7%bb%93/php-redis%e4%b8%ad%e6%96%87%e5%b8%ae%e5%8a%a9%e6%89%8b%e5%86%8c/" rel="attachment wp-att-2036">php-redis中文帮助手册</a></p>
<p>相关文章：<br />
<a href="http://timyang.net/data/redis-misunderstanding/" title="Redis几个认识误区" target="_blank">Redis几个认识误区</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>rsync安装与使用细节</title>
		<link>https://www.mudbest.com/rsync%e5%ae%89%e8%a3%85%e4%b8%8e%e4%bd%bf%e7%94%a8%e7%bb%86%e8%8a%82/</link>
		
		<dc:creator><![CDATA[hkshadow]]></dc:creator>
		<pubDate>Fri, 28 Mar 2014 09:30:12 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[分享]]></category>
		<category><![CDATA[rsync]]></category>
		<category><![CDATA[同步]]></category>
		<guid isPermaLink="false">http://www.mudbest.com/?p=2028</guid>

					<description><![CDATA[老套的搬用一下rsync的介绍，rsync是Linux系统下的数据镜像备份工具，从软件的命名上就可以看出来了— ... <a title="rsync安装与使用细节" class="read-more" href="https://www.mudbest.com/rsync%e5%ae%89%e8%a3%85%e4%b8%8e%e4%bd%bf%e7%94%a8%e7%bb%86%e8%8a%82/" aria-label="阅读 rsync安装与使用细节">阅读更多</a>]]></description>
										<content:encoded><![CDATA[<p>老套的搬用一下rsync的介绍，rsync是Linux系统下的数据镜像备份工具，从软件的命名上就可以看出来了——remote sync。rsync支持大多数的类Unix系统，无论是Linux、Solaris还是BSD上都经过了良好的测试。它的特性如下： </p>
<p>1、可以镜像保存整个目录树和文件系统。<br />
2、可以很容易做到保持原来文件的权限、时间、软硬链接等等。 <span id="more-2028"></span><br />
3、无须特殊权限即可安装。<br />
4、优化的流程，文件传输效率高。<br />
5、可以使用rcp、ssh等方式来传输文件，当然也可以通过直接的socket连接。</p>
<p><strong>一、安装Rsync。</strong><br />
如果支持yum安装，直接使用：</p>
<pre class="brush: bash; title: ; notranslate">
yum install xinetd
</pre>
<p>如果是源码安装则到官方http://rsync.samba.org/下载source包即可，安装过程大致如下：</p>
<pre class="brush: bash; title: ; notranslate">
tar zxvf *
cd *
./configure
make
make install
#如果是已安装了RPM版的Rsync，并且要安装新版的Rsync，需要先删除Rsync 
#rpm -e rsync
</pre>
<p>Redhat会有一个包依赖rsync，可以使用rpm -e rsync &#8211;nodeps卸载。另外，RPM版的rsync带了一个服务端的启动脚本，/etc/xinetd.d/rsync可以保留，但是需要注意的是必须在主服务器和同步服务器上都安装rsync，其中主服务器上是以服务器模式运行rsync，而同步上则以客户端方式运行rsync。这样在主服务器上运行rsyn守护进程，在同步上用crond定时运行客户程序来同步主服务器上需要同步的内容。</p>
<p><strong>二、配置rsync服务器端</strong></p>
<p>rsync服务器的配置文件为/etc/rsyncd.conf，其控制认证、访问、日志记录等等。该文件是由一个或多个模块结构组成。一个模块定义以方括弧中的模块名开始，直到下一个模块定义开始或者文件结束，模块中包含格式为name=value的参数定义。每个模块其实就对应需要备份的一个目录树，比方说在我们的实例环境中，有三个目录树需要备份：/www/和/mirror/file0/和/mirror/file1/目录，那么就需要在配置文件中定义三个模块，分别对应三个目录树。配置文件是行为单位的，也就是每个新行都表示一个新的注释、模块定义或者参数赋值。</p>
<pre class="brush: bash; title: ; notranslate">
# default: off
# description: The rsync server is a good addition to an ftp server, as it \
#       allows crc checksumming etc.
service rsync
{
        disable = no
        socket_type     = stream
        wait            = no
        user            = root
        server          = /usr/bin/rsync
        server_args     = --daemon
        log_on_failure  += USERID
}
</pre>
<p>将disable 改为no，另外将配置成随系统启动：</p>
<pre class="brush: bash; title: ; notranslate">
chkconfig rsync on
</pre>
<p>重新启动：</p>
<pre class="brush: bash; title: ; notranslate">
service xinetd restart  
#重新加载配置
/etc/rc.d/init.d/xinetd reload  
</pre>
<p>查看进程是否在监听：</p>
<pre class="brush: bash; title: ; notranslate">
netstat -a | grep rsync
#或者
lsof -i :873
</pre>
<p>配置rsync账户相关：</p>
<pre class="brush: bash; title: ; notranslate">
#配置rsync密码文件，(名字随便写，只要和配置文件里的一致即可)，格式(一行一个用户) ：
vim /home/rsync.ps
hkshadow:hkshadow
#配置rsync密码文件权限 
chown root.root rsync.ps
#注意：该文件只能是root用户可读写的，注意，出于安全目的，这个文件的属性必需是只有属主可读，否则rsync将拒绝运行。 
chmod 600 rsync.ps
</pre>
<p>创建配置文件：</p>
<pre class="brush: bash; title: ; notranslate">
uid = nobody # 备份以什么身份进行，用户
ID gid = nobody # 备份以什么身份进行，组ID ，注意这个用户ID和组ID，如果要方便的话，可以设置成root，这样rsync几乎就可以读取任何文件和目录了，但是也带来安全隐患。建议设置成只能读取你要备份的目录和文件即可。 
use chroot = no  max connections = 0  #最大连接数，0代表没有限制  
#port = 873          #默认端口873  
pid file = /var/log/rsync/rsyncd.pid   #运行进程的ID写到哪里 
#lock file = /var/log/rsync/rsync.lock

log file = /var/log/rsync/rsyncd.log  #日志记录文件 
motd file = /var/log/rsync/rsyncd.motd  #欢迎消息 
strict modes =yes         #是否检查口令文件的权限 

&#x5B;txt]           # 指定认证的备份模块名  
path = /www/htdocs/pub/test/   # 需要备份的目录 
comment = BACKUP attachment           # 注释  
ignore errors              # 忽略一些无关的IO错误  
read only = false          # 设置为非只读，即可以传至服务器的相应目录。 
list = false                # 不允许列文件  
exclude = test/ test.php      #设置不同步的目录或文件用空格隔开 
hosts allow = 210.51.0.80     #允许连接服务器的主机IP地址，如果多个ip则用空格隔开 
hosts deny = 0.0.0.0/0.0.0.0         #禁止连接服务器的主机IP地址，也可为*，表示所有。 
auth users = msyn                     # 认证的用户名，如果没有这行，则表明是匿名 
secrets file = /home/rsync.ps      # 认证文件名，用来存放密码
</pre>
<p><strong>三、配置客户端(省略)</strong><br />
配置密码文件 (注：为了安全，设定密码档案的属性为：600。rsync.scrt的密码一定要和Rsync Server 密码设定案里的密码一样)</p>
<p>下一步是一个运行rsync的例子：</p>
<pre class="brush: bash; title: ; notranslate">
rsync -vzrltogp --progress --delete user@x.x.x.168::attachment  /usr/local/apache/htdocs/pub/html/ --password-file=/home/rsync.ps
</pre>
<p>上面这个命令行中-vzrtopg代表的意思是：<br />
-v表示verbose(详细)<br />
-z表示zip（压缩）<br />
-r表示recursive（递归目录）<br />
-topg是保持文件原有属性如o=owner(属主)、t=times(时间)、p=perms(权限)、g=group(组)的参数 -H表示保持硬连接<br />
-l：保留软链结  -u：表示只更新源文件比目标时间新的文件<br />
&#8211;progress是指显示出详细的进度情况<br />
&#8211;delete是指如果服务器端删除了这一文件，那么客户端也相应把文件删除，保持真正的一致。 user@x.x.x.168::attachment 是表示对服务器x.x.x.168中的attachment模块进行备份，登录帐号是user<br />
&#8211;password-file = /etc/rsync.scrt来指定密码文件，这里需要注意的是这份密码文件权限属性要设得只 有属主可读(权限为600)，属主为正在运行此命令的用户。<br />
-a:(-a, &#8211;archive equivalent to -rlptgoD)以archive模式操作，复制目录、符号连接在这里面</p>
<p>==========================================================================<br />
另外，可以创建一个脚本运行这个命令，并记录日志：</p>
<pre class="brush: bash; title: ; notranslate">
# cat /usr/local/bin/rsync.sh  
#!/bin/bash    
DATE=`date +%w`  
rsync -avzH --progress --delete inburst@192.168.168.52::inburst /home/quack/backup/$DATE --password-file=/etc/rsync.pass &gt; /var/log/rsync.$DATE   
</pre>
<p>修改/etc/crontab做好定时更新(配置文件 /etc/crontab)  </p>
<pre class="brush: bash; title: ; notranslate">
crontab -e  15 4 * * 6 root rsync.sh  
crontab -l    
//查看所有自定义任务 
/etc/init.d/crond restart    //重启动任务计划 

#crontab Crontab文件的格式： 
#第1列分钟1～59  
#第2列小时1～23（0表示子夜） 
#第3列日1～31  
#第4列月1～12  
#第5列星期0～6（0表示星期天）
</pre>
<p>扩展阅读：<br />
<strong>关于 rsync 中: 和 :: 及 rysnc 和 ssh 认证协议的区别</strong></p>
<p>（1）双冒号 “::”的用法：<br />
rsync 传输文件前需要登录认证，那么这个过程用到的协议有两种：ssh 和 rsync<br />
何时用ssh 协议呢？<br />
我们平时用的  rsync -av /SRC root@192.168.99.36:/DEST 就是默认用的 ssh 协议<br />
这种方式默认是省略了 -e ssh 的，与下面等价：</p>
<pre class="brush: bash; title: ; notranslate">
rsync -av /SRC -e ssh root@192.168.99.36:/DEST
</pre>
<p>当遇到要修改端口的时候，我们可以：</p>
<pre class="brush: bash; title: ; notranslate">
rsync -av /SRC -e &quot;ssh -p36000&quot; root@192.168.99.36:/DEST
</pre>
<p>何时用rysnc协议呢？</p>
<pre class="brush: bash; title: ; notranslate">
rsync -av /SRC rsync://root@192.168.99.36:36000/modual/DestPath
</pre>
<p>注意：这条语句显示的指明了使用rsync认证协议，port后的modual是rsync服务端配置文件rsyncd.conf<br />
里面配置的模块名，模块里面会包含一些用户名、密码、路径等认证信息。<br />
使用rsync认证，还有一种写法：</p>
<p>1<br />
rsync -av /SRC &#8211;port=36000 root@172.17.256.211::modual/DestPath<br />
注意：这种写法不需显示指定 rsync 协议，而是根据 :: 来识别的，端口自己用 &#8211;port 指定。<br />
而且这里 modual 前面没有 / 的。</p>
<p>总结： 双冒号:: 是用在 rsync 协议里面的，: 一般用在ssh协议里面，这两种用法各有千秋：<br />
rsync协议你需要在rsync服务端配置模块，这增加了运维工作量，但是安全，因为不需要对客户公开帐号密码。<br />
ssh协议方便，不需配置，拿到帐号密码即可开工，但是对客户是暴露的，有安全风险。<br />
还需要注意的是用rsync协议认证的时候，后面跟的是模块名，而不是路径，这点要注意。</p>
<p>（2）关于 rsync &#8211;port 的man文档如下：<br />
rsync 客户端 &#8211;port<br />
 &#8211;port=PORT<br />
              This  specifies  an alternate TCP port number to use rather than<br />
              the default of 873.  This is only needed if you  are  using  the<br />
              double-colon  (::) syntax to connect with an rsync daemon (since<br />
              the URL syntax has a way to specify the port as a  part  of  the<br />
              URL).<br />
rsync 服务端 &#8211;port<br />
 &#8211;port=PORT<br />
              This  specifies  an  alternate TCP port number for the daemon to<br />
              listen on rather than the default of 873.  See also  the  &#8220;port&#8221;<br />
              global option in the rsyncd.conf manpage.</p>
<p>（3）附一些参考文档：<br />
rsync实例用法及参数详解<br />
http://hi.baidu.com/leejun_2005/item/672c31d4c12a8b1b20e25041</p>
<p>rsync命令用法入门<br />
http://hi.baidu.com/leejun_2005/item/a04d17c4cf24547088ad9e7c</p>
<p>rsync 的核心算法<br />
http://hi.baidu.com/leejun_2005/item/11651fc379229f52bdef69b7</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>由于binlog未及时清理导致硬盘爆满无法启动mysql</title>
		<link>https://www.mudbest.com/%e7%94%b1%e4%ba%8ebinlog%e6%9c%aa%e5%8f%8a%e6%97%b6%e6%b8%85%e7%90%86%e5%af%bc%e8%87%b4%e7%a1%ac%e7%9b%98%e7%88%86%e6%bb%a1%e6%97%a0%e6%b3%95%e5%90%af%e5%8a%a8mysql/</link>
		
		<dc:creator><![CDATA[hkshadow]]></dc:creator>
		<pubDate>Sat, 08 Feb 2014 05:04:38 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[Mysql]]></category>
		<category><![CDATA[binlog]]></category>
		<guid isPermaLink="false">http://www.mudbest.com/?p=2017</guid>

					<description><![CDATA[这几天由于太忙了，7天没有观察服务器了，今天用手机打开网站发现报mysql.sock丢失的错误，刚开始以为是m ... <a title="由于binlog未及时清理导致硬盘爆满无法启动mysql" class="read-more" href="https://www.mudbest.com/%e7%94%b1%e4%ba%8ebinlog%e6%9c%aa%e5%8f%8a%e6%97%b6%e6%b8%85%e7%90%86%e5%af%bc%e8%87%b4%e7%a1%ac%e7%9b%98%e7%88%86%e6%bb%a1%e6%97%a0%e6%b3%95%e5%90%af%e5%8a%a8mysql/" aria-label="阅读 由于binlog未及时清理导致硬盘爆满无法启动mysql">阅读更多</a>]]></description>
										<content:encoded><![CDATA[<p>这几天由于太忙了，7天没有观察服务器了，今天用手机打开网站发现报mysql.sock丢失的错误，刚开始以为是my.ini修改的原因，用df一看，/dev/xvda1的占用已经100%了，这样的情况还能启动mysql就真的逆天了。这时候想到了用sql删除binlog，但是根本进不去控制台，连安全模式都启动不了，以下是具体操作。<span id="more-2017"></span></p>
<p>分配了20G的硬盘，活生生的被binlog吃完了。</p>
<pre class="brush: sql; title: ; notranslate">
tail -f /opt/server/mysql/var/slyar.err
</pre>
<p>看了一下Mysql的错误日志，意外状况出现……</p>
<pre class="brush: sql; title: ; notranslate">
Disk is full writing './mysql-bin.~rec~' (Errcode: 28). Waiting for someone to free space... (Expect up to 60 secs delay for server to continue after freeing disk space)
</pre>
<p>神奇的情况，居然是因为磁盘满了无法写入日志导致Mysql起不来。</p>
<pre class="brush: sql; title: ; notranslate">
root@hkshadow# df 
Filesystem 1K-blocks Used Available Use% Mounted on 
/dev/xvda1 20641404 20641404 0 100% / 
</pre>
<p>基本上就是被这些玩意占满了，查了一下Mysql手册发现这些东西也没啥用，直接删除(此操作最好在Mysql服务停止时进行，因为当前日志使用的话无法删除，而且有可能导致一些其它问题，不过用mysql>reset master命令可以直接清空日志)。</p>
<pre class="brush: sql; title: ; notranslate">/opt/server/mysql/var/
root@hkshadow# cd 
root@hkshadow# rm -f mysql-bin.*
</pre>
<p>如果一定要使用binlog又担心时间久了没及时清理的话，可以在my.ini里设置binlog过期时间。</p>
<pre class="brush: sql; title: ; notranslate">
expire_logs_days = 7
</pre>
<p>如果不需要binlog的话可以关闭掉，避免未来得及监控导致的系列问题。</p>
<pre class="brush: sql; title: ; notranslate">
vim /etc/my.cnf
</pre>
<p>注释掉下面2行</p>
<pre class="brush: sql; title: ; notranslate">
log-bin=mysql-bin
binlog_format=mixed
</pre>
<p>然后重启即可</p>
<pre class="brush: sql; title: ; notranslate">
/etc/init.d/mysqld restart
</pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>linux终止超时的进程</title>
		<link>https://www.mudbest.com/linux%e7%bb%88%e6%ad%a2%e8%b6%85%e6%97%b6%e7%9a%84%e8%bf%9b%e7%a8%8b/</link>
		
		<dc:creator><![CDATA[hkshadow]]></dc:creator>
		<pubDate>Thu, 30 Jan 2014 09:29:43 +0000</pubDate>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[kill]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[超时进程]]></category>
		<guid isPermaLink="false">http://www.mudbest.com/?p=2009</guid>

					<description><![CDATA[目前服务器数据接口调用的地方较多，虽然将超时控制的很好了，但依然还是有超时的脚本占了进程，由于作了-eq这样的 ... <a title="linux终止超时的进程" class="read-more" href="https://www.mudbest.com/linux%e7%bb%88%e6%ad%a2%e8%b6%85%e6%97%b6%e7%9a%84%e8%bf%9b%e7%a8%8b/" aria-label="阅读 linux终止超时的进程">阅读更多</a>]]></description>
										<content:encoded><![CDATA[<p>目前服务器数据接口调用的地方较多，虽然将超时控制的很好了，但依然还是有超时的脚本占了进程，由于作了-eq这样的判断进程数的方法，超时进程的导致无法开启新进程，根据进程的执行时间可以判断是否为超时进程，并kill掉即可解决问题。</p>
<p>shell：<br />
<span id="more-2009"></span></p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/bash
function show_elapsed_time()
{
    user_hz=$(getconf CLK_TCK) #mostly it's 100 on x86/x86_64
    pid=$1
    jiffies=$(cat /proc/$pid/stat | cut -d&quot; &quot; -f22)
    sys_uptime=$(cat /proc/uptime | cut -d&quot; &quot; -f1)
    last_time=$(( ${sys_uptime%.*} - $jiffies/$user_hz ))
    #echo &quot;the process $pid lasts for $last_time seconds.&quot;
    time_out=1800 #限制为 30 分钟
    if &#x5B; &quot;$last_time&quot; -ge &quot;$time_out&quot; ]
    then
        echo &quot;the process $pid lasts for $last_time seconds.&quot;
        kill -9 $pid
    fi
}
#pgrep php 用于返回进程名包含 php 字符的进程ID列表
for pid in `pgrep php`
do
    #echo 'It is '$pid  
    show_elapsed_time $pid

done
</pre>
<p>//匹配筛选</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/bash
function show_elapsed_time()
{
    user_hz=$(getconf CLK_TCK) #mostly it's 100 on x86/x86_64
    pid=$1
    jiffies=$(cat /proc/$pid/stat | cut -d&quot; &quot; -f22)
    sys_uptime=$(cat /proc/uptime | cut -d&quot; &quot; -f1)
    last_time=$(( ${sys_uptime%.*} - $jiffies/$user_hz ))
    #echo &quot;the process $pid lasts for $last_time seconds.&quot;
    time_out=180
    if &#x5B; &quot;$last_time&quot; -ge &quot;$time_out&quot; ]
    then
        echo &quot;the process $pid lasts for $last_time seconds.&quot;
        kill -9 $pid
    fi
}

#for pid in `pgrep php`
for pid in `ps -ef| grep a.php | awk '{print $2}'`
do
    echo 'It is '$pid  
    show_elapsed_time $pid

done
</pre>
<p>扩展阅读：<br />
<strong>Linux bash shell 逐行读取文本文件的三种方法</strong></p>
<p>方法一，指定换行符读取：</p>
<pre class="brush: bash; title: ; notranslate">
#! /bin/bash  
   
IFS=&quot;  
&quot;  
   
for LINE in `cat /etc/passwd`  
do  
        echo $LINE 
done
</pre>
<p>方法二，文件重定向给read处理：</p>
<pre class="brush: bash; title: ; notranslate">
#! /bin/bash  
   
cat /etc/passwd | while read LINE  
do
        echo $LINE 
done
</pre>
<p>方法三，用read读取文件重定向：</p>
<pre class="brush: bash; title: ; notranslate">
#! /bin/bash  
   
while read LINE
do
        echo $LINE 
done &lt; /etc/passwd
</pre>
<p><strong>Linux获取进程已经运行的时间</strong><br />
本来，ps本身也提供了选项来查询的，但是比较直观和形象（如 10:32这样的），不是用seconds为单位，并不方便在脚本中直接使用。ps中的关于进程时间的命令如下：</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@AY140122175316610bdcZ shell]# ps -p 4260 -o pid,start_time,etime,comm
  PID START     ELAPSED COMMAND
 4260 Apr18 16-08:57:25 gnome-session
</pre>
<p>其中第三列的16-08:57:25就是进程运行的时间，为：16天8小时57分25秒。<br />
根据一些/proc文件系统中的信息，查询进程运行时间脚本分享如下：</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/bash
function show_elapsed_time()
{
	user_hz=$(getconf CLK_TCK) #mostly it's 100 on x86/x86_64
	pid=$1
	jiffies=$(cat /proc/$pid/stat | cut -d&quot; &quot; -f22)
	sys_uptime=$(cat /proc/uptime | cut -d&quot; &quot; -f1)
	last_time=$(( ${sys_uptime%.*} - $jiffies/$user_hz ))
	echo &quot;the process $pid lasts for $last_time seconds.&quot;
}
 
if &#x5B; $# -ge 1 ];then
	for pid in $@
	do
		show_elapsed_time $pid
	done
fi
 
while read pid
do
	show_elapsed_time $pid
done
</pre>
<p>执行过程和结果如下：</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@AY140122175316610bdcZ shell]# ./get_process_time.sh 4260
the process #4260 lasts for 1415417 seconds.
</pre>
<p><strong>linux根据进程名查询PID值</strong></p>
<p>很多时候，我们都需要根据进程名查询进程PID值，笔者总结了多种方法解决：<br />
1、pidof命令<br />
用pidof指令很轻易的找到您所想要的程序内容<br />
范例二：仅列出关于 root 的所有程序开启的 socket 档案</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@AY140122175316610bdcZ shell]# lsof -u root -a -U
COMMAND     PID USER   FD   TYPE     DEVICE SIZE   NODE NAME
kmodule     793 root    4u  unix 0xd744b700        3549 socket
udevd       801 root    5u  unix 0xd744bb40        3561 socket
syslogd    1539 root    0u  unix 0xd75946e0        4870 /dev/log
</pre>
<p># 注意到那个 -a 吧！如果你分别输入 lsof -u root 及 lsof -U ，会有啥信息？<br />
# 使用 lsof -u root -U 及 lsof -u root -a -U ，呵呵！都不同啦！<br />
# -a 的用途就是在解决同时需要两个项目都成立时啊！ ^_^</p>
<p>范例三：请列出目前系统上面所有的被启动的周边设备</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@AY140122175316610bdcZ shell]# lsof +d /dev
COMMAND     PID    USER   FD   TYPE     DEVICE SIZE NODE NAME
init          1    root   10u  FIFO       0,13      1834 /dev/initctl
kmodule     793    root    2u   CHR        1,3      2135 /dev/null
kmodule     793    root    3u   CHR        5,1      2134 /dev/console
udevd       801    root    2u   CHR        1,3      2135 /dev/null
syslogd    1539    root    0u  unix 0xd75946e0      4870 /dev/log xinetd     1589    root    1r   CHR        1,3      2135 /dev/null
</pre>
<p>#看吧！因为设备都在 /dev 里面嘛！所以啰，使用搜寻目录即可啊！<br />
范例四：秀出属于 root 的 bash 这支程序所开启的档案</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@AY140122175316610bdcZ shell]# lsof -u root | grep bash
bash   26199 root  cwd   DIR   3,2   4096   159875 /root
bash   26199 root  rtd   DIR   3,1   4096        2 /
bash   26199 root  txt   REG   3,1 686520   294425 /bin/bash
bash   26199 root  mem   REG   3,1  83160    32932 /usr/lib/gconv/BIG5.so
bash   26199 root  mem   REG   3,1  46552   915764 /lib/libnss_files-2.3.5.so
#.....底下的数据就省略不写了.....
</pre>
<p>这个指令可以找出您想要知道的某个程序是否有启用哪些信息？ 例如上头提到的范例四的执行结果呢！</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@AY140122175316610bdcZ shell]# pidof &#x5B;-sx] program_name
</pre>
<p>参数：<br />
-s  ：仅列出一个 PID 而不列出所有的 PID<br />
-x  ：同时列出该 program name 可能的 PPID 那个程序的 PID<br />
范例：<br />
范例一：列出目前系统上面 init 以及 syslogd 这两个程序的 PID</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@AY140122175316610bdcZ shell]# pidof init syslogd
</pre>
<p>1 2546<br />
# 理论上，应该会有两个 PID 才对。上面的显示也是出现了两个 PID 喔。<br />
# 分别是 init 及 syslogd 这两支程序的 PID 啦。</p>
<p>范例二：找出 bash 即以 bash 为 PPID 的几个主要的 PID</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@AY140122175316610bdcZ shell]# pidof -x bash
2961 2959 338
</pre>
<p># 因为我的系统被我登入之后，我就会主动取得一个 bash 的程序，所以啰，<br />
# 很自然就会拥有一个 PID 啊。只要我再以底下的方式，就可以取得我所想要的 PID 内容。</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@AY140122175316610bdcZ shell]# ps aux | egrep '(2961|2959|338)'
dmtsai   338  0.0  0.1  6024 1536 pts/0    Ss   16:43   0:00 -bash
kiki    2961  0.0  0.1  6025 1526 pts/0    Ss   17:43   0:00 -bash
#.....以下省略......
</pre>
<p>很简单的用法吧，讲解的这个pidof 指令，并且配合 ps aux 与正规表示法， 就可以很轻易的找到您所想要的程序内容了呢。 </p>
<p>2、pgrep命令<br />
语 法</p>
<pre class="brush: bash; title: ; notranslate">
pgrep &#x5B;必要参数] &#x5B;选择参数]  &#x5B;程序]      功 能   pgrep 命令：可以依照进程ID来浏览程序
类似命令: ps  kill  grep  killall  less  top   
  
参数必要参数
-f 显示完整程序
-l 显示源代码
-n 显示新程序
-o 显示旧程序
-v 与条件不符合的程序
-x 与条件符合的程序

选择参数
-p&lt;进程号&gt; 列出父进程为用户指定进程的进程信息
-t&lt;终端&gt; 指定终端下的所有程序
-u&lt;用户&gt; 指定用户的程序
</pre>
<p>范例</p>
<p>范例1：显示指定终端相联系的程序</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@AY140122175316610bdcZ shell]# pgrep -t tty2
862
8236
8672
&#x5B;root@AY140122175316610bdcZ shell]#
</pre>
<p>范例2：显示与某字符串相关的命令</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@AY140122175316610bdcZ shell]# pgrep at //列出at字符串相关的程序
3
5
19
20
42
&#x5B;root@AY140122175316610bdcZ shell]#
</pre>
<p>范例3：列出父进程为init进程的所有进程</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@AY140122175316610bdcZ shell]# pgrep -P 1 //列出父进程为1的所有进程
314
317
672
&#x5B;root@AY140122175316610bdcZ shell]#
</pre>
<p>范例4： 反向选择</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@AY140122175316610bdcZ shell]# pgrep -v -P 1 //列出父进程不为1的进程
1
2
3
&#x5B;root@AY140122175316610bdcZ shell]#
</pre>
<p>范例5：显示指定用户进程</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;root@AY140122175316610bdcZ shell]# pgrep -u root
1
2
3
#显示结果省略
</pre>
<p>3、ps命令<br />
查找进程httpd的PID：</p>
<pre class="brush: bash; title: ; notranslate">
ps -ef | grep &quot;httpd&quot; | grep -v &quot;grep&quot; | awk '{print $2}' 
</pre>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
