PHP5.6

CentOS 默认的 yum 源安装的 PHP 版本过低,又想通过 yum 来安装 PHP5.6。

  • 查看系统上是否安装了 PHP,有就删除。
    查看系统是否安装了 PHP
    yum list installed | grep php
    # 删除PHP相关的模块
    yum remove phpxxx
    
  • 添加 EPEL 和 REMI 源
    rpm -Uvh http://ftp.iij.ad.jp/pub/linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
    rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
    
  • 查看 yum 源是否有 PHP5.6 及相关库
    yum list --enablerepo=remi --enablerepo=remi-php56 | grep php
    
  • 添加 REMI 源成功之后,安装 PHP5.6 及相关库
    yum install --enablerepo=remi --enablerepo=remi-php56 php-fpm php-opcache php-devel php-mbstring php-mcrypt php-mysqlnd
    

Nginx

  • 添加 nginx 的 yum 源
    wget http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
    rpm -ivh nginx-release-centos-6-0.el6.ngx.noarch.rpm
    

    或者直接添加 /etc/yum.repos.d/nginx.repo

    [nginx]
    name=nginx repo
    baseurl=http://nginx.org/packages/centos/6/$basearch/
    gpgcheck=0
    enabled=1
    
  • 安装 nginx
    yum install -y nginx
    

MySQL

  • 添加 MySQL 的 yum 源。
    到 https://dev.mysql.com/downloads/repo/yum/ 下载相应的 RPM 包,如:mysql57-community-release-el6-11.noarch.rpm

    wget https://repo.mysql.com//mysql57-community-release-el6-11.noarch.rpm
    rpm -Uvh mysql57-community-release-el6-n.noarch.rpm
    
  • 安装 MySQL
    yum install mysql-community-server
    

    更多信息可以参考:A Quick Guide to Using the MySQL Yum Repository

MariaDB

  • 添加 yum 源
    Setting up MariaDB Repositories 生成相应 的 yum 源,然后添加到 /etc/yum.repos.d/mariadb.repo

    [mariadb]
    name = MariaDB
    baseurl = http://yum.mariadb.org/10.2/centos6-amd64
    gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
    gpgcheck=1
    
  • 安装 MariaDB
    yum install -y MariaDB-server MariaDB-client MariaDB-devel
    

用官方源下载在没有翻墙的情况下是很慢的,可以用中国科学技术大学的镜像,不过也很不稳定。

CentOS6.6 系统自带的 Python 版本是 Python2.6,但项目需要 Python2.7。

升级 Python2.6 到 Python2.7

  • 下载 Python源码包
    curl https://www.python.org/ftp/python/2.7.13/Python-2.7.13.tgz > Python-2.7.13.tgz
    tar -zxvf Python-2.7.13.tgz -C /opt/
    
  • 安装 Python
    cd /opt/Python-2.7.13
    ./configure
    make &&  make install
    

    默认安装在 /usr/loca/python2.7 目录下,也可以通过参数配置来指定安装路径 ./configure --prefix=/path/to/install/python
    安装完之后,系统默认的 Python 版本还是 Python2.6 的,需要修改:

    rm -f /usr/bin/python
    ln -s /usr/local/bin/python /usr/bin/python
    

    修改完之后,发现 yum 工具用不了了,因为 yum 工具是基于 Python2.6 的。将 /usr/bin/yum 的头部 #!/usr/bin/python 改为 #!/usr/bin/python2.6

安装 pip

