JoyLau's Blog

JoyLau 的技术学习与思考

背景

最近维护了一个比较老的项目,操作数据库直接用的 Spring 的 JdbcTemplate,有很多地方我们传入的参数都是不确定的
简单的还好,复杂的 sql 语句在代码里用字符串拼接起来简直不能忍,
又不想对原来的项目有什么大的改动,就想这能不能在现在的基础上优化一下
还好有 NamedParameterJdbcTemplate

解释

具名参数: SQL 按名称(以冒号开头)而不是按位置进行指定. 具名参数更易于维护, 也提升了可读性. 具名参数由框架类在运行时用占位符取代
具名参数只在 NamedParameterJdbcTemplate 中得到支持。NamedParameterJdbcTemplate可以使用全部jdbcTemplate方法

初始化

  1. 该类位于 org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate
  2. 有2个构造方法,参数分别是 DataSource 和 JdbcOperations
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* Create a new NamedParameterJdbcTemplate for the given {@link DataSource}.
* <p>Creates a classic Spring {@link org.springframework.jdbc.core.JdbcTemplate} and wraps it.
* @param dataSource the JDBC DataSource to access
*/
public NamedParameterJdbcTemplate(DataSource dataSource) {
Assert.notNull(dataSource, "DataSource must not be null");
this.classicJdbcTemplate = new JdbcTemplate(dataSource);
}

/**
* Create a new NamedParameterJdbcTemplate for the given classic
* Spring {@link org.springframework.jdbc.core.JdbcTemplate}.
* @param classicJdbcTemplate the classic Spring JdbcTemplate to wrap
*/
public NamedParameterJdbcTemplate(JdbcOperations classicJdbcTemplate) {
Assert.notNull(classicJdbcTemplate, "JdbcTemplate must not be null");
this.classicJdbcTemplate = classicJdbcTemplate;
}
  1. 实例化 bean 只要将 dataSource 或者 JdbcTemplate 传入到构造参数即可
1
2
3
4
<bean id="namedParameterJdbcTemplate"
class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>

使用

  1. 注入 namedParameterJdbcTemplate

参数的传入

namedParameterJdbcTemplate 参数传入有 2 中方法:

  1. Map<String, ?> paramMap 我们熟知的 map

  2. SqlParameterSource paramSource
    该接口默认的实现有三个类:

    MapSqlParameterSource 实现非常简单,只是封装了java.util.Map;
    当 Map<String, ?> paramMap 用吧 或者 new MapSqlParameterSource(paramMap) 参数为 map

    BeanPropertySqlParameterSource 封装了一个JavaBean对象,通过JavaBean对象属性来决定命名参数的值。
    new BeanPropertySqlParameterSource(dto) new 出一个 BeanPropertySqlParameterSource 对象,构造方法传入实体类即可,绝大部分情况下我们都使用这种方式

    EmptySqlParameterSource 一个空的SqlParameterSource ,常用来占位使用
    没用过

数据返回

  1. 返回 Map

  2. 返回 RowMapper 包装好的实体类,该类有2中实现
    SingleColumnRowMapper ,sql结果为一个单列的数据,如List , List,String,Integer等

    BeanPropertyRowMapper, sql结果匹配到对象 List< XxxVO> , XxxVO

示例

1
2
3
4
5
6
7
KnowledgeInfo info = new KnowledgeInfo();
info.setAuditState("1");
List<KnowledgeInfo> infos = namedParameterJdbcTemplate.query(
sql,
new BeanPropertySqlParameterSource(info),
new BeanPropertyRowMapper<>(KnowledgeInfo.class)
);

注意: sql 语句中的参数使用 :参数名 进行占位

背景

今天连接远程服务器发生了以下的错误

1
ssh_exchange_identification: read: Connection reset

我想应该是我当前的 IP 地址被 DenyHosts 加入了黑名单
本来想只要将当前的 ip 地址在黑名单中去掉就可以了
没想到事实并不是如此,为此还查资料花费了一点功夫
现记录下来

