Monthly Archives: 四月 2016

linux ubutun 配置邮件并发送附件

Ubuntu下使用最常用的mail功能,需要安装mailutils,
安装命令:sudo apt-get install mailutils  
使用带附件的功能,则还需要安装sharutils,

安装命令:sudo apt-get install sharutils;

 uuencode 附件名 附件名|mail -s test 65933962@qq.com

Magento的redis安装~~好网站好文章·~redis是个好东西

http://www.hinckleywebservices.co.uk/using-redis-cache-backend-and-session-storage-for-magento/、

Redis Cache Backend and Session Storage for Magento

Redis Cache can be used as both a backend cache and a session store for Magento e-Commerce Sites bringing significant speed improvements for your web store.

Probably the single biggest improvement you can make to a Magento installation is implementation of a fast cache backend for both backend cache files and session storage, there are many cache implementations you can choose from including APC & Memcache however for the purposes of this blog we will focus on using Redis Cache for both Sessions and Backend Cache file storage.

Please note the following article deals with Magento CE only and not Magento Enterprise Edition and was tested and based on Magento CE Version 1.9.1.1.

Redis Cache with Magento

Redis Backend and Session Storage Cache with Magento

Installing Redis Cache

The Redis Cache itself is simple to install on any LAMP server we have not included instructions here for installation of Redis Cache itself as full instructions are available on the Redis Website, and we suggest you use these as they will contain the latest information and documentation regarding the installation of the Redis Cache package on your specific server.

Also because Redis can be implemented in the cloud as seperate server or cloud instance as with Amazon’s AWS etc, we have included the IP address for LocalHost in all configuration files and examples, for cloud installs this would need to be modified to that of your Redis Server.

Implementing Redis Session Storage for Magento

Magento has by default a module installed for implementing session storage on Redis, however this module is disable by default and needs to be enabled prior to use, to enable the CM-RedisSession module within magento open the magento-install-dir/app/etc/modules/Cm_RedisSession.xml in a text editor and change the value of the <active> tag to true before saving.

Additionally you will need to modify your magento config file (magento-install-dir/app/etc/local.xml) to tell Magento which Redis database to use for sessions etc see below:

 <session_save>db</session_save>
 <redis_session>
 <host>127.0.0.1</host>
 <port>6379</port>
 <password></password>
 <timeout>2.5</timeout>
 <persistent>sess-db0</persistent>
 <db>0</db>
 <compression_threshold>2048</compression_threshold>
 <compression_lib>gzip</compression_lib> 
 <log_level>1</log_level>
 <max_concurrency>6</max_concurrency>
 <break_after_frontend>5</break_after_frontend>
 <break_after_adminhtml>30</break_after_adminhtml>
 <bot_lifetime>7200</bot_lifetime> 
 </redis_session>

You will notice we have highlighted the <db> tag in the above XML configuration for Redis, the reason for this is that you will need to ensure that if you are running multiple implementations of Magento on a single server then each implementation will need 2 seperate Redis databases (one for Sessions and one for the backend cache), If you do not configure each installation to use a seperate Redis database then there is a significant possibility that the cache will return incorrect results.

We also recommend implementing two Redis databases to split sessions from the main backend Magento cache in order to allow the backend cache to be flushed completely without destroying the session data, and vice versa.

There is a wealth of information on Cm_RedisSession configuration on GitHub , along with the latest version of the Cm_RedisSession module source code.

Once you have got Redis Sessions installed and configured it is possible to migrate the existing session from your disk or database sessions storage into your new Redis cache sessions database.

There are two procedures for migrating sessions, which one you use is down to which previous session storage method you were using.

The migration procedure for file based session storage is:

cd /path/to/magento/root 
touch maintenance.flag 
sleep 10 
wget https://raw2.github.com/colinmollenhour/Cm_RedisSession/master/migrateSessions.php 
php migrateSessions.php -y 
rm maintenance.flag

And for database session storage:

cd /path/to/magento/root 
touch maintenance.flag 
sleep 10 
wget https://raw2.github.com/colinmollenhour/Cm_RedisSession/master/migrateSessions_mysql_redis.php 
php migrateSessions_mysql_redis.php -y 
rm maintenance.flag

Once you have completed implementation of your Magento sessions on Redis, you can clear both the /var/sessions directory within your public_html folder and also the core_sessions table in your database, and both should remain empty.