cd /opt/
curl https://bootstrap.pypa.io/get-pip.py > get-pip.py
python get-pip.py
  • 如果出现错误:

    zipimport.ZipImportError: can’t decompress data; zlib not available

    是因为系统缺少了 zlibzlib-devel 库。

    yum install -y zlib zlib-devel
    

    安装成功之后,需要重新编译 Python:

    cd /opt/Python-2.7.13/
    make clean && make && make install
    # 重新编译完成之后再试一次安装 pip
    python get-pip.py
    
  • 如果接着出现错误:

    Could not fetch URL https://pypi.python.org/simple/pip/: There was a problem confirming the ssl certificate: Can’t connect to HTTPS URL because the SSL module is not available. – skipping

    是因为系统缺少 openssl-devel

    yum install -y openssl-devel
    

    安装成功之后,需要重新编译 Python:

    cd /opt/Python-2.7.13/
    make clean && make && make install
    # 重新编译完成之后再试一次安装 pip
    python get-pip.py
    

    到这里,我就成功安装了 pip。


总结 update.sh

#!/bin/sh

set -e
# 先安装需要的库:
yum install -y gcc zlib zlib-devel openssl-devel
# 下载 Python2.7 的源包
curl https://www.python.org/ftp/python/2.7.13/Python-2.7.13.tgz > Python-2.7.13.tgz
tar -zxvf Python-2.7.13.tgz -C /opt/
# 安装 Python
cd /opt/Python-2.7.13
./configure
make &&  make install
# 修改系统默认的 Python 版本
rm -f /usr/bin/python
ln -s /usr/local/bin/python /usr/bin/python
# 将 `/usr/bin/yum` 的头部 `#!/usr/bin/python` 改为 `#!/usr/bin/python2.6`
sed -i '1c #!/usr/bin/python2.6' /usr/bin/yum
# 接着安装 pip
cd /opt/
curl https://bootstrap.pypa.io/get-pip.py > get-pip.py
python get-pip.py

Linux autossh + ssh 设置 sockets5 代理翻墙
Linux – LSBInitScript

系统服务脚本 /etc/init.d/autossh-proxy:

#!/bin/sh

### BEGIN INIT INFO
# Provides:          autossh-proxy
# Required-Start:    $network
# Required-Stop:     $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: start and stop autossh-proxy
# Description:       autossh-proxy is a manager of socket5 proxy by ssh
### END INIT INFO

# Author: lizs <lizsmail.com>

PATH=/sbin:/bin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

NAME=autossh
AUTOSSH=/usr/bin/autossh
AUTOSSH_PIDFILE=/var/run/$NAME.pid
# AUTOSSH_LOGFILE=/var/log/$BASE.log
# autossh can use environment variables to control features, e.g. AUTOSSH_PID.
# more info see `man autossh`
AUTOSSH_PID="/usr/bin/env AUTOSSH_PIDFILE=${AUTOSSH_PIDFILE}"
# The autossh args
AUTOSSH_ARGS="-M 0 -fqTN -D 1080 root@alizs.cc"

# Get lsb functions
. /lib/lsb/init-functions

do_start()
{
    start-stop-daemon --start --quiet --oknodo \
        --pidfile $AUTOSSH_PIDFILE \
        --make-pidfile \
        --exec $AUTOSSH_PID $AUTOSSH \
        -- $AUTOSSH_ARGS
    RETVAL="$?"
    return "${RETVAL}"
}

do_stop()
{
    # Return
    # 0 if the daemon has been stopped
    # 2 if the daemon could not be stopped
    # other if a failure occured
    start-stop-daemon --stop --quiet --oknodo \
        --retry=TERM/5/KILL/5 \
        --pidfile $AUTOSSH_PIDFILE \
        --remove-pidfile
    RETVAL="$?"
    return "${RETVAL}"
}

do_restart()
{
    exit 0
}


case "$1" in
    status)
        if init_is_upstart; then
            exit 1
        fi
        status_of_proc -p "${AUTOSSH_PIDFILE}" "${AUTOSSH}" "${NAME}"
        ;;
    start)
        if init_is_upstart; then
            exit 1
        fi
        log_begin_msg "Starting ${NAME}..."
        do_start
        log_end_msg "$?" # e.g. [ok], failed!, (warning)
        ;;
    stop)
        if init_is_upstart; then
            exit 1
        fi
        log_begin_msg "Stopping ${NAME}..."
        do_stop
        log_end_msg "$?"
        ;;
    restart)
        if init_is_upstart; then
            exit 1
        fi
        log_begin_msg "Restarting ${NAME}"
        do_restart
        log_end_msg "$?"
        ;;
    force-reload)
        exit 0
        ;;
    *)
        log_failure_msg "Usage: service ${NAME} {status|start|stop|restart}"
        ;;