解决

  1. 停用 DenyHosts : systemctl stop denyhosts.service
  2. 删除黑名单中当前的ip地址: vim /etc/hosts.deny
  3. 进入 /var/lib/denyhosts
1
2
3
4
5
6
7
8
9
10
-rw-r--r-- 1 root root    39 2月  16 2015 allowed-hosts
-rw-r--r-- 1 root root 71451 7月 19 10:58 hosts
-rw-r--r-- 1 root root 71270 7月 19 10:58 hosts-restricted
-rw-r--r-- 1 root root 71433 7月 19 10:58 hosts-root
-rw-r--r-- 1 root root 71280 7月 19 10:58 hosts-valid
-rw-r--r-- 1 root root 105 7月 19 10:58 offset
-rw-r--r-- 1 root root 0 7月 19 10:58 suspicious-logins
-rw-r--r-- 1 root root 44731 7月 19 10:58 users-hosts
-rw-r--r-- 1 root root 50925 7月 19 10:58 users-invalid
-rw-r--r-- 1 root root 643 7月 19 10:58 users-valid
  1. 依次在上面各个文件中移除自己当前的IP地址
  2. 如果要将当前的IP地址添加到白名单中,可以在 /etc/hosts.allow 添加
    sshd: ip地址
    allowed-hosts 添加 IP地址
  3. 重启 DenyHosts

注意: 这些文件里有很多被拉入黑名单的IP地址,vim编辑的时候可以在命令行模式下使用 /ip地址 来查找, n 和 N 上下翻动,再在命令行模式下 :noh 取消查找

背景

自从入了 MBP 后就被其默认的字体显示效果吸引了,在编辑器里写代码更是舒服,于是想着把 Mac 下的字体也移植到 Ubuntu 下,但是显示效果并不是特别的好,尤其是粗体字的显示

前后对比

左侧使用前,右侧使用后

使用步骤

  1. 该字体为开源字体,字体地址: https://github.com/vjpr/monaco-bold
  2. 复制到 /usr/share/fonts
  3. fc-cache -fv 生成字体缓存

我的 1080P 分辨率,我的配置如下:
MonacoB2

2018-07-18 14:22:05 更新