Installing the Redis Cache Backend  for Magento

The backend Redis Cache for Magento is implemented in much the same way as the sessions cache however there is at time of writing no built in Magento module to support Redis Cache backend for Magento, however Cm_Cache_Backend_Redis is available via GitHub¬†and can be installed manually by following the simple instructions included with the module.

You will again need to modify the local.xml within your Magento installation, the following is an example of the cache entry you will need to add to the local.xml file

<cache>
  <backend>Cm_Cache_Backend_Redis</backend>
  <backend_options>
    <server>127.0.0.1</server>
    <port>6379</port>
    <persistent></persistent>
    <database>1</database>
    <password></password>
    <force_standalone>0</force_standalone>
    <connect_retries>1</connect_retries>
    <read_timeout>10</read_timeout>
    <automatic_cleaning_factor>0</automatic_cleaning_factor>
    <compress_data>1</compress_data>
    <compress_tags>1</compress_tags>
    <compress_threshold>20480</compress_threshold>
    <compression_lib>gzip</compression_lib> 
    <use_lua>0</use_lua>
  </backend_options>
</cache>

Again, we have highlighted the database number configuration option this will need to be set to a unique number on your server, to ensure that each implementation running on the server uses a totally seperate Redis database.

Once installed, you will need to flush the Magento Cache to force it to start using the new Redis cache immediately.

Monitoring and Managing the Redis Backend & Session Cache

As a quick check that redis is running and working you can you the following command via a SSH terminal command line to check that Redis is running and working.

> redis-cli MONITOROK
1434959408.731767 "MONITOR"
1434959408.745281 (db 11) "HGET" "zc:k:13e_Zend_LocaleC_en_GB_time_" "d"
1434959408.745838 (db 11) "HGET" "zc:k:13e_Zend_LocaleC_de_time_" "d"
1434959408.748487 (db 11) "HGET" "zc:k:13e_Zend_LocaleC_en_GB_currencynumber_" "d"
1434959408.748680 (db 11) "HGET" "zc:k:13e_Zend_LocaleL_en_GB_symbols_" "d"
1434959408.785205 (db 11) "HGET" "zc:k:13e_Zend_LocaleC_en_GB_time_" "d"
1434959408.785665 (db 11) "HGET" "zc:k:13e_Zend_LocaleC_de_time_" "d"
1434959408.788057 (db 11) "HGET" "zc:k:13e_Zend_LocaleC_en_GB_currencynumber_" "d"

When you issue this command on the SSH command line you will see all instructions that pass through the Redis cache, to exit the Redis monitor stream use ctrl-c to exit.

It is also possible to quickly and easily flush the Redis Cache database via the command line if needed via the following command.

> redis-cli FLUSHALL

Obviously this type of command line monitoring does not tell you a lot more than just that the Redis Cache is  running and accepting commands, what you really need to see is whats in the Redis Cache databases that we have created, for this we can use phpRedisAdmin which is available from GitHub.

phpRedisAdmin is simple to install and configure, with full installation instructions provided on the GitHub page, so we wont go into the installation here, however given we have been dealing with a multiple Redis Cache database install above, then I have included a sample config file below to assist you in setting up phpRedisAdmin once you have it installed.

'servers' => array(
array(
 'name' => 'Sessions',
 'host' => '127.0.0.1',
 'port' => 6379,
 'db' => 0, // Optional database number, see http://redis.io/commands/select
 'filter' => '*' // Show only parts of database for speed or security reasons
 ),
array(
 'name' => 'Backend',
 'host' => '127.0.0.1',
 'port' => 6379,
 'db' => 1, // Optional database number, see http://redis.io/commands/select
 'filter' => '*' // Show only parts of database for speed or security reasons
 )
),

Above is the servers section of the phpRedisAdmin includes/config.inc.php¬†file, this array in the config file controls which databases and servers you will see in the admin panel, the above file shows databases 0 & 1 (highlighted in red in the config) for the two databases we have configured.

We recommend that you install the phpRedisAdmin code on a sub domain or seperate management domain to that of your main site so that it is not accessible via your actual production website, and also that you password protect the installation either via .htaccess or via the inbuilt password authorisation procedure within phpRedisAdmin (this can be set in the config file).