esac

添加系统服务

将服务脚本添加到 /etc/init.d/ 目录下之后,就可以添加系统服务了。

  • CentOS
    Redhat 提供了 chkconfig 命令来管理系统的服务:

    • chkconfig --list:所有服务列表
    • chkconfig --list serviceName:只显示 serverName 服务
    • chkconfig serviceName on:开启 serverName 服务的自动启动
    • chkconfig serviceName off:关闭 serverName 服务的自动启动
    • chkconfig --add serviceName:添加服务
    • chkconfig --del serviceName:删除服务
  • Ubuntu
    Ubuntu 是没有 chkconfig 命令的,而是提供了另外的命令来实现管理服务:

    • sudo update-rc.d serviceName defaults:添加服务,默认添加服务为自动启动,即 /etc/rc0.d//etc/rc6.d 各级别里面都添加了服务的启动软链接。
    • sudo update-rc.d serviceName remove:删除服务,默认会删除所有级别的服务,即彻底删除服务。

      如果,你想要配置各级别的启动情况,可以删除相应级别目录里面的服务软链接。

    • systemctl daemon-reload:修改过服务之后,用该命令来重新加载服务。

#!/bin/sh

### BEGIN INIT INFO
# Provides:          autossh-proxy
# Required-Start:    $network
# Required-Stop:     $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: start and stop autossh-proxy
# Description:       autossh-proxy is a manager of socket5 proxy by ssh
### END INIT INFO

# Author: lizs <lizsmail.com>

PATH=/sbin:/bin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

NAME=autossh
AUTOSSH=/usr/bin/autossh
AUTOSSH_PIDFILE=/var/run/$NAME.pid
# AUTOSSH_LOGFILE=/var/log/$BASE.log
# autossh can use environment variables to control features, e.g. AUTOSSH_PID.
# more info see `man autossh`
AUTOSSH_PID="/usr/bin/env AUTOSSH_PIDFILE=${AUTOSSH_PIDFILE}"
# The autossh args
AUTOSSH_ARGS="-M 0 -fqTN -D 1080 root@alizs.cc"

# Get lsb functions
. /lib/lsb/init-functions

do_start()
{
    start-stop-daemon --start --quiet --oknodo \
        --pidfile $AUTOSSH_PIDFILE \
        --make-pidfile \
        --exec $AUTOSSH_PID $AUTOSSH \
        -- $AUTOSSH_ARGS
    RETVAL="$?"
    return "${RETVAL}"
}

do_stop()
{
    # Return
    # 0 if the daemon has been stopped
    # 2 if the daemon could not be stopped
    # other if a failure occured
    start-stop-daemon --stop --quiet --oknodo \
        --retry=TERM/5/KILL/5 \
        --pidfile $AUTOSSH_PIDFILE \
        --remove-pidfile
    RETVAL="$?"
    return "${RETVAL}"
}

do_restart()
{
    exit 0
}


case "$1" in
    status)
        if init_is_upstart; then
            exit 1
        fi
        status_of_proc -p "${AUTOSSH_PIDFILE}" "${AUTOSSH}" "${NAME}"
        ;;
    start)
        if init_is_upstart; then
            exit 1
        fi
        log_begin_msg "Starting ${NAME}..."
        do_start
        log_end_msg "$?" # e.g. [ok], failed!, (warning)
        ;;
    stop)
        if init_is_upstart; then
            exit 1
        fi
        log_begin_msg "Stopping ${NAME}..."
        do_stop
        log_end_msg "$?"
        ;;
    restart)
        if init_is_upstart; then
            exit 1
        fi
        log_begin_msg "Restarting ${NAME}"
        do_restart
        log_end_msg "$?"
        ;;
    force-reload)
        exit 0
        ;;
    *)
        log_failure_msg "Usage: service ${NAME} {status|start|stop|restart}"
        ;;
