HTTP 基本认证中,web 服务器拒绝一个事务,质询客户端,请用户提供有效的用户名和密码。同时,返回 401 状态码,并用 WWW-Authenticate 响应首部指定要访问的安全域(realm)。然后,客户端用 Authorization 请求首部发送经过 base64 加密之后的用户名密码(用户名:密码)给服务器。

Nginx 搭建 HTTP Basic Authorization

Nginx ngx_http_auth_basic_module 可以实现 HTTP Basic Authorization 协议。

location / {
    auth_basic 'authorization';
    auth_basic_user_file conf/htpasswd;
}
  • auth_basic: string | off,默认 off,不开启。开启 HTTP Basic Authorization 只需要填写一个字符串,该字符串会作为 realm 的值,在服务器质询客户端的返回头部信息 WWW-Authenticate 中显示,如:WWW-Authenticate: Basic realm="Authorication"

  • auth_basic_user_file: 指定访问的用户名和密码的配置文件,如,htpasswd

    # comment
    name1:password1
    name2:password2:comment
    
    • 可以用 # 注释
    • 可以设置多个用户名和密码,每行一个,用户名和密码之间用 : 隔开,注释也可以写在密码后面,用 : 隔开。
    • 用户名直接填写,但是密码需要经过加密。如,Linux 系统,密码 123456 可以用 openssl passwd 123456 生成。

假设,刚刚搭建的服务器地址为:127.0.0.1。从浏览器访问 http://127.0.0.1 就会收到一个 401 质询,弹出一个用户名和密码的输入框。用户输入账号和密码之后,浏览器会用 : 将其连接起来,编成 base64 编码,然后将其放在请求头部的 Authorization 中发送给服务端。服务端验证通过后就可以正常浏览页面的内容了。

HTTP 基础认证过程

假如,nginx 配置好的认证页面为 http://127.0.0.1

  • telnet 建立一条 http 连接
telnet 127.0.0.1 80
  • 发送正常的请求,会返回 401
HEAD / HTTP/1.1
Host: 172.16.105.114

HTTP/1.1 401 Unauthorized
Server: BDSCAN/1.5.0
Date: Wed, 17 Jan 2018 08:26:04 GMT
Content-Type: text/html
Content-Length: 195
Connection: keep-alive
WWW-Authenticate: Basic realm="authorization"
  • 发送带验证信息的请求
HEAD / HTTP/1.1
Host: 172.16.105.114
Authorization: Basic bGl6czoxMjM0NTY=

HTTP/1.1 200 OK
Server: BDSCAN/1.5.0
Date: Wed, 17 Jan 2018 08:26:59 GMT
Content-Type: text/html
Content-Length: 334
Last-Modified: Tue, 16 Jan 2018 08:55:10 GMT
Connection: keep-alive
ETag: "5a5dbdee-14e"
Accept-Ranges: bytes

验证信息放在请求头的 Authorization,即 Authorization: Basic base64-username-and-passwordbase64-username-and-password 为用户名和密码用 : 连接起来,并经过 base64 编码等到的字符串 (即上面的 bGl6czoxMjM0NTY=) 。Python(python2) 生成:

import base64

username = 'lizs'
password = '123456'
msg = base64.b64encode('%s:%s' % (username, password))

webbrowser – Convenient Web-browser controller

webbrowser 可以在命令行使用

python -m webbrowser -t/-n URL
  • -t: 在浏览器的新页面(tab)上打开 URL
  • -n: 在浏览器的新的窗口打开 URL(if possible)。

例子:在浏览器打开 http://alizs.cc,在命令行输入:

python -m webbrowser -t 'http://alizs.cc'
  • webbrowser.open(url, new=0, autoraise=True)
    用系统默认的浏览器打开 url

  • webbrowser.get(using=None)
    通过 using 的值,返回浏览器控制器对象。默认返回系统默认浏览器控制器对象。比如,系统默认的浏览器是 Chrome,现在想要用系统上安装的 FIrefox 浏览器打开 http://alizs.cc

    firefox = webbrowser.get('firefox')
    firefox.open('http://alizs.cc')
    

    已经预定义的浏览器类型,可以通过 get() 方法来获取。如果系统存在该类型浏览器,则会返回相应的浏览器控制器对象。

    Type Name Class Name
    ‘mozilla’ Mozilla(‘mozilla’)
    ‘firefox’ Mozilla(‘mozilla’)
    ‘netscape’ Mozilla(‘netscape’)
    ‘galeon’ galeon(‘galeon’)
    ‘epiphany’ Galeon(‘epiphany’)
    ‘skipstone’ BackgroundBrowser(‘skipstone’)
    ‘kfmclient’ Konqueror()
    ‘konqueror’ Konqueror()
    ‘kfm’ Konqueror()
    ‘mosaic’ BackgroundBrowser(‘mosaic’)
    ‘opera’ Opera()
    ‘grail’ Grail()
    ‘links’ GenericBrowser(‘links’)
    ‘elinks’ Elinks(‘elinks’)
    ‘lynx’ GenericBrowser(‘lynx’)
    ‘w3m’ GenericBrowser(‘w3m’)
    ‘windows-default’ WindowsDefault
    ‘macosx’ MacOSX(‘default’)
    ‘safari’ MacOSX(‘safari’)
    ‘google-chrome’ Chrome(‘google-chrome’)
    ‘chrome’ Chrome(‘chrome’)
    ‘chromium’ Chromium(‘chromium’)
    ‘chromium-browser’ Chromium(‘chromium-browser’)
  • webbrowser.register(name, constructor, instance=None)
    注册一个名为 name 的浏览器类型。注册成功之后,可以通过类型名 nameget() 该浏览器控制器对象。

    • name: 浏览器类型名称。
    • constructor: 可调用的对象名称,用来构建浏览器对象 instance。当 instance 不为 None 时,才有效。
    • instance: 浏览器对象。

    例一,用 constructor 来注册浏览器类型:

    def custom_browser():
        browser_path = '/usr/bin/firefox'
            return webbrowser.BackgroundBrowser(browser_path)
    
    webbrowser.register('custom_browser', custom_browser)
    controller = webbrowser.get('custom_browser')
    controller.open('http://alizs.cc')
    

    例二,用 instance 来注册浏览器类型:

    browser_path = '/usr/bin/firefox'
    custom_browser = webbrowser.BackgroundBrowser(browser_path)
    webbrowser.register('custom_browser', None, custom_browser)
    controller = webbrowser.get('custom_browser')
    controller.open('http://alizs.cc')
    

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
    # 检测到系统中有 mysql-libs-5.1.73-3.el6_5.x86_64
    rpm -qa | grep mysql   
    # 删除旧版本MySQL包和相关的依赖
    rpm -e --nodeps mysql-libs-5.1.73-3.el6_5.x86_64
    
  • 添加 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-11.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