Cleaning up the Magento Redis Cache Databases

As above if you need to clear the Redis Cache database quickly then you can issue a flush command via the SSH Command line

> redis-cli FLUSHALL

Or you can manually remove single keys via the phpRedisAdmin app discussed above, however it is also a good idea to run systematic maintenance on the Redis Cache database

In addition to the above manual methods of cleaning either all or parts of the Redis Cache you can also implement a little housekeeping via a cron job, there is a good example of this on the AtWix website with full details of a Scheduled Redis Cache Clean Up cron module for Magento, whilst this appears to be a good module for doing a total Redis Cache flush.

We would not 100% recommend the total cache flush¬†approach to cleaning the Redis Cache as it means the cache would need to be fully rebuilt after each flush causing a heavy server load during the initial build phase when the cache is totally empty, much better would be to flush the cache based on age and the TTL of the stored keys within Redis, the cm_redis_tools implementation on GitHub allows you to schedule cache cleaning based on clearing old keys, or matched tags etc. the cm_redis_tools script also allows you to use cron to schedule cleaning¬†on specific Redis databases.

Another option is to run a Magento garbage collection script via a cron job, to do this create the file ./shell/redisgarbage.php containing the following script.

<?php 

  count($argc) or die('<pre>:P</pre>');
  ini_set('memory_limit','1024M');
  set_time_limit(0);
  error_reporting(E_ALL | E_STRICT);
  require_once '../app/Mage.php';
  Mage::app()->getCache()->getBackend()->clean('old');

?>

And then add the following cron job to your server to execute the job at a timed interval in this case every four hours.

0 */4 * * */usr/bin/php /home/yourpath/public_html/shell/redisgarbage.php

If you want to have the script run silenty without any feebback from the cron manager then add the following to the end of the command

> /dev/null

We think the above information covers 99% of what you need to know regarding using Redis Cache with Magento CE, if you have any questions or require any clarification, then please comment below and we will do our best to answer any questions you may have.

APC安装

Alternative PHP Cache (APC) 是一个开放自由的PHP opcode 缓存。它的目标是提供一个自由、 开放,和健全的框架用于缓存和优化PHP的中间代码。
安装(centos5.5+nginx+php5.3):
wget http://pecl.php.net/get/APC-3.1.9.tgz
tar xzvf APC-3.1.9.tgz
cd APC-3.1.9
/usr/local/php/bin/phpize
./configure –enable-apc –enable-mmap –enable-apc-spinlocks –disable-apc-pthreadmutex –with-php-config=/usr/local/php/bin/php-config
make
make install
其中红色部分是php的目录
编译安装好后我们要加入到php.ini文件,directadmin的php.ini在/usr/local/php/etc,加入以下文字
extension = “apc.so” ;
;APC setting
apc.enabled = 1
apc.shm_segments = 1
apc.shm_size = 64M
apc.optimization = 1
apc.num_files_hint = 0
apc.ttl = 0
apc.gc_ttl = 3600
apc.cache_by_default = on
重启nginx和php-fpm

修改数据库密码后,全部表变成read only

       今天快下班,接到一个任务,修改密码,好容易的任务啊~~~直接修改后,发现~~数据库表全部变成read only~~~~吓死宝宝了,网站还在跑,同事们都在看~~~我这逼装大了~~~~~

个人想应该是数据表缓存的问题吧,FLUSH下不就好了吗·~~~哪知道还不行~~~~难道我flush有错误·~~~~经常胆战心惊的NNNNNNN秒后,才解决:

感觉是我修改密码时候,造成网站突然中断(原谅我的放荡不羁)~~~表锁了,因为数据表都是myisam类型,然后flush-talbes,还是不行~~~难道是修改密码的问题,然后flush privileges下权限表,重启mysql服务~~~~还是不行,~~大爷的,此时我已经冒汗了,去修改下mysql表权限~重启mysql服务~还是不行·~~~~

大爷的~~~再flush privileges ,再重启mysql服务·~~可以了~~~~~

    我本来想写一遍条理分明,逻辑紧凑的文章,普及大众的·~~~~原谅对于这种情况写不出了~~~

Web Storage

QQ截图20160406205144QQ截图20160406205144

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <p id="msg"></p>
    <input title="" type="text" id="input" />
    <input type="button" value="save" onclick="saveStorage('input')" />
    <input type="button" value="get" onclick="loadStorage('input')" />