esac

wiki: LSBInitScripts
Linux Standard Base Core Specification 3.1

#!/bin/sh

### BEGIN INIT INFO
# Provides:          autossh-proxy
# Required-Start:    $network
# Required-Stop:     $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: start and stop autossh-proxy
# Description:       autossh-proxy is a manager of socket5 proxy by ssh
### END INIT INFO

# Author: lizs <lizsmail.com>

PATH=/sbin:/bin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

NAME=autossh
AUTOSSH=/usr/bin/autossh
AUTOSSH_PIDFILE=/var/run/$NAME.pid
# AUTOSSH_LOGFILE=/var/log/$BASE.log
# autossh can use environment variables to control features, e.g. AUTOSSH_PID.
# more info see `man autossh`
AUTOSSH_PID="/usr/bin/env AUTOSSH_PIDFILE=${AUTOSSH_PIDFILE}"
# The autossh args
AUTOSSH_ARGS="-M 0 -fqTN -D 1080 root@alizs.cc"

# Get lsb functions
. /lib/lsb/init-functions

do_start()
{
    start-stop-daemon --start --quiet --oknodo \
        --pidfile $AUTOSSH_PIDFILE \
        --make-pidfile \
        --exec $AUTOSSH_PID $AUTOSSH \
        -- $AUTOSSH_ARGS
    RETVAL="$?"
    return "${RETVAL}"
}

do_stop()
{
    # Return
    # 0 if the daemon has been stopped
    # 2 if the daemon could not be stopped
    # other if a failure occured
    start-stop-daemon --stop --quiet --oknodo \
        --retry=TERM/5/KILL/5 \
        --pidfile $AUTOSSH_PIDFILE \
        --remove-pidfile
    RETVAL="$?"
    return "${RETVAL}"
}

do_restart()
{
    exit 0
}


case "$1" in
    status)
        if init_is_upstart; then
            exit 1
        fi
        status_of_proc -p "${AUTOSSH_PIDFILE}" "${AUTOSSH}" "${NAME}"
        ;;
    start)
        if init_is_upstart; then
            exit 1
        fi
        log_begin_msg "Starting ${NAME}..."
        do_start
        log_end_msg "$?" # e.g. [ok], failed!, (warning)
        ;;
    stop)
        if init_is_upstart; then
            exit 1
        fi
        log_begin_msg "Stopping ${NAME}..."
        do_stop
        log_end_msg "$?"
        ;;
    restart)
        if init_is_upstart; then
            exit 1
        fi
        log_begin_msg "Restarting ${NAME}"
        do_restart
        log_end_msg "$?"
        ;;
    force-reload)
        exit 0
        ;;
    *)
        log_failure_msg "Usage: service ${NAME} {status|start|stop|restart}"
        ;;
esac

Comment Conventions for Init Scripts

Reference: Comment Conventions for Init Scripts