看到一篇关于 Ubuntu 字体渲染问题的文章: 修复 Ubuntu 中文字体渲染 https://i-meto.com/fix-chinese-font-display/

  1. 原来阿里云给每个账户都有分配专属的加速器地址

  2. 登录阿里云控制台

  3. 进入容器镜像服务,点击最下方的镜像加速器,会出现个人的专属加速器地址,我的是: https://0ppztvl0.mirror.aliyuncs.com

  4. Docker客户端版本大于1.10.0的用户,创建 /etc/docker/daemon.json
    {
    “registry-mirrors”: [“https://0ppztvl0.mirror.aliyuncs.com"]
    }

    sudo systemctl daemon-reload
    sudo systemctl restart docker

背景

docker 安装完成后,其他用户只能使用 sudo 访问它。docker 守护进程始终以 root 用户身份运行,这样每次在使用命令时都需要在前面加上sudo,这很不方便。
有没有什么方式能够解决?
官方文档地址: https://docs.docker.com/install/linux/linux-postinstall/

解决

docker 守护进程绑定至 Unix 套接字,而不是 TCP 端口。默认情况下,该 Unix 套接字由用户 root 所有,而其他用户只能使用 sudo 访问它。docker 守护进程始终以 root 用户身份运行。

在使用 docker 命令时,如果您不想使用 sudo,请创建名为 docker 的 Unix 组并向其中添加用户。docker 守护进程启动时,它将使 Unix 套接字的所有权可由 docker 组进行读取/写入。

警告: docker 组将授予等同于 root 用户的特权。如需有关此操作如何影响系统安全性的详细信息,请参阅 Docker 守护进程攻击面。

如需创建 docker 组并添加您的用户,请执行下列操作:

  1. 创建 docker 组。
1
$ sudo groupadd docker

向 docker 组中添加您的用户。

1
$ sudo usermod -aG docker $USER

注销并重新登录,以便对您的组成员资格进行重新评估。

如果在虚拟机上进行测试,可能必须重启此虚拟机才能使更改生效。

在桌面 Linux 环境(例如,X Windows)中,彻底从您的会话中注销,然后重新登录。

验证您是否可以在不使用 sudo 的情况下运行 docker 命令。

1
$ docker run hello-world

此命令将下载一个测试镜像并在容器中运行它。容器运行时,它将输出一条参考消息并退出。

经过实测,Ubuntu通过源添加安装最新版 Docker 时,已经自动添加了 docker 组,只需要将 当前用户添加到组里面在重新登录就可以了。

ElasticSearch 环境准备

中文分词实现

  1. 安装插件 https://github.com/medcl/elasticsearch-analysis-ik

  2. 测试分词:

ik_max_word会将文本做最细粒度的拆分;
ik_smart 会做最粗粒度的拆分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
http://192.168.10.74:9200/_analyze/ POST
{
"analyzer": "ik_max_word",
"text": "绝地求生是最好玩的游戏"
}


{
"analyzer": "ik_smart",
"text": "绝地求生是最好玩的游戏"
}


{
"analyzer": "standard",
"text": "绝地求生是最好玩的游戏"
}
  1. 创建索引

    http://192.168.10.74:9200/ik-index PUT
    指定使用 ik_max_word 分词器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
"settings" : {
"analysis" : {
"analyzer" : {
"ik" : {
"tokenizer" : "ik_max_word"
}
}
}
},
"mappings" : {
"article" : {
"dynamic" : true,
"properties" : {
"subject" : {
"type" : "string",
"analyzer" : "ik_max_word"
},
"content" : {
"type" : "string",
"analyzer" : "ik_max_word"
}
}
}
}
}

  1. 添加数据

  2. 查询:
    http://192.168.10.74:9200/index/_search POST

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    {
    "query": {
    "match": {
    "subject": "合肥送餐冲突"
    }
    },
    "highlight": {
    "pre_tags": ["<span style = 'color:red'>"],
    "post_tags": ["</span>"],
    "fields": {"subject": {}}
    }
    }
  3. 热更新
    IKAnalyzer.cfg.xml

    http://localhost/hotload.dic

    放入到 静态资源服务器下面

  4. 同义词配置
    http://192.168.10.74:9200/synonyms-ik-index PUT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
{
"settings": {
"analysis": {
"analyzer": {
"by_smart": {
"type": "custom",
"tokenizer": "ik_smart",
"filter": [
"by_tfr",
"by_sfr"
],
"char_filter": [
"by_cfr"
]
},
"by_max_word": {
"type": "custom",
"tokenizer": "ik_max_word",
"filter": [
"by_tfr",
"by_sfr"
],
"char_filter": [
"by_cfr"
]
}
},
"filter": {
"by_tfr": {
"type": "stop",
"stopwords": [
" "
]
},
"by_sfr": {
"type": "synonym",
"synonyms_path": "synonyms.dic"
}
},
"char_filter": {
"by_cfr": {
"type": "mapping",
"mappings": [
"| => |"
]
}
}
}
},
"mappings": {
"article": {
"dynamic": true,
"properties": {
"subject": {
"type": "string",
"analyzer": "by_max_word",
"search_analyzer": "by_smart"
},
"content": {
"type": "string",
"analyzer": "by_max_word",
"search_analyzer": "by_smart"
}
}
}
}
}
  1. 测试同义词

    http://192.168.10.74:9200/synonyms-ik-index/_analyze POST

