linux进程管理工具-supervisor

作者:matrix 发布时间:2017年2月13日 分类:Linux 零零星星

Linux后台守护进程化有nohup,screen命令可一般解决。但突发崩溃情况就不能很好的保证进程在后台的驻留。
supervisor是一个python脚本编写的工具,可以起到很好的管理、监控进程的作用。

安装

Debian类系统安装:

pip install supervisor #建议使用方式 避免旧版本导致的一系列问题

#或者
sudo apt-get install supervisor 

选择y确认操作后即可安装完成。

配置

  1. 查看supervisord.conf
    • supervisord已自动启动
      使用 ps -aux|grep supervisord 查看supervisord进程信息,-c参数就是指定使用的配置文件
      如图 我这里的配置文件就是/etc/supervisor/supervisord.conf

    图片3665-linux进程管理工具-supervisor

    • supervisord 手动启动
      执行supervisord命令即可启动supervisord工具。
      默认会读取/etc/supervisord.conf配置文件,若不存在可能就需要自己手动创建:
    $ echo_supervisord_conf > /etc/supervisord.conf
    

    文件末尾include位置是定义需要管理的进程配置信息载入路径:

    [include]
    files = /etc/supervisord.d/*.ini
    

    这里表示supervisord会读取/etc/supervisord.d/目录下的所有ini配置文件;这里支持多个文件列表的传入 用空格隔开即可。如:

    [include]
    files = /etc/supervisord.d/*.ini /home/supervisord_conf/*.ini
    
  2. 创建进程命令配置ini文件

    进入/etc/supervisord.d/目录,创建ini文件

    e.g. ws.ini:
    文件名称可自定

    [program:ws] 
    user=www ;执行进程的用户
    command=php /home/wwwroot/chat.hhtjim.com/wsServer.php
    autostart=true ;是否随系统自动启动
    autorestart=true ;自动重启
    startretries=10 ;启动失败时的最多重试次数   默认3
    redirect_stderr = true  ; 把 stderr 重定向到 stdout,默认 false
    stdout_logfile_maxbytes = 20MB  ; stdout 日志文件大小,默认 50MB
    stdout_logfile_backups = 2     ; stdout 日志文件备份数
    ; stdout 日志文件,需要注意当指定目录不存在时无法正常启动,所以需要手动创建目录(supervisord 会自动创建日志文件)
    stdout_logfile = /root/logs/rss2channel_stdout.log
    

    说明:
    program 表示自定义的任务名称
    command 执行的命令

    其他配置官方手册:
    http://supervisord.org/configuration.html#program-x-section-values

启动

supervisord -c /etc/supervisord.conf
/etc/supervisord.conf为默认的配置文件,可自定

查看

  1. cli方式
    > supervisorctl #进入命令行
    > reload #重新载入配置
    > status #状态查看
    
  2. web页面方式
    supervisord.conf文件中需要配置

    [inet_http_server]         ; inet (TCP) server disabled by default
    port=127.0.0.1:9001        ; (ip_address:port specifier, *:port for all iface)
    username=user              ; (default is no username (open server))
    password=123               ; (default is no password (open server))
    

    设置后执行supervisorctl reload重启再访问IP:9001就能监控supervisord的运行状态。

报错

unix:///var/run/supervisor.sock no such file错误

确保已经启动supervisord进程。

ps -aux|grep supervisord #查看是否存在进程

unix:///tmp/supervisor.sock no such file 错误

解决办法:

vi /etc/supervisord.conf
#把sock文件所在tmp目录的配置修改为/var/run目录

主要修改如下配置:

[unix_http_server]
;file=/tmp/supervisor.sock   ; (the path to the socket file)
file=/var/run/supervisor.sock   ;

......

[supervisorctl]
;serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL  for a unix socket
serverurl=unix:///var/run/supervisor.sock ; 修改为 /var/run 目录,避免被系统删除

修改操作参考:
http://www.cashqian.net/blog/001472975510127673ea63db9234c4e8293cf43cefcafde000

最后执行更新:

supervisorctl update

socket.py line: 224错误

如果修改上面tmp目录再更新出现错误:

error: <class 'socket.error'>, [Errno 2] No such file or directory: file: /usr/lib64/python2.7/socket.py line: 224

解决:
先执行启动命令:supervisordsupervisorctl update
如果还是报错,那需要重新安装。因为版本太旧会导致这种问题

uwsgi无法启动

取消或注释uwsgi配置文件中的daemonize

附 使用的supervisord.conf:
; Sample supervisor config file.

[unix_http_server]
file=/var/run/supervisor.sock   ; (the path to the socket file)
;chmod=0700                 ; sockef file mode (default 0700)
;chown=nobody:nogroup       ; socket file uid:gid owner
;username=user              ; (default is no username (open server))
;password=123               ; (default is no password (open server))

;[inet_http_server]         ; inet (TCP) server disabled by default
;port=127.0.0.1:9001        ; (ip_address:port specifier, *:port for all iface)
;username=user              ; (default is no username (open server))
;password=123               ; (default is no password (open server))

[supervisord]
logfile=/var/log/supervisor/supervisord.log  ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB       ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10          ; (num of main logfile rotation backups;default 10)
loglevel=info               ; (log level;default info; others: debug,warn,trace)
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false              ; (start in foreground if true;default false)
minfds=1024                 ; (min. avail startup file descriptors;default 1024)
minprocs=200                ; (min. avail process descriptors;default 200)
;umask=022                  ; (process file creation umask;default 022)
;user=chrism                 ; (default is current user, required if root)
;identifier=supervisor       ; (supervisord identifier, default is 'supervisor')
;directory=/tmp              ; (default is not to cd during start)
;nocleanup=true              ; (don't clean up tempfiles at start;default false)
;childlogdir=/tmp            ; ('AUTO' child log dir, default $TEMP)
;environment=KEY=value       ; (key value pairs to add to environment)
;strip_ansi=false            ; (strip ansi escape codes in logs; def. false)

; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL  for a unix socket
;serverurl=http://127.0.0.1:9001 ; use an http:// url to specify an inet socket
;username=chris              ; should be same as http_username if set
;password=123                ; should be same as http_password if set
;prompt=mysupervisor         ; cmd line prompt (default "supervisor")
;history_file=~/.sc_history  ; use readline history if available

; The below sample program section shows all possible program subsection values,
; create one or more 'real' program: sections to be able to control them under
; supervisor.

;[program:theprogramname]
;command=/bin/cat              ; the program (relative uses PATH, can take args)
;process_name=%(program_name)s ; process_name expr (default %(program_name)s)
;numprocs=1                    ; number of processes copies to start (def 1)
;directory=/tmp                ; directory to cwd to before exec (def no cwd)
;umask=022                     ; umask for process (default None)
;priority=999                  ; the relative start priority (default 999)
;autostart=true                ; start at supervisord start (default: true)
;autorestart=true              ; retstart at unexpected quit (default: true)
;startsecs=10                  ; number of secs prog must stay running (def. 1)
;startretries=3                ; max # of serial start failures (default 3)
;exitcodes=0,2                 ; 'expected' exit codes for process (default 0,2)
;stopsignal=QUIT               ; signal used to kill process (default TERM)
;stopwaitsecs=10               ; max num secs to wait b4 SIGKILL (default 10)
;user=chrism                   ; setuid to this UNIX account to run the program
;redirect_stderr=true          ; redirect proc stderr to stdout (default false)
;stdout_logfile=/a/path        ; stdout log path, NONE for none; default AUTO
;stdout_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
;stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
;stdout_capture_maxbytes=1MB   ; number of bytes in 'capturemode' (default 0)
;stdout_events_enabled=false   ; emit events on stdout writes (default false)
;stderr_logfile=/a/path        ; stderr log path, NONE for none; default AUTO
;stderr_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
;stderr_logfile_backups=10     ; # of stderr logfile backups (default 10)
;stderr_capture_maxbytes=1MB   ; number of bytes in 'capturemode' (default 0)
;stderr_events_enabled=false   ; emit events on stderr writes (default false)
;environment=A=1,B=2           ; process environment additions (def no adds)
;serverurl=AUTO                ; override serverurl computation (childutils)

; The below sample eventlistener section shows all possible
; eventlistener subsection values, create one or more 'real'
; eventlistener: sections to be able to handle event notifications
; sent by supervisor.

;[eventlistener:theeventlistenername]
;command=/bin/eventlistener    ; the program (relative uses PATH, can take args)
;process_name=%(program_name)s ; process_name expr (default %(program_name)s)
;numprocs=1                    ; number of processes copies to start (def 1)
;events=EVENT                  ; event notif. types to subscribe to (req'd)
;buffer_size=10                ; event buffer queue size (default 10)
;directory=/tmp                ; directory to cwd to before exec (def no cwd)
;umask=022                     ; umask for process (default None)
;priority=-1                   ; the relative start priority (default -1)
;autostart=true                ; start at supervisord start (default: true)
;autorestart=unexpected        ; restart at unexpected quit (default: unexpected)
;startsecs=10                  ; number of secs prog must stay running (def. 1)
;startretries=3                ; max # of serial start failures (default 3)
;exitcodes=0,2                 ; 'expected' exit codes for process (default 0,2)
;stopsignal=QUIT               ; signal used to kill process (default TERM)
;stopwaitsecs=10               ; max num secs to wait b4 SIGKILL (default 10)
;user=chrism                   ; setuid to this UNIX account to run the program
;redirect_stderr=true          ; redirect proc stderr to stdout (default false)
;stdout_logfile=/a/path        ; stdout log path, NONE for none; default AUTO
;stdout_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
;stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
;stdout_events_enabled=false   ; emit events on stdout writes (default false)
;stderr_logfile=/a/path        ; stderr log path, NONE for none; default AUTO
;stderr_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
;stderr_logfile_backups        ; # of stderr logfile backups (default 10)
;stderr_events_enabled=false   ; emit events on stderr writes (default false)
;environment=A=1,B=2           ; process environment additions
;serverurl=AUTO                ; override serverurl computation (childutils)

; The below sample group section shows all possible group values,
; create one or more 'real' group: sections to create "heterogeneous"
; process groups.

;[group:thegroupname]
;programs=progname1,progname2  ; each refers to 'x' in [program:x] definitions
;priority=999                  ; the relative start priority (default 999)

; The [include] section can just contain the "files" setting.  This
; setting can list multiple files (separated by whitespace or
; newlines).  It can also contain wildcards.  The filenames are
; interpreted as relative to this file.  Included files *cannot*
; include files themselves.

[include]
files = /etc/supervisord.d/*.ini

环境变量无法读取

本来在/etc/profile文件末尾添加环境变量的声明,也执行了source

## production environment
export RUN_ENV="TEST"

但是今天意外发现进程服务无法读取到环境变量信息。

需要配置supervisord段的environment,让supervisord能正常读取指定环境变量RUN_ENV

[supervisord]
environment=RUN_ENV="%(ENV_RUN_ENV)s"

可以在/etc/supervisord.conf文件中新增supervisord,也可以在/etc/supervisord.d/*.ini中的进程文件中添加

意外FATAL

如果长时间执行有可能会造成意外中断,这里最好做定时检测重启

check.sh

#!/bin/bash

status=`/usr/bin/supervisorctl status rss2channel|awk '{print $2}'`
if [ $status == 'STOPPED' -o $status == 'FATAL' ]; then
        /usr/bin/supervisorctl restart rss2channel >/dev/null 2&>1
fi

检测STOPPED 或者 FATAL状态就执行重启
rss2channel 为配置名称
再配合crontab定时任务 每小时检测

0 */1 * * *  /bin/bash /root/check.sh