### BEGIN INIT INFO
# Provides:          scriptname
# Required-Start:    $network
# Required-Stop:     $network
# Should-Start:      cgroup-lite
# Should-Stop:       cgroup-lite
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: short_description
# Description:       multiline_description
### END INIT INFO
  • 以上注释必须在以下两行分隔符内
    ### BEGIN INIT INFO
    ### END INIT INFO
    
  • 前后两行分隔符内的注释要以 # 开头,并且后面至少要跟着一个空格。(Description 除外,Description注释可以是多行描述。)
    # {keyword}: arg1 [arg2 ...]
    
    • Provides: boot_facility_1 [boot_facility_2 ...]
      Boot facilities provided by this init script. 该脚本要启动的服务的名称。
    • Required-Start: boot_facility_1 [boot_facility_2 ...]
      Facilities which must be available during startup of this service. The init-script system should insure init scripts which provide the Required-Start facilities are started before starting this script. 启动该脚本服务的依赖设备。
    • Required-Stop: boot_facility_1 [boot_facility_2 ...]
      Facilities which must be available during the shutdown of this service. The init-script system should avoid stopping init scripts which provide the Required-Stop facilities until this script is stopped. 关闭该脚本服务的依赖设备。
    • Should-Start: boot_facility_1 [boot_facility_2 ...]
      Facilities which, if present, should be available during startup of this service. This allows for weak dependencies which do not cause the service to fail if a facility is not available. 启动该脚本服务应该提供的依赖,如果没有,也不会造成启动服务失败。
    • Should-Stop: boot_facility_1 [boot_facility_2]
      Facilities which should be available during shutdown of this service. 关闭该脚本服务应该提供的依赖。
    • Default-Start: run_level_1 [run_level_2 ...]
    • Default-Stop: run_level_1 [run_level_2 ...]
      which run levels should by default run the init script with a start (stop) argument to start (stop) the services controlled by the init script. 该脚本服务的运行等级(0~6)。
      Run Level:

      • 0: halt
      • 1: single user mode.
      • 2: multiuser with no network services exported.
      • 3: normal/full multiuser.
      • 4: reserved for local user, default is normal/full multiuser
      • 5: multiuser with a display manager or equivalent
      • 6: reboot
    • Short-Description: short_description
      Provide a brief description of the actions of the init script. Limited to a single line of text. 脚本服务简述,只能够为一行。
    • Description: multiline_description
      Provide a more complete description of the actions of the init script. May span mulitple lines. In a multiline description, each continuation line shall begin with a # followed by tab character or a # followed by at least two space characters. The multiline description is terminated by the first line that does not match this criteria. 脚本服务的详细描述,可以分为多行。多行描述的时候,第二行开始每一行必须要 # 开头接着一个 tab 或者至少两个空格。
  • Facility Names
    Boot facilities are used to indicate dependencies in initialization scripts, as defined in Comment Conventions for Init Scripts. Facility names are assigned to scripts by the Provides: keyword. Facility names that begin with a dollar sign ($) are reserved system facility names.

    Note: Facility names are only recognized in the context of the init script comment block and are not available in the body of the init script. In particular, the use of the leading $ character does not imply system facility names are subject to shell variable expansion, since they appear inside comments.

    • $local_fs: all local file systems are mounted.
    • $remote_fs: all remote file systems are available. In some configurations, file systems such as /usr may be remote. Many applications that require $local_fs will probably also require $remote_fs.
    • $network: basic networking is available. Example: a server program could listen on a socket.
    • $named: IP name-to-address translation, using the interfaces described in this specification, are available to the level the system normally provides them. Example: if a DNS query daemon normally provides this facility, then that daemon has been started.
    • $portmap: daemons providing SunRPC/ONCRPC portmapping service as defined in RFC 1833: Binding Protocols for ONC RPC Version 2 (if present) are running.
    • $syslog: system logger is operational.
    • $time: the system time has been set, for example by using a network-based time program such as ntp or rdate, or via the hardware Real Time Clock.

The comment conventions described are only required for init scripts installed by conforming applications. Conforming runtime implementations are not required to use this scheme in their system provided init scripts.

Init Script Functions

Reference: Init Script Functions

. /lib/lsb/init-functions