1
2
3
4
{
"analyzer": "by_smart",
"text": "绝地求生是最好玩的游戏"
}
  1. 查询同义词
    http://192.168.10.74:9200/synonyms-ik-index/_search POST
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"query": {
"match": {
"subject": "吃鸡"
}
},
"highlight": {
"pre_tags": [
"<span style = 'color:red'>"
],
"post_tags": [
"</span>"
],
"fields": {
"subject": {}
}
}
}

数据导入/导出 : elasticdump

github 地址: https://github.com/taskrabbit/elasticsearch-dump

文件搜索实现

  1. 文档地址: https://www.elastic.co/guide/en/elasticsearch/plugins/5.3/using-ingest-attachment.html

  2. 安装插件
    ./bin/elasticsearch-plugin install ingest-attachment

  3. 创建管道single_attachment
    http://192.168.10.74:9200/_ingest/pipeline/single_attachment PUT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"description": "Extract single attachment information",
"processors": [
{
"attachment": {
"field": "data",
"indexed_chars": -1,
"ignore_missing": true
}
},
{
"remove": {
"field": "data"
}
}
]
}

field  :  指定某个字段作为附件内容字段(需要用base64进行加密)

target_field:指定某个字段作为附件信息字段(作者、时间、类型)

indexed_chars : 指定解析文件管道流的最大大小,默认是100000。如果不想限制设置为-1(注意设置为-1的时候如果上传文件过大会而内存不够会导致文件上传不完全)

indexed_chars_field:指定某个字段能覆盖index_chars字段属性,这样子可以通过文件的大小去指定indexed_chars值。

properties:  选择需要存储附件的属性值可以为:content,title,name,author,keyword,date,content_type,content_length,language

ignore_missing: 默认为false,如果设置为true表示,如果上面指定的field字段不存在这不对附件进行解析,文档还能继续保留

新增了添加完附件数据后 删除 data 的 base64 的数据

多文件管道流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
  "description": "多文件管道流",
  "processors": [
     {
      "foreach": {
        "field": "attachments",
        "processor": {
          "attachment": {
            "field": "data",
"indexed_chars": -1,
"ignore_missing": true
          }
        }
      }
    }
  ]
}
  1. 删除通道

http://192.168.10.74:9200/_ingest/pipeline/single_attachment DELETE

  1. 创建索引
    http://192.168.10.74:9200/file_attachment/ PUT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