扩展/修改启动脚本的配置

默认脚本启动目录:/etc/supervisord.d

如果需要新添加启动脚本eth_kline.ini配置而不想重载reload所有。可以先执行reread,再add就可以了

$ supervisorctl reread
>>> eth_kline: available

$ supervisorctl add  eth_kline
>>> eth_kline: added process group

这样即可无痛扩展 不用重启所有已运行的脚本

如果需要修改也差不多 要使用update命令:

$ supervisorctl reread eth_kline
>>> eth_kline: changed

$ supervisorctl update eth_kline
>>> eth_kline: stopped
>>> eth_kline: updated process group

通配符操作

默认supervisorctl操作的名称不支持通配符 但是可以使用awk来达到效果

比如我想重启所有包含_kline关键字的进程脚本名 /usr/bin/supervisorctl restart *_kline ,让它匹配*_kline符合的name进程脚本名,然而supervisorctl不支持。

解决办法:

/usr/bin/supervisorctl restart `/usr/bin/supervisorctl status |awk '{print $1}'|grep -E  ".*_kline"`

参考:
http://supervisord.org
http://liyangliang.me/posts/2015/06/using-supervisor/
http://www.tuicool.com/articles/Ejm2u2
http://stackoverflow.com/questions/16171338/supervisord-cant-find-command-in-virtualenv-folder
https://neo1218.github.io/supervisor/
https://blog.csdn.net/qq_27754983/article/details/78782866
https://serverfault.com/questions/511707/supervisord-error-class-socket-error