Each conforming init script shall execute the commands in the file /lib/lsb/init-functions in the current environment (see shell special built-in command dot).

  • init_is_upstart: If the currently running init daemon is upstart, return zero; if the calling init script belongs to package which also provides a native upstart job, it should generally exit non-zero in this case.
  • status_of_proc: Return LSB status.
    • $1: daemon,init script 启动的进程
    • $2: 进程名称
    • -p: optional, daemon 的 pid 文件
     status_of_proc -p "/var/run/nginx.pid" "/usr/bin/nginx" "nginx"
    
  • log_begin_msg: 记录并打印信息,一般用在执行某个操作的开始位置,记录信息可以在 /var/log/syslog 查看,int log_begin_msg (char *message),传入值是一个信息字符串.
    log_begin_msg  "Starting autossh..."
    
  • log_end_msg: int log_end_msg (int exitstatus),传入值是一个整型的退出状态值,根据状态值返回:[ok], failed!, (warning) 等等。
    start-stop-daemon --start ...
    log_end_msg "$?"
    
  • log_success_msg, log_failure_msg, log_warning_msg
    更多函数说明可以查看 /lib/lsb/init-functions

Init Script Actions

Reference: Init Script Actions

Init scripts provided by conforming applications shall accept a single argument which selects the action:

  • start: Start the service
  • stop: Stop the service
  • restart: Stop and restart the service if the service if already running, otherwise start the service.
  • try-restart: Restart the service if the service is already running.
  • reload: Cause the configuration of the service to be reloaded without actually stoping and restarting the service.
  • force-reload: Cause the configuration to be reloaded if the service support this, otherwise restart the service if it is running.
  • status: Print the current status of the service.

The start, stop, restart, force-reload and status actions shall be supported by all init scripts; the reload and try-restart actions are optional. Other init-scripts actions may be defined by the init script.

case "$1" in
    status)
        exit 0
        ;;
    start)
        exit 0
        ;;
    stop)
        exit 0
        ;;
    restart)
        exit 0
        ;;
    force-reload)
        exit 0
        ;;
    *)
        log_failure_msg "Usage: service ${NAME} {status|start|stop|restart}"
        ;;
esac

Installation and removal of Init Scripts

Reference: Linux – 管理系统服务

  • CentOS
    Redhat 提供了 chkconfig 命令来管理系统的服务:

    • chkconfig --list:所有服务列表
    • chkconfig --list serviceName:只显示 serverName 服务
    • chkconfig serviceName on:开启 serverName 服务的自动启动
    • chkconfig serviceName off:关闭 serverName 服务的自动启动
    • chkconfig --add serviceName:添加服务
    • chkconfig --del serviceName:删除服务
  • Ubuntu
    Ubuntu 是没有 chkconfig 命令的,而是提供了另外的命令来实现管理服务:

    • sudo update-rc.d serviceName defaults:添加服务,默认添加服务为自动启动,即 /etc/rc0.d//etc/rc6.d 各级别里面都添加了服务的启动软链接。
    • sudo update-rc.d serviceName remove:删除服务,默认会删除所有级别的服务,即彻底删除服务。

      如果,你想要配置各级别的启动情况,可以删除相应级别目录里面的服务软链接。

    • systemctl daemon-reload:修改过服务之后,用该命令来重新加载服务。

ssh 设置 sockets 代理

ssh -qTfnN -D 1080 root@alizs.cc
  • -q: Quiet modle. Causes most warning and diagnostic messages to be suppressed.
  • -T: Disable pseudo-terminal allocation.
  • -f: Requests ssh to go to background just before command execution. This is useful if ssh is going to ask for passwords or passphrases, but the user wants it in the background. This implies -n.
  • -n: Redirects stdin from /dev/null (actually, prevents reading from stdin). This must be used when ssh is run in the background.
  • -N: Do not execute a remote command. This is useful for just forwarding ports.
  • -D: Specifies a local “dynamic” application-level port forwarding.
  • root@alizs.cc: sockets 代理服务器

更多设置可以参考 ssh

这样就可以将请求通过 sockets5 代理地址 127.0.0.1:1080 转发到代理服务器 alizs.cc,完成翻墙了。不过,这种方式实现的代理,会存在 ssh 经常断开链接的问题。这时候,可以用 autossh 来解决。