"settings": {
"analysis": {
"analyzer": {
"ik": {
"tokenizer": "ik_max_word"
}
}
}
},
"mappings": {
"attachment": {
"properties": {
"filename": {
"type": "text",
"analyzer": "ik_max_word"
},
"data": {
"type": "text"
},
"time": {
"type": "string"
},
"attachment.content": {
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
}
  1. 添加数据
    http://192.168.10.74:9200/file_attachment/attachment/1?pipeline=single_attachment&refresh=true&pretty=1/ POST
1
2
3
4
5
{
"filename": "测试文档.txt",
"time": "2018-06-13 15:14:00",
"data": "6L+Z5piv56ys5LiA5Liq55So5LqO5rWL6K+V5paH5pys6ZmE5Lu255qE5YaF5a6577yb5paH5Lu25qC85byP5Li6dHh0LOaWh+acrOS4uuS4reaWhw=="
}
  1. 文档查询
    http://192.168.10.74:9200/file_attachment/_search POST
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"query": {
"match": {
"attachment.content": "测试"
}
},
"highlight": {
"pre_tags": [
"<span style = 'color:red'>"
],
"post_tags": [
"</span>"
],
"fields": {
"attachment.content": {}
}
}
}

注意: 使用 nginx 的静态资源目录作为 文件的存放,那么在下载文件时,想要 txt ,html ,pdf 等文件直接被下载而不被浏览器打开时,可在 nginx 的配置文件加入以下配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
server {
listen 80;
server_name localhost;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
root html;
if ($request_filename ~* ^.*?.(txt|doc|pdf|rar|gz|zip|docx|exe|xlsx|ppt|pptx|jpg|png|html|xml)$){
add_header Content-Disposition attachment;
add_header Content-Type 'APPLICATION/OCTET-STREAM';
}
index index.html index.htm;
}

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}

重点是 :
if ($request_filename ~* ^.?.(txt|doc|pdf|rar|gz|zip|docx|exe|xlsx|ppt|pptx|jpg|png|html|xml)$){
add_header Content-Disposition attachment;
add_header Content-Type ‘APPLICATION/OCTET-STREAM’;
}
或者也可以这样处理:
if ($args ~
“target=download”) {
add_header Content-Disposition ‘attachment’;
add_header Content-Type ‘APPLICATION/OCTET-STREAM’;
}

这样的话只要在 get请求加上 target=download 参数就可以下载了。

Office 套件研究

OpenOffice 服务搭建

安装步骤

  1. 下载 rpm 包 : 官网: https://www.openoffice.org/download/

  2. 解压,进入 /zh-CN/RPMS/ , 安装 rpm 包: rpm -ivh *.rpm

  3. 安装完成后,生成 desktop-integration 目录,进入,因为我的系统是 centos 的 ,我选择安装 rpm -ivh openoffice4.1.5-redhat-menus-4.1.5-9789.noarch.rpm

  4. 安装完成后,目录在 /opt/openoffice4 下
    启动: /opt/openoffice4/program/soffice -headless -accept="socket,host=0.0.0.0,port=8100;urp;" -nofirststartwizard &

遇到的问题

  1. libXext.so.6: cannot open shared object file: No such file or directory
    解决 : yum install libXext.x86_64

  2. no suitable windowing system found, exiting.
    解决: yum groupinstall "X Window System"

之后再启动,查看监听端口 netstat -lnp |grep 8100
已经可以了。

存在的问题

对很多中文字体的支持并不是很好,很多中文字符及特殊字符无法显示

LibreOffice 服务搭建

安装步骤

  1. 下载 Linux系统下的 rpm 安装包

  2. 将安装包解压缩到目录下

  3. 安装
    $ sudo yum install ./RPMS/.rpm / 安装主安装程序的所有rpm包 /
    $ sudo yum install ./RPMS/
    .rpm /* 安装中文语言包中的所有rpm包 /
    $ sudo yum install ./RPMS/
    .rpm /* 安装中文离线帮助文件中的所有rpm包 */

  4. 卸载
    $ sudo apt-get remove –purge libreoffice6.x-* /* 移除所有类似libreoffice6.x-*的包。–purge表示卸载的同时移除所有相关的配置文件 */

使用总结

LibreOffice 的安装表示没有像 OpenOffice 那样遇到很多问题,且对中文字符的支持较为友好,官网也提供了相应的中文字体下载。

Spring Boot 连接并调用 Office 服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public Object preview(@PathVariable String fileName){
try {
Resource resource = new UrlResource(remoteAddr + fileName);
if (FilenameUtils.getExtension(resource.getFilename()).equalsIgnoreCase("pdf")) {
return "Is the PDF file";
}
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {

final DocumentFormat targetFormat =
DefaultDocumentFormatRegistry.getFormatByExtension("pdf");
converter
.convert(resource.getInputStream())
.as(
DefaultDocumentFormatRegistry.getFormatByExtension(
FilenameUtils.getExtension(resource.getFilename())))
.to(baos)
.as(targetFormat)
.execute();

final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType(targetFormat.getMediaType()));
return new ResponseEntity<>(baos.toByteArray(), headers, HttpStatus.OK);

} catch (OfficeException | IOException e) {
e.printStackTrace();
return "convert error: " + e.getMessage();
}
} catch (IOException e) {
e.printStackTrace();
return "File does not exist;";
}
}

Collabora Office 服务搭建