</body>
</html>
<script>
    function saveStorage(id){
        var target = document.getElementById(id);
        var str = target.value;
//        保存数据方法 key value
        sessionStorage.setItem("message",str);
    }
    function loadStorage(id){
        var target = document.getElementById(id);
//        读取数据
        var msg = sessionStorage.getItem("message");
        document.getElementById('msg').innerHTML =msg;
    }
</script>

Mysql事务

SAVEPONIT 语句可以对事务进行部分回滚

START TRANSACTION;
INSERT INTO t VALUES(1);
SAVEPOINT my_savepoint;
INSERT INTO t VALUES(2);
ROLLBACK TO SAVEPOINT my_savepoint;
INSERT INTO t VALUES(3);
COMMIT;     

表里只有第一条和第三条插入成功

InnoDB存储引擎实现事务隔离级别功能,可以许可或防止可能出现的问题:

1.脏读。 事务看到一些其他事务未提交的修改;( 因为update等操作时先更新的是cache,而select操作正好是先在cache里找,如果事务a先更新到cache里,而还没有更新到库,这时事务b正好select这条数据,就形成脏读);

2.不可重复读。同一事务中,执行同一个select的结果,因有一个事务再执行期间修改了某些行,造成结果不一样;

3.幻影行。同一事务中,执行同一个select的结果,因有一个事务插入了新行,造成突然看到一个之前没看过的行出现;


为解决以上问题,InnoDB提供了4种事务隔离级别:

1.READ UNCOMMITTED.许可事务看到其他事务未提交的行修改;

2.READ COMMITTED.只许可事务看到其他事务已经提交的行修改;

3.(默认)REPEATABLE READ.事务select结果维持一致性,即使其他事务同时插入或修改操作;

4.SERIALIZABLE.事务正在读取时,其他事务禁止对这些行进行操作。



可以通过SET GLOBAL TRANSACTION ISOATION LEVEL level修改默认隔离级别。

个人总结,有不妥之处,欢迎指正!


深入理解PHP内存管理之谁动了我的内存

04 Mar 11 深入理解PHP内存管理之谁动了我的内存

首先让我们看一个问题: 如下代码的输出,

  1. var_dump(memory_get_usage());
  2. $a = "laruence";
  3. var_dump(memory_get_usage());
  4. unset($a);
  5. var_dump(memory_get_usage());

输出(在我的个人电脑上, 可能会因为系统,PHP版本,载入的扩展不同而不同):

  1. int(90440)
  2. int(90640)
  3. int(90472)

注意到 90472-90440=32, 于是就有了各种的结论, 有的人说PHP的unset并不真正释放内存, 有的说, PHP的unset只是在释放大变量(大量字符串, 大数组)的时候才会真正free内存, 更有人说, 在PHP层面讨论内存是没有意义的.

那么, 到底unset会不会释放内存? 这32个字节跑哪里去了?

要回答这个问题, 我将从俩个方面入手:

这32个字节去哪里了

首先我们要打破一个思维: PHP不像C语言那样, 只有你显示的调用内存分配相关API才会有内存的分配. 
也就是说, 在PHP中, 有很多我们看不到的内存分配过程.
比如对于:

  1. $a = "laruence";

隐式的内存分配点就有:

  1. 1. 为变量名分配内存, 存入符号表
  2. 2. 为变量值分配内存

所以, 不能只看表象.
第二, 别怀疑,PHP的unset确实会释放内存(当然, 还要结合引用和计数, 这部分的内容请参看我之前的文章深入理解PHP原理之变量分离/引用), 但这个释放不是C编程意义上的释放, 不是交回给OS.
对于PHP来说, 它自身提供了一套和C语言对内存分配相似的内存管理API:

  1. emalloc(size_t size);
  2. efree(void *ptr);
  3. ecalloc(size_t nmemb, size_t size);
  4. erealloc(void *ptr, size_t size);
  5. estrdup(const char *s);
  6. estrndup(const char *s, unsigned int length);

这些API和C的API意义对应, 在PHP内部都是通过这些API来管理内存的.