使用 autossh 管理 ssh 进程

autossh 是一个用来启动并监控管理 ssh 的程序,在 ssh 断开的时候,autossh 会自动重启 ssh 进程。

安装 autossh (ubuntu)

sudo apt-get install autossh

使用方法:

autossh [-V] [-M monitor_port[:echo_port]] [-f] [SSH_OPTIONS]
  • -M: specifies monitor port. Overrides the environment variable AUTOSSH_PORT. 0 turns monitoring loop off. Alternatively, a port for an echo service on the remote machine may be specified.
  • -f: run in background (autossh handles this, and does not pass it to ssh). 后台运行,并且 -f 参数不会传给 ssh,因为 ssh 也有 -f 参数。比如,执行 autossh -M 0 -fqTnN -D 1080 root@alizs.cc 的时候,autossh 进程会启动一个 ssh 进程,并且 -qTnN -D 1080 root@alizs.cc 这些参数是会传给 ssh 的,但是 -f 不会传给 ssh。也就是说 ssh 进程会像这样:/usr/bin/ssh -qTnN -D 1080 root@alizs.cc
  • -V: print autossh version and exit.

使用实例:

autossh -M 0 -fqTN -D 1080 root@alizs.cc
  • -M: -M 0,表示通过 端口检测 ssh 的连接状态,断开后就会自动重连。
  • -f: 后台运行。
  • -qTN: 是 ssh 的参数。(autossh 不传 -f 给 ssh,-n 也就没意义了。)

运行以上命令之后,可以发现系统里多了两个进程,一个是 autossh,一个是 ssh。其中 ssh 是由 autossh 启动的,autossh 作为 ssh 的守护进程,监测 ssh 的状态,当 ssh 断开之后,会自动重启 ssh。

Reference: Virtualenv

安装

pip install virtualenv

创建虚拟环境

virtualenv ENV

ENV: 需要创建的虚拟环境的路径。ENV 可以是全局路径,也可以是相对路径。

以上命令创建的 Python 虚拟环境是没有从系统的 Python 中继承任何 Python 库的,是一个新的 Python 环境。其它选项:

  • -p PYTHON_EXE, --python=PYTHON_EXE
    默认创建的虚拟环境的 Python 版本是系统默认的 Python,但是可以通过添加该选项来指定虚拟环境的 Python 版本(前提是系统已有的 Python 版本)。

    virtualenv -p python3.5 ENV
    # or
    virtualenv --python=python3.5 ENV
    
  • --system-site-packages
    默认创建的虚拟环境是没有继承任何 Python 库的,如果需要继承系统默认 Python 的库,可以添加该选项:

    virtualenv --system-site-packages ENV
    
  • --always-copy
    默认情况下,创建虚拟环境需要的文件很多都是从系统软连接过来使用的。如果想要直接复制那些文件到虚拟环境而不是使用软连接,可以添加该选项:

    virutalenv --always-copy ENV
    

    更多参数选项可以参考 virtualenv,或 virtualenv --help

激活虚拟环境

激活虚拟环境,只需要 source 虚拟环境 ENV/bin/activate。如,虚拟环境目录为 /var/virtualenvs/scanner/,当前路径为 /home/lizs/

cd /var/virtualenvs/scanner/
source bin/activate

source /var/virtualenvs/scanner/bin/activate

成功激活之后,当前命令窗口的 python 就处于一个独立的虚拟环境的。pip freeze 可以看到当前的虚拟环境是没有安装任何 Python 的库的。

退出激活状态

如果想要退出激活状态的虚拟环境,可以执行:

deactivate