官方地址: https://www.collaboraoffice.com/solutions/collabora-office/

Collabora CODE 服务搭建

官方建议采用docker来安装

Docker
1
2
3
$ docker pull collabora/code
$ docker run -t -d -p 127.0.0.1:9980:9980 -e "domain=<your-dot-escaped-domain>" \
-e "username=admin" -e "password=S3cRet" --restart always --cap-add MKNOD collabora/code
Linux packages
1
2
3
4
5
6
# import the signing key
wget https://www.collaboraoffice.com/repos/CollaboraOnline/CODE-centos7/repodata/repomd.xml.key && rpm --import repomd.xml.key
# add the repository URL to yum
yum-config-manager --add-repo https://www.collaboraoffice.com/repos/CollaboraOnline/CODE-centos7
# perform the installation
yum install loolwsd CODE-brand

Office 套件文档在线协作

需要域名和SSL证书,尚未实际研究

安装完系统后的一些配置

  1. 关闭并禁用 swap 分区: sudo swapoff 并且 sudo vim /etc/fstab 注释掉 swap 那行

  2. 开启点击图标最小化: gsettings set org.compiz.unityshell:/org/compiz/profiles/unity/plugins/unityshell/ launcher-minimize-window true

  3. 开机开启小键盘: sudo apt-get install numlockx 然后 sudo vim /usr/share/lightdm/lightdm.conf.d/50-unity-greeter.conf 在最后添加:greeter-setup-script=/usr/bin/numlockx on

  4. 用久显示隐藏文件夹: Edit -> Preferences -> Views 勾选 Show hidden and backup files

  5. 禁用客人会话: https://blog.csdn.net/thuyx/article/details/78503870

  6. jdk 10 的配置??
    分别下载 jdk10 和 jre 10 解压缩到 /usr/java目录下
    配置如下环境变量

1
2
3
4
5
6
7
8
9
10
11
#set java environment
JAVA_HOME=/usr/java/jdk-10
JRE_HOME=/usr/java/jre-10
CLASS_PATH=.:$JAVA_HOME/lib:$JRE_HOME/lib

MAVEN_HOME=/usr/maven/apache-maven-3.5.3
NODE_HOME=/usr/nodejs/node-v8.11.2-linux-x64

PATH=$JAVA_HOME/bin:$MAVEN_HOME/bin:${NODE_HOME}/bin:$PATH
export JAVA_HOME JRE_HOME CLASS_PATH MAVEN_HOME NODE_HOME PATH

  1. 安装中文字体文泉译:sudo apt-get install fonts-wqy-microhei

  2. 防火墙配置
    sudo ufw enable

    sudo ufw default deny

    运行以上两条命令后,开启了防火墙,并在系统启动时自动开启。关闭所有外部对本机的访问,但本机访问外部正常

    sudo ufw disable 关闭防火墙

  3. 鼠标移动速度调整
    xset m N
    其中,N是速度,估计取值为0-10
    恢复默认 xset m default

apt-get 命令的记录

  1. 卸载软件: sudo apt-get purge docker-ce
  2. 查看软件版本: apt-cache madison docker-ce

2018年07月19日09:10:55 更新

indicator-sysmonitor 显示网速时,在状态栏会左右移动,解决方法是:
修改源代码

1
sudo vi  /usr/lib/indicator-sysmonitor/sensors.py   

打开后,修改第29行的B_UNITS:

1
B_UNITS = ['MB', 'GB', 'TB']

接着修改下面的bytes_to_human函数:

1
2
3
4
5
6
7
8
def bytes_to_human(bytes_):                 
unit = 0
bytes_ = bytes_ / 1024 / 1024
while bytes_ > 1024:
unit += 1
bytes_ /= 1024
# 做成00.00MB/s的形式,避免变化
return '{:0>5.2f}{:0>2}'.format(bytes_, B_UNITS[unit])

然后保存退出,重启就可以了。

0%