当我们调用emalloc申请内存的时候, PHP并不是简单的向OS要内存, 而是会像OS要一个大块的内存, 然后把其中的一块分配给申请者, 这样当再有逻辑来申请内存的时候, 就不再需要向OS申请内存了, 避免了频繁的系统调用.

比如如下的例子:

  1. <?php
  2. var_dump(memory_get_usage(TRUE)); //注意获取的是real_size
  3. $a = "laruence";
  4. var_dump(memory_get_usage(TRUE));
  5. unset($a);
  6. var_dump(memory_get_usage(TRUE));

输出:

  1. int(262144)
  2. int(262144)
  3. int(262144)

也就是我们在定义变量$a的时候, PHP并没有向系统申请新内存.

同样的, 在我们调用efree释放内存的时候, PHP也不会把内存还给OS, 而会把这块内存, 归入自己维护的空闲内存列表. 而对于小块内存来说, 更可能的是, 把它放到内存缓存列表中去(后记, 某些版本的PHP, 比如我验证过的PHP5.2.4, 5.2.6, 5.2.8, 在调用get_memory_usage()的时候, 不会减去内存缓存列表中的可用内存块大小, 导致看起来, unset以后内存不变, 见评论).

现在让我来回答这32个字节跑哪里去了, 就向我刚才说的, 很多内存分配的过程不是显式的, 看了下面的代码你就明白了:

  1. <?php
  2. var_dump("I am Laruence, From http://www.laruence.com");
  3. var_dump(memory_get_usage());
  4. $a = "laruence";
  5. var_dump(memory_get_usage());
  6. unset($a);
  7. var_dump(memory_get_usage());

输出:

  1. string(43) "I am Laruence, From http://www.laruence.com"
  2. int(90808) //赋值前
  3. int(90976)
  4. int(90808) //是的, 内存正常释放了

90808-90808 = 0, 正常了, 也就是说这32个字节是被输出函数给占用了(严格来说, 是被输出的Header占用了)

只增不减的数组

Hashtable是PHP的核心结构(了解Hashtable, 可以参看我之前的文章深入理解PHP之数组(遍历顺序)), 数组也是用她来表示的, 而符号表也是一种关联数组, 对于如下代码:

  1. var_dump("I am Laruence, From http://www.laruence.com");
  2. var_dump(memory_get_usage());
  3. $array = array_fill(1, 100, "laruence");
  4. foreach ($array as $key => $value) {
  5.     ${$value . $key} = NULL;
  6. }
  7. var_dump(memory_get_usage());
  8. foreach ($array as $key=> $value) {
  9.     unset(${$value . $key});
  10. }
  11. var_dump(memory_get_usage());

我们定义了100个变量, 然后又按个Unset了他们, 来看看输出:

  1. string(43) "I am Laruence, From http://www.laruence.com"
  2. int(93560)
  3. int(118848)
  4. int(104448)

Wow, 怎么少了这么多内存?
这是因为对于Hashtable来说, 定义它的时候, 不可能一次性分配足够多的内存块, 来保存未知个数的元素, 所以PHP会在初始化的时候, 只是分配一小部分内存块给HashTable, 当不够用的时候再RESIZE扩容,

而Hashtable, 只能扩容, 不会减少, 对于上面的例子, 当我们存入100个变量的时候, 符号表不够用了, 做了一次扩容, 而当我们依次unset掉这100个变量以后, 变量占用的内存是释放了(118848 – 104448), 但是符号表并没有缩小, 所以这些少的内存是被符号表本身占去了…

现在, 你是不是对PHP的内存管理有了一个初步的认识了呢?

Drupal第三方模块

1.Color box -弹出框

2.mollom-反垃圾邮件
3.catpha-验证
4.boost-缓存
5.ckediter+ctools-文本编辑框
6。filed-pemission-权限到字段
7.feeds-批量导入导出
8.tb_menc-分类菜单
9.view
10.devel-7-开发者
11.disque-评论
12.htmlmial-html邮件
13.password_policy 密码复杂度

drupal的bootstrap模版安装

1.解压所得文件到drupal的sites\all\themes目录下;

2.从解压文件分离出子主题bootstrap_subtheme文件;
3.修改子文件名为本站名;
4.修改bootstrap_subtheme.info.starterkit文件名和属性对应上本站名,并修改name;
5.访问设置默认的主题;
6.负责相关工程页面modules\system\page.tpl.php。