mysql 启动失败

作者:matrix 发布时间:2017年2月11日 分类:零零星星

重启系统发现mysql启动失败。
环境为 ubuntu Lnmp

Starting MySQL
. * The server quit without updating PID file (/var/run/mysqld/mysqld.pid).

/var/run/mysqld/ 目录中没有pid文件

找到网上说的文件权限、磁盘已满,这些都不符合情况。

解决

删除文件my.cnf
> rm /etc/mysql/my.cnf

启动mysql

lnmp mysql start

最后启动成功就ok
peace

参考:

[分享]MySQL启动报错 The server quit without updating PID file (/var/run/mysqld/mysqld.pid) 解决


https://bbs.vpser.net/viewthread.php?tid=13217

ubuntu安装Let’s Encrypt证书实测

作者:matrix 发布时间:2017年1月15日 分类:兼容并蓄 零零星星

Let’s Encrypt证书出来已经有很长时间,之前用主机未到期,也就干瞪眼。
现在手上拿了一台有设备,其实算下来价格也都差不多,国外的速度是慢点,但是好处很多。

测试环境:
ubuntu 14 64bit
lnmp 1.3

获取证书

git clone https://github.com/letsencrypt/letsencrypt 
cd letsencrypt
./letsencrypt-auto certonly --standalone --email hhtjim@foxmail.com -d hhtjim.com -d www.hhtjim.com
# 若服务器已经占用80端口开启webserver则只需执行webroot:
#  ./letsencrypt-auto certonly --webroot --email hhtjim@foxmail.com -d link.hhtjim.com

