• 在Linux服务器上手工释放内存

    在Linux服务器上手工释放内存

    总有很多朋友对于Linux的内存管理有疑问,之前一篇linux下的内存管理方式似乎也没能清除大家的疑虑。而在新版核心中,似乎对这个问题提供了新的解决方法,特转出来给大家参考一下。最后,还附上我对这方法的意见,欢迎各位一同讨论。

      当在Linux下频繁存取文件后,物理内存会很快被用光,当程序结束后,内存不会被正常释放,而是一直作为caching。这个问题,貌似有不少人在问,不过都没有看到有什么很好解决的办法。那么我来谈谈这个问题。

      一、通常情况

      先来说说free命令:

      [root@server ~]# free -m

      total used free shared buffers cached

      Mem: 249 163 86 0 10 94

      -/+ buffers/cache: 58 191

      Swap: 511 0 511

      其中:

      total 内存总数

      used 已经使用的内存数

      free 空闲的内存数

      shared 多个进程共享的内存总额

      buffers Buffer Cache和cached Page Cache 磁盘缓存的大小

      -buffers/cache (已用)的内存数:used – buffers – cached

      +buffers/cache(可用)的内存数:free + buffers + cached

      可用的memory=free memory+buffers+cached

      有了这个基础后,可以得知,我现在used为163MB,free为86MB,buffer和cached分别为10MB,94MB。

      那么我们来看看,如果我执行复制文件,内存会发生什么变化.

      [root@server ~]# cp -r /etc ~/test/

      [root@server ~]# free -m

      total used free shared buffers cached

      Mem: 249 244 4 0 8 174

      -/+ buffers/cache: 62 187

      Swap: 511 0 511

      在我命令执行结束后,used为244MB,free为4MB,buffers为8MB,cached为174MB,天呐,都被cached吃掉了。别紧张,这是为了提高文件读取效率的做法。

      为了提高磁盘存取效率,Linux做了一些精心的设计,除了对dentry进行缓存(用于VFS,加速文件路径名到inode的转换),还采取了两种主要Cache方式:Buffer Cache和Page Cache。前者针对磁盘块的读写,后者针对文件inode的读写。这些Cache有效缩短了 I/O系统调用(比如read,write,getdents)的时间。

      那么有人说过段时间,linux会自动释放掉所用的内存。等待一段时间后,我们使用free再来试试,看看是否有释放?

      [root@server test]# free -m

      total used free shared buffers cached

      Mem: 249 244 5 0 8 174

      -/+ buffers/cache: 61 188

      Swap: 511 0 511

      似乎没有任何变化。(实际情况下,内存的管理还与Swap有关)

      那么我能否手动释放掉这些内存呢?回答是可以的!

    二、手动释放缓存

      /proc是一个虚拟文件系统,我们可以通过对它的读写操作做为与kernel实体间进行通信的一种手段。也就是说可以通过修改/proc中的文件,来对当前kernel的行为做出调整。那么我们可以通过调整/proc/sys/vm/drop_caches来释放内存。操作如下:

      [root@server test]# cat /proc/sys/vm/drop_caches

      0

      首先,/proc/sys/vm/drop_caches的值,默认为0。

      [root@server test]# sync

      手动执行sync命令(描述:sync 命令运行 sync 子例程。如果必须停止系统,则运行sync 命令以确保文件系统的完整性。sync 命令将所有未写的系统缓冲区写到磁盘中,包含已修改的 i-node、已延迟的块 I/O 和读写映射文件)

      [root@server test]# echo 3 > /proc/sys/vm/drop_caches

      [root@server test]# cat /proc/sys/vm/drop_caches

      3

      将/proc/sys/vm/drop_caches值设为3

      [root@server test]# free -m

      total used free shared buffers cached

      Mem: 249 66 182 0 0 11

      -/+ buffers/cache: 55 194

      Swap: 511 0 511

      再来运行free命令,会发现现在的used为66MB,free为182MB,buffers为0MB,cached为11MB。那么有效的释放了buffer和cache。

      ◎ 有关/proc/sys/vm/drop_caches的用法在下面进行了说明

      /proc/sys/vm/drop_caches (since Linux 2.6.16)

      Writing to this file causes the kernel to drop clean caches,dentries and inodes from memory, causing that memory to become free.

      To free pagecache, use echo 1 > /proc/sys/vm/drop_caches;

      to free dentries and inodes, use echo 2 > /proc/sys/vm/drop_caches;

      to free pagecache, dentries and inodes, use echo 3 > /proc/sys/vm/drop_caches.

      Because this is a non-destructive operation and dirty objects are not freeable, the user should run sync first.

      三、我的意见

      上述文章就长期以来很多用户对Linux内存管理方面的疑问,给出了一个比较“直观”的回复,我更觉得有点像是核心开发小组的妥协。

      对于是否需要使用这个值,或向用户提及这个值,我是有保留意见的:

      1、从man可以看到,这值从2.6.16以后的核心版本才提供,也就是老版的操作系统,如红旗DC 5.0、RHEL 4.x之前的版本都没有;

      2、若对于系统内存是否够用的观察,我还是原意去看swap的使用率和si/so两个值的大小;

      用户常见的疑问是,为什么free这么小,是否关闭应用后内存没有释放?

      但实际上,我们都知道这是因为Linux对内存的管理与Windows不同,free小并不是说内存不够用了,应该看的是free的第二行最后一个值:

      -/+ buffers/cache: 58 191

      这才是系统可用的内存大小。

      实际项目中告诉我们,如果因为是应用有像内存泄露、溢出的问题,从swap的使用情况是可以比较快速可以判断的,但free上面反而比较难查看。

      相反,如果在这个时候,我们告诉用户,修改系统的一个值,“可以”释放内存,free就大了。用户会怎么想?不会觉得操作系统“有问题”吗?

      所以说,我觉得既然核心是可以快速清空buffer或cache,也不难做到(这从上面的操作中可以明显看到),但核心并没有这样做(默认值是0),我们就不应该随便去改变它。

      一般情况下,应用在系统上稳定运行了,free值也会保持在一个稳定值的,虽然看上去可能比较小。

      当发生内存不足、应用获取不到可用内存、OOM错误等问题时,还是更应该去分析应用方面的原因,如用户量太大导致内存不足、发生应用内存溢出等情况,否则,清空buffer,强制腾出free的大小,可能只是把问题给暂时屏蔽了。

      我觉得,排除内存不足的情况外,除非是在软件开发阶段,需要临时清掉buffer,以判断应用的内存使用情况;或应用已经不再提供支持,即使应用对内存的时候确实有问题,而且无法避免的情况下,才考虑定时清空buffer。(可惜,这样的应用通常都是运行在老的操作系统版本上,上面的操作也解决不了)。而生产环境下的服务器可以不考虑手工释放内存,这样会带来更多的问题。记住内存是拿来用的,不是拿来看的。不像windows, 无论你的真实物理内存有多少,他都要拿硬盘交换文件来读。这也就是windows为什么常常提示虚拟空间不足的原因,你们想想多无聊,在内存还有大部分的时候,拿出一部分硬盘空间来充当内存。硬盘怎么会快过内存,所以我们看linux,只要不用swap的交换空间,就不用担心自己的内存太少。如果常常swap用很多,可能你就要考虑加物理内存了,这也是linux看内存是否够用的标准哦。当然这仅代表我个人意见,也欢迎大家来交流讨论。

  • CentOS 5.2下Memcache的安装与配置

    安装服务器端:
    1,安装libevent库,它将Linux的epoll、freebsd操作系统的kqueue等事件处理功能封装成统一的接口,memcached使用这个库,可以发挥其高性能。
    [root@youxia205 opt]# yum install libevent libevent-devel
    2,下载memcache源码包:
    [root@youxia205 opt]# wget http://memcached.googlecode.com/files/memcached-1.4.5.tar.gz
    3,解压、编译、安装:
    [root@youxia205 opt]# tar -zxvf memcached-1.4.5.tar.gz
    [root@youxia205 opt]# cd memcached-1.4.5
    [root@youxia205 memcached-1.4.5]# ./configure
    [root@youxia205 memcached-1.4.5]# make && make install
    4,安装完成之后可以看下memcache的参数:
    [root@youxia205 local]# memcached -help
    memcached 1.4.5
    -p <num>      TCP port number to listen on (default: 11211)
    -U <num>      UDP port number to listen on (default: 11211, 0 is off)
    -s <file>     UNIX socket path to listen on (disables network support)
    -a <mask>     access mask for UNIX socket, in octal (default: 0700)
    -l <ip_addr>  interface to listen on (default: INADDR_ANY, all addresses)
    -d            run as a daemon
    -r            maximize core file limit
    -u <username> assume identity of <username> (only when run as root)
    -m <num>      max memory to use for items in megabytes (default: 64 MB)
    -M            return error on memory exhausted (rather than removing items)
    -c <num>      max simultaneous connections (default: 1024)
    -k            lock down all paged memory.  Note that there is a
    limit on how much memory you may lock.  Trying to
    allocate more than that would fail, so be sure you
    set the limit correctly for the user you started
    the daemon with (not for -u <username> user;
    under sh this is done with ‘ulimit -S -l NUM_KB’).
    -v            verbose (print errors/warnings while in event loop)
    -vv           very verbose (also print client commands/reponses)
    -vvv          extremely verbose (also print internal state transitions)
    -h            print this help and exit
    -i            print memcached and libevent license
    -P <file>     save PID in <file>, only used with -d option
    -f <factor>   chunk size growth factor (default: 1.25)
    -n <bytes>    minimum space allocated for key+value+flags (default: 48)
    -L            Try to use large memory pages (if available). Increasing
    the memory page size could reduce the number of TLB misses
    and improve the performance. In order to get large pages
    from the OS, memcached will allocate the total item-cache
    in one large chunk.
    -D <char>     Use <char> as the delimiter between key prefixes and IDs.
    This is used for per-prefix stats reporting. The default is
    “:” (colon). If this option is specified, stats collection
    is turned on automatically; if not, then it may be turned on
    by sending the “stats detail on” command to the server.
    -t <num>      number of threads to use (default: 4)
    -R            Maximum number of requests per event, limits the number of
    requests process for a given connection to prevent
    starvation (default: 20)
    -C            Disable use of CAS
    -b            Set the backlog queue limit (default: 1024)
    -B            Binding protocol – one of ascii, binary, or auto (default)
    -I            Override the size of each slab page. Adjusts max item size
    (default: 1mb, min: 1k, max: 128m)
  • 用css控制图片最大尺寸

    <style type=”text/css”>
    <!–
    img,a img{
    border:0;
    margin:0;
    padding:0;
    max-width:650px;
    width: expression(this.width > 650 && this.width > this.height ? 650px : ‘auto’;);
    max-height:1650px;
    height: expresion(this.height > 1650 ? 1650px : ‘auto’;);
    } –>
    </style>
  • 常见mysql远程连接错误解决方法

    1,远端无法telnet到mysql服务器的3306无反应

    解决方法:

    进入/etc/mysql/my.cnf,找到bind-address   = 127.0.0.1,将其注释掉,然后自毁执行/etc/init.d/mysql restart重启.

    2,ip地址不被允许访问该mysql服务器

    解决方法:

    grant all PRIVILEGES on *.* to root@’您的本地ip地址’ identified by ‘数据库密码’;

    *.*代表 数据库.数据表

    all PRIVILEGES 所有权限   也可以是create,select,insert,update,delete

  • svn的安装与远程备份

    svn的安装与远程备份

  • linux下 A服务器到B服务器(远程)备份

    linux下 A服务器到B服务器(远程)备份
    一个示例脚本
    A:首先手动备份一个目录压缩成一个tar.gz
    写一个执行脚本
    #! /bin/sh
    rm /var/www/备份源文件_bak.tar.gz
    tar -cvzf /var/www/备份源文件_bak.tar.gz /var/www/源文件夹
    rq=`date +%Y%m%d` 生成当前日期
    scp /var/www/备份源文件_bak.tar.gz root@XXX.XXX.XXX.XXX:/var/wiki_copy/备份新名称i$rq.tar.gz
    scp命令 从A服务器拷贝文件到B服务器(XXX.XXX.XXX.XXX)
  • svn数据备份,还原检出到其他目录

    hooks目录下的post-commit 是上传钩子脚本
    即你从本地上传文件到svn服务器的时候触发该脚本
    注意post-commit 文件权限为root可执行
    vi  /var/svn/project-name/hooks/post-commit
    #!/bin/sh
    export LANG=zh_CN.UTF-8
    REPOS=”$1″
    REV=”$2″
    svn checkout –username 用户名 –password 密码 svn://127.0.0.1/test /var/www/test
    ##从svn版本库中检出源文件到新的目录  /var/www/test
  • apache端口转发

    在某些时候,可能需要将发到apache某个端口的请求转发到另外一个端口. mod_proxy模块可以方便的完成这个需求.
    ubuntu中配置apache2比较方便.  下面以lucid中apache2为例介绍如何使用 mod_proxy
    1. 首先配置mod_proxy模块
    将/etc/apache2/mods-available中的
    proxy_http.load
    proxy.load
    proxy.conf
    proxy_connect.load
    ln -s 到 /etc/apache2/mods-enabled
    注意需要适当的修改 proxy.conf
    2. 在 /etc/apache2/sites-enabled中建立一个文件(或一个连接 ln -s 到一个文件)
    <VirtualHost *:80>
    ProxyPreserveHost On
    ServerName www.example.com
    ProxyPass / http://www.example.com:8000/
    ProxyPassReverse / http://www.example.com:8000/
    ServerAdmin webmaster@localhost
    </VirtualHost>
    这样, 所有http://www.example.com 请求实际上都是到了其 8000端口. 80端口实际上成了 8000端口的一个代理
    当然 mod_proxy能够完成的任务不止这些. 例如, 它可以将请求转发到别的服务器上(配置合适的话).
    使用该模块应该注意 proxy.conf的配置.
  • debian操作系统安装记录

    1.安装sudo  编辑/etc/sudoers
    2.安装配置apt源
    vim /etc/apt/source.list
    然后进行更新源
    apt-get -s upgrade
    apt-get update
    3.安装ssh(openssh-server)
    4.安装rcconf(服务管理器)管理需要启动的服务
  • scp命令:两台服务器文件传输,进阶-设置两台服务器不需要密码直接复制

    scp 命令是 SSH 中最方便有用的命令了,试想,在两台服务器之间直接传送文件,仅仅用 scp 一个命令就完全解决了。 你可以在一台服务器上 以 root 身份运行 #scp servername:/home/ftp/pub/file1 . 这样就把另一台服务器上的文件 /home/ftp/pub/file1 直接传到本机器的当前目录下,当然你也可以用 #scp /tmp/file2 servername:/boot 把本机上的文件 /tmp/file2 送到另一台机器的 /boot 目录下。而且整个传送过程仍然是用 SSH 加密的。
    scp 就是 secure copy, 是用来进行远程文件拷贝的 . 数据传输使用 ssh1, 并且和 ssh1 使用相同的认证方式 , 提供相同的安全保证 . 与 rcp 不同的是 ,scp 会要求你输入密码如果需要的话 .
    案例:
    copy 本地的档案到远程的机器上
    scp /etc/lilo.conf my@www.upsdn.net:/home/my

    scp 命令是 SSH 中最方便有用的命令了,试想,在两台服务器之间直接传送文件,仅仅用 scp 一个命令就完全解决了。 你可以在一台服务器上 以 root 身份运行 #scp servername:/home/ftp/pub/file1 . 这样就把另一台服务器上的文件 /home/ftp/pub/file1 直接传到本机器的当前目录下,当然你也可以用 #scp /tmp/file2 servername:/boot 把本机上的文件 /tmp/file2 送到另一台机器的 /boot 目录下。而且整个传送过程仍然是用 SSH 加密的。
    scp 就是 secure copy, 是用来进行远程文件拷贝的 . 数据传输使用 ssh1, 并且和 ssh1 使用相同的认证方式 , 提供相同的安全保证 . 与 rcp 不同的是 ,scp 会要求你输入密码如果需要的话 .
    案例:
    copy 本地的档案到远程的机器上

    scp /etc/lilo.conf my@www.upsdn.net:/home/my/123.conf

    copy远程机器上的档案到本地来

    scp my@www.upsdn.net:/etc/lilo.conf /etc

    进阶—————-

    最近在编写定时自动执行的shell脚步中遇到一个问题。在该脚步中,需要使用scp命令将本地的文件复制到另一台机器中备份。但通常执行scp命令后都需要输入用户密码,这样在定时自动执行的shell脚步中就不适用了。

    本人的第一直觉就是建立无密码用户,在scp命令中使用该用户就不需要输入用户密码了。

    以下是在机器Client的root和机器Server的root之间建立安全信任关系的步骤:

    1. 在机器Client上root用户执行ssh-keygen命令,生成建立安全信任关系的证书。

    [root@Client root]# ssh-keygen -b 1024 -t rsa

    Generating public/private rsa key pair.

    Enter file in which to save the key (/root/.ssh/id_rsa):

    Enter passphrase (empty for no passphrase):            <– 直接输入回车

    Enter same passphrase again:                           <– 直接输入回车

    Your identification has been saved in /root/.ssh/id_rsa.

    Your public key has been saved in /root/.ssh/id_rsa.pub.

    The key fingerprint is:

    49:9c:8a:8f:bc:19:5e:8c:c0:10:d3:15:60:a3:32:1c root@Client

    [root@Client root]#

    注意:在程序提示输入passphrase时直接输入回车,表示无证书密码。

    上述命令将生成私钥证书id_rsa和公钥证书id_rsa.pub,存放在用户家目录的.ssh子目录中。

    2. 将公钥证书id_rsa.pub复制到机器Server的root家目录的.ssh子目录中,同时将文件名更换为authorized_keys。

    [root@Client root]# scp -p .ssh/id_rsa.pub root@192.168.3.206:/root/.ssh/authorized_keys

    root@192.168.3.206’s password:          <– 输入机器Server的root用户密码

    id_rsa.pub           100% |**************************|   218       00:00

    [root@Client root]#

    在执行上述命令时,两台机器的root用户之间还未建立安全信任关系,所以还需要输入机器Server的root用户密码。

    经过以上2步,就在机器Client的root和机器Server的root之间建立安全信任关系。