在非激活状态使用虚拟环境

  • 使用虚拟环境的 python 和相应的库
    如果,想要在非激活状态使用用虚拟环境的 Python 执行 Python 文件,可以指定 Python 解析器的路径为 /path/to/ENV/bin/python

  • 使用全局环境的 python,并且添加虚拟环境中的 python 库
    在 python 环境下,或执行文件中添加以下内容:

    activate_this = '/path/to/env/bin/activate_this.py'
    execfile(activate_this, dict(__file__=activate_this))
    

删除虚拟环境

删除虚拟环境,非激活状态下直接删除虚拟环境下的文件即可:

rm -r ENV

现有某个项目的数据库文件:app.sql,需要在命令行将 app.sql 数据库导入当前系统数据库。

  • 首先,创建一个相应的空数据库 app
# 登录数据
mysql -u root -p"123456"
# 创建数据库
CREATE DATABASE `app` DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
  • 导入 app.sql 文件
use app;
SOURCE /home/lizs/app.sql;  # app.sql 文件的绝对路径为:/home/lizs/app.sql

场景

在一个内存只有 700M 左右的服务器上面使用 git push 一个带 submodule 的项目的时候,出错:


fatal: Out of memory, malloc failed (tried to allocate 79691777 bytes)

当停止一些占用内存的服务之后,发现又可以正常 push。Stackoverflow 之后,解决办法有:添加内存或添加 swap 空间。cat /proc/swaps 之后发现服务器没有设置 swap 空间。

swap 简介

计算机的内存分为物理内存和虚拟内存。物理内存,即实际内存大小(RAM);虚拟内存,是由磁盘虚拟出来的,在内存不够的时候可以起到一个代替物理内存的作用,也就是 swap。

当产生一个新进程的时候,机器会判断当前物理内存是否有空闲运行该进程,如果没有,则会根据优先级将物理内存中运行的一个或多个进程挂起,并将挂起的进程放到 swap 中等待,然后,把这个新进程放入物理内存中运行。等到物理内存中有进程结束释放空间之后,再将在 swap 中挂起等待的进程调到物理内存中运行。

当物理内存使用达到一个比例之后,机器就会使用 swap 作为临时内存使用。这个比例保存在 /proc/sys/vm/swappiness 中,大小从 0 到 100。0,表示最大限度使用内存。更改该比例的大小:


echo 60 > /proc/sys/vm/swappiness

当物理内存和 swap 内存都使用完的时候,就会出现 out of memory 之类的错误。

添加/开启/关闭 swap

创建一个 swap 文件


dd if=/dev/zero of=/root/swap1 bs=1M count=1024

执行完之后就会产生文件 /root/swap1

为了安全起见,设置一下文件的权限


chmod 600 /root/swap1

将文件变为 swap 文件


mkswap /root/swap1

开启 swap


swapon /root/swap1

该命令还可以有其它参数,如 -p 设定 swap 的优先级。

使 swap 开机生效

/etc/fstab 文件主要存放文件系统的静态信息。在文件中添加:


/root/swap1 none swap defaults 0 0

各个参数之间可以用空格或 tab 键隔开。

关闭 swap


swapoff /root/swap1

参考 unix/linux: 2 ways to add swap space

Expect, an extension to the Tcl (Tool Command Language) scripting language, and it is a scripting language to interface with programs such as FTP, telnet, fsck, ssh, and others that normally cannot be automated from a shell script.

使用情景

Expect 可以实现自动交互的功能,所以,很常用的一种情景就是为我们自动输入密码。如:ssh 登录,git push/pull 等情景。

安装

  • Ubuntu

sudo apt-get install expect
  • CentOS

sudo yum install expect

Expect 需要 Tcl 编程语言的支持,所以必须先安装 Tcl。

实例

Expect 脚本使用的是 Tcl 的语法

  • 批量更新 git 仓库的内容(git pull)

#!/usr/bin/expect set password "123456" foreach app { /root/app/ic/ic-server/ /root/app/ic/ic-client/ } { cd $app spawn git pull expect { "Username*" {send "lizs\r"} "*assword*" { send $password interact } } }

更多使用参考 Expect-wiki.