执行完上面三个命令之后会有图形界面出现
gui图形界面
选择Agree之后出现这个也就完成了证书的获取

安装证书

修改域名对应下的nginx配置
进入/usr/local/nginx/conf/vhost目录找到和域名同名的conf文件
在server代码块中添加:

listen 443 ssl;
        #listen [::]:80;
        ssl on;
        ssl_certificate /etc/letsencrypt/live/域名/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/域名/privkey.pem;

参考如下完整配置

server
    {
        listen 80;
        listen 443 ssl;
        #listen [::]:80;
        ssl on;
        ssl_certificate /etc/letsencrypt/live/hhtjim.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/hhtjim.com/privkey.pem;

        server_name hhtjim.com www.hhtjim.com;
        index index.html index.htm index.php default.html default.htm default.php;
        root  /home/wwwroot/hhtjim.com;

        include other.conf;
        #error_page   404   /404.html;
        include enable-php.conf;
        include wordpress.conf;

                if ($http_host !~ "^www.hhtjim.com$"){
                    rewrite  ^(.*)    https://www.hhtjim.com$1 permanent;
                }
                if ($scheme = "http"){ 
                        rewrite ^(.*)$  https://$host$1 permanent;
                }

        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
        {
            expires      30d;
        }

        location ~ .*\.(js|css)?$
        {
            expires      12h;
        }

        location ~ /\.
        {
            deny all;
        }

        access_log  /home/wwwlogs/hhtjim.com.log;
    }

接着准备重启nginx:lnmp nginx restart

参考:loazuo

更新操作

按照网上大多执行的命令我这里就会出现交互界面,需要手动选择webroot目录

How would you like to authenticate with the ACME CA? 

       x x          1  Place files in webroot directory (webroot)           x x  
       x x          2  Spin up a temporary webserver (standalone)  


还好找到办法,只需要添加参数 --webroot -w 设置好存放web路径即可。最终参考如下

ubuntu下保存为sh文件。记得附加x执行权限。然后执行该sh文件即可自动更新证书.

#!/bin/sh
~/letsencrypt/letsencrypt-auto certonly --webroot -w /home/wwwroot/www.hhtjim.com/ --renew-by-default --email hhtjim@foxmail.com -d hhtjim.com -d www.hhtjim.com && lnmp nginx restart

若报错Failed authorization procedure...则需要修改-w参数为网站根目录
如:

-w /home/wwwroot/hhtjim.com/

且nginx配置中将.well-known加入白名单:

location ~ /.well-known {
            allow all;
    }

参考:
http://letsencrypt.readthedocs.io/en/latest/using.html
https://www.ubock.com/article/25
https://stackoverflow.com/questions/42269107/using-certbot-to-apply-lets-encrypt-certificate-failed-authorization-procedure

最后的定时执行

修改定时任务 crontab -e
0 0 1 * * /root/updateLetsEncrypt.sh #每月1号执行sh脚本

重启定时服务 /etc/init.d/cron restart

peace

飘雪效果

作者:matrix 发布时间:2017年1月13日 分类:零零星星

这个季节看到TGP的LOL新闻页面的飘雪效果挺好看的。顺手就copy了下
飘雪效果网上貌似大多数代码都是http://x-team.com 。
css,js,png文件都整理出来了也就记录下。 都取自15w.com

直接盗链

建议代码放到html中的body标签中的底部加载

<link rel="stylesheet" href="//www.15w.com/ui/pages/others/2016/snow/css/snow.css?v3" type="text/css" />
<script type="text/javascript" src="//www.15w.com/ui/pages/others/2016/snow/js/snow.js?v5"></script>
<script>
    createSnow("img/", 30);
</script>

若是WordPress

add_action('wp_footer', 'snow_footer');
function snow_footer()
{

    if ('1' === date("n")) {//一月份才会有飘雪效果 
        print <<<R
<link rel="stylesheet" href="//www.15w.com/ui/pages/others/2016/snow/css/snow.css?v3" type="text/css" />
<script type="text/javascript" src="//www.15w.com/ui/pages/others/2016/snow/js/snow.js?v5"></script>
<script>
    createSnow("img/", 30);
</script>
R;
    }
}

文件本地化

文件: https://pan.baidu.com/s/1i5cAnhb#383t
提取码在#字符后面

注意需要修改snow.js 105行处代码

peace


P.S. 180206
jd页面的飘雪效果。依赖JQ
图片3891-飘雪效果

页面中添加画布div容器
<div class="snow-container" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 100001;"></div>

然后引入js
three.js和snow.js(可修改为本地的离线图片)

资源包:jd-snow

wp替换emoji源地址s.w.org

作者:matrix 发布时间:2017年1月11日 分类:Wordpress 零零星星

wp的页面都会加载类似下面的的javascript代码用来显示emoji表情。

{
    "baseUrl": "https://s.w.org/images/core/emoji/2.2.1/72x72/",
    "ext": ".png",
    "svgUrl": "https://s.w.org/images/core/emoji/2.2.1/svg/",
    "svgExt": ".svg",
    "source": {
        "concatemoji": "https://static.hhtjim.com/wp-includes/js/wp-emoji-release.min.js?ver=dd887"
    }
}

s.w.org毕竟是墙外的东西,很麻烦。将其替换为国内镜像地址。
WordPress functions中添加

替换emoji源  s.w.org
function filter_baseurl()
{
    return set_url_scheme('//twemoji.maxcdn.com/72x72/');

}

function ilter_svgurl()
{
    return set_url_scheme('//twemoji.maxcdn.com/svg/');
}

add_filter('emoji_url', 'filter_baseurl');
add_filter('emoji_svg_url', 'ilter_svgurl');

lnmp 1.3 安装 typecho 404错误

作者:matrix 发布时间:2017年1月2日 分类:零零星星

修改对应域名的nginx配置文件
vi /usr/local/nginx/conf/vhost/域名

重新配置nginx的配置文件

server
    {
    。。。。。。
        <strong>include typecho.conf;
        include enable-php-pathinfo.conf;</strong>
 。。。。。。
   }

参考:https://bbs.vpser.net/thread-13341-1-1.html

ThinkPHP 3.2 添加软删除功能

作者:matrix 发布时间:2016年12月31日 分类:零零星星

类似于TP5框架的软删除功能

软删除的作用就是把数据加上删除标记,而不是真正的删除,同时也便于需要的时候进行数据的恢复。

这里以数据库表Dynamics为例

执行SQL语句给表新建字段delete_time:
ALTER TABLE sx_dynamics ADD `delete_time` char(13) DEFAULT NULL COMMENT '删除时间';

新建Model层文件

<?php 
/**
 * Created by PhpStorm.
 * User: pang
 */
namespace Home\Model;

use Think\Model;
use Think\Page;

class DynamicsModel extends Model
{
    /**
     * 重写Model删除方法 实现TP5类似的软删除
     *
     * @param bool $trueDel 是否真实删除数据
     * @return mixed
     */
    public function delete($trueDel = false)
    {
        if ($trueDel) {
            return parent::delete();
        }
        $data['delete_time'] = time();
        return parent::save($data);
    }
}

在Controller层

//使用D()方法实例化Model 调用重写的delete 软删除方法
D('dynamics')->where($w)->delete();

查询的where条件:

$where['delete_time'] = array('exp', 'IS NULL');//没有删除的数据
$where['delete_time'] = array('exp', 'IS NOT NULL');//已经删除的数据

-EOF-
for mac

Elementary OS安装PHP测试环境 lnmp一键安装包

作者:matrix 发布时间:2016年12月30日 分类:零零星星

安装环境

2016-12-2202

按照ubuntu正常安装的时候却报错:
Lnmp Unable to get linux distribution name, or do NOT support the current di

原因是因为 /etc/issue 中记录的是linux发行版本:elementary OS Loki
lnmp脚本无法识别出为ubuntu的系统内核

修改main.sh文件

文件路径:/lnmp1.3/include/main.sh
搜索关键字Get_Dist_Name()查找该方法替换为一下内容:

Get_Dist_Name()
{
    if grep -Eqi "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release; then
        DISTRO='CentOS'
        PM='yum'
    elif grep -Eqi "Red Hat Enterprise Linux Server" /etc/issue || grep -Eq "Red Hat Enterprise Linux Server" /etc/*-release; then
        DISTRO='RHEL'
        PM='yum'
    elif grep -Eqi "Aliyun" /etc/issue || grep -Eq "Aliyun" /etc/*-release; then
        DISTRO='Aliyun'
        PM='yum'
    elif grep -Eqi "Fedora" /etc/issue || grep -Eq "Fedora" /etc/*-release; then
        DISTRO='Fedora'
        PM='yum'
    elif grep -Eqi "Debian" /etc/issue || grep -Eq "Debian" /etc/*-release; then
        DISTRO='Debian'
        PM='apt'
    elif grep -Eqi "Ubuntu" /etc/issue || grep -Eq "Ubuntu" /etc/*-release; then
        DISTRO='Ubuntu'
        PM='apt'
    elif grep -Eqi "Raspbian" /etc/issue || grep -Eq "Raspbian" /etc/*-release; then
        DISTRO='Raspbian'
        PM='apt'
    elif grep -Eqi "Deepin" /etc/issue || grep -Eq "Deepin" /etc/*-release; then
        DISTRO='Deepin'
        PM='apt'
    else
        DISTRO='Ubuntu'
        PM='apt'
    fi
    Get_OS_Bit
}

或者下载main.sh覆盖:http://pan.baidu.com/s/1hsyVSw8
然后再执行install.sh脚本安装就可以了

%e5%b1%8f%e5%b9%95%e6%88%aa%e5%9b%be-2016-12-22