Python3学习-基础语法
Python3学习-基本数据类型
Python3学习-运算符
Python3学习-基本语句
Python3学习-函数
Python3学习-迭代器与生成器
Python3学习-数据结构
Python3学习-模块与包
Python3学习-输入和输出
Python3-字符串格式化
Python3学习-文件操作
Python3学习-OS模块
Python3学习-错误和异常处理
Python3学习-面向对象
Python3学习-命名空间和作用域
Python3学习-函数装饰器
Python3-星号和双星号变量用法
Python3-时间模块
Python3-数学模块
Python3-多线程
Python3-多进程
Python3-MySQL操作
Python3-操作SqLite
Python3-JSON操作
Python3-XML操作
Python3-Word操作
Python3-Excel操作
Python3-网络编程
Python3-标准库1

密码更换周期设置

密码定期更换配置在 /etc/login.defs 中:

1
2
3
4
PASS_MAX_DAYS	90   # 密码到期时间
PASS_MIN_DAYS 6 # 初始密码更改时间
PASS_MIN_LEN 8 # 密码最小长度
PASS_WARN_AGE 10 # 密码过期提示时间

注意:

/etc/login.defs 中设置仅影响创建用户,而不会影响现有用户。
如果设置为现有用户,使用命令 chage -M(days)(user),例如:chage -M 60 root

chage命令

chage 命令是用来修改帐号和密码的有效期限。

语法

chage [选项] 用户名

选项

  • -m:密码可更改的最小天数。为零时代表任何时候都可以更改密码。
  • -M:密码保持有效的最大天数。
  • -w:用户密码到期前,提前收到警告信息的天数。
  • -E:帐号到期的日期。过了这天,此帐号将不可用。
  • -d:上一次更改的日期。
  • -i:停滞时期。如果一个密码已过期这些天,那么此帐号将不可用。
  • -l:例出当前的设置。由非特权用户来确定他们的密码或帐号何时过期。

示例

1
2
3
4
5
# 查看root配置
chage -l root

# 设置root密码90天过期
chage -M 90 root

密码复杂度设置

CentOS7/RHEL7 开始使用 pam_pwquality 模块进行密码复杂度策略的控制管理。pam_pwquality 替换了原来 Centos6/RHEL6 中的 pam_cracklib 模块,并向后兼容。

pam_pwquality模块设置

retry=N 允许重试N次
difok=N 新密码必需与旧密码不同的位数 difok=3 新密码必须与旧密码有3位不同
minlen=N 最小位数
ucredit=N 大写字母位数
lcredit=N 小写字母位数
dcredit=N 数字个数
ocredit=N 特殊字母的个数

两种方式实现:

  • 1,直接指定 pam_pwquality 模块参数,在 /etc/pam.d/system-auth 中的 password requisite pam_pwquality.so 行尾添加具体参数,比如 minlen=16 ucredit=-1 lcredit=-1 ocredit=-1 dcredit=-1 ,表示最小密码长度16位,数字,大小写字母,特殊字符均至少包含1位。

N >= 0:密码中最多有多少个;
N < 0 :密码中最少有多少个;

1
password    requisite     pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type= minlen=8 ucredit=-1 lcredit=-1 ocredit=-1 dcredit=-1
  • 2,通过修改 /etc/security/pwquality.conf 参数文件,定义密码复杂度规则。

修改 pwquality.conf 参数文件有2种方法。

(1)直接修改 /etc/security/pwquality.conf
(2)使用 authconfig 命令修改,修改后最终会体现在 /etc/security/pwquality.conf

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
# 最小长度
authconfig --passminlen=8 --update
grep "^minlen" /etc/security/pwquality.conf

# 设置同一类的允许连续字符的最大数目
authconfig --passmaxclassrepeat=6 --update
grep "^maxclassrepeat" /etc/security/pwquality.conf

# 至少需要一个小写字符
authconfig --enablereqlower --update
grep "^lcredit" /etc/security/pwquality.conf

# 至少需要一个大写字符
authconfig --enablerequpper --update
grep "^ucredit" /etc/security/pwquality.conf

# 至少需要一个数字
authconfig --enablereqdigit --update
grep "^dcredit" /etc/security/pwquality.conf

# 至少一个特殊字符
authconfig --enablereqother --update
grep "^ocredit" /etc/security/pwquality.conf

# 以下需要单独设置
vim /etc/security/pwquality.conf

# 添加一下配置

# 设置单调字符序列的最大长度
maxsequence = 5

# 新密码中不能出现在旧密码中的字符数
difok = 5

# 检查来自用户 passwd 条目的 GECOS 字段的长度超过3个字符的字是否包含在新密码中。
gecoscheck = 1

# 设置不能包含在密码中的Ssace分隔的单词列表
badwords = test test1 test2

示例:

1
2
vim /etc/security/pwquality.conf
grep -vE "^#|^$" /etc/security/pwquality.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
minlen = 8

# 新密码所需的字符类(数字、大写、小写、其他)的最小字符数。
minclass = 1

# 新密码中允许的连续相同字符的最大数量。如果值为 0,则禁用检查。
maxrepeat = 0

maxclassrepeat = 6
lcredit = -1
ucredit = -1
dcredit = -1
ocredit = -1

Centos7 继续使用 pam_cracklib 模块检验密码复杂度

vim /etc/pam.d/system-auth

1
2
# 添加到 pam_pwquality.so 所在行的上行
password requisite pam_cracklib.so try_first_pass retry=3 type= minlen=8 ucredit=-1 lcredit=-1 ocredit=-1 dcredit=-1

Read Hat配置密码复杂度

vim /etc/pam.d/system-auth

1
password   requisite      pam_cracklib.so retry=3 difok=3 minlen=8 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1

参考:

CentOS7上密码复杂度设置

CentOS7密码复杂度配置

chage命令

CentOS 7 设置密码规则

数据库审计简介

数据库审计(简称 DBAudit)能够实时记录网络上的数据库活动,对数据库操作进行细粒度审计的合规性管理,对数据库遭受到的风险行为进行告警,对攻击行为进行阻断。它通过对用户访问数据库行为的记录、分析和汇报,用来帮助用户事后生成合规报告、事故追根溯源,同时加强内外部数据库网络行为记录,提高数据资产安全。数据库审计可以记录某用户在某个时间点对数据库的操作,包括登录、连接、对表的增删改查等等,便于责任追溯,问题查找,当然开启审计功能在一定方面会影响数据库性能。

环境

  • 操作系统:CentOS7.4
  • Mysql:mysql-5.7.31-linux-glibc2.12-x86_64.tar.gz (社区版)
  • Mariadb:mariadb-10.5.8-linux-x86_64

由于MySQL的社区版不支持审计系统,可通过第三方插件实现,此次采用MariaDB的server_audit插件来记录{时间,节点,用户,源IP,事件类型,库,语句,影响行数},注:从mysql8开始已不支持该插件。

安装插件

1,登陆 Mysql,查看插件安装目录:

1
2
3
4
5
6
7
mysql> show global variables like 'plugin_dir';
+---------------+------------------------------+
| Variable_name | Value |
+---------------+------------------------------+
| plugin_dir | /usr/local/mysql/lib/plugin/ |
+---------------+------------------------------+
1 row in set (0.01 sec)

2,提取 Mariadb 审计插件,并放置Mysql插件目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 拷贝
cp /ldjc/mariadb-10.5.8-linux-x86_64/lib/plugin/server_audit.so /usr/local/mysql/lib/plugin/

# 授予执行权限
chmod +x /usr/local/mysql/lib/plugin/server_audit.so

# 安装
# 或者 在 my.cnf 中配置:plugin_load=server_audit=server_audit.so
install plugin server_audit soname 'server_audit.so';

# 备注:
# UNINSTALL PLUGIN server_audit; # 卸载插件
# show variables like '%audit%';

# 查看插件
show plugins;

3,新建 auditlogs 目录,并更改所属的组和用户

1
2
3
mkdir /usr/local/mysql/auditlogs
chown -R mysql /usr/local/mysql/auditlogs
chgrp -R mysql /usr/local/mysql/auditlogs

4,修改my.cnf配置文件

vim /usr/local/mysql/my.cnf

在 [mysqld] 标签下添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#防止server_audit 插件被卸载 进行配置文件配置
server_audit=FORCE_PLUS_PERMANENT

#指定哪些操作被记录到日志文件中
server_audit_events='CONNECT,QUERY,TABLE,QUERY_DDL'

#开启审计功能
server_audit_logging=on

#默认存放路径,可以不写,默认到data文件下
server_audit_file_path=/usr/local/mysql/auditlogs

#设置文件大小 默认1000000,1073741824=1GB
server_audit_file_rotate_size=1073741824

#指定日志文件的数量,如果为0日志将从不轮转
server_audit_file_rotations=200

#强制日志文件轮转
server_audit_file_rotate_now=ON

4,重启mysql

1
2
3
4
/etc/init.d/mysqld restart

# 或
service mysqld restart

验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
mysql> show variables like '%audit%';
+-------------------------------+-------------------------------+
| Variable_name | Value |
+-------------------------------+-------------------------------+
| server_audit_events | CONNECT,QUERY,TABLE,QUERY_DDL |
| server_audit_excl_users | |
| server_audit_file_path | /usr/local/mysql/auditlogs |
| server_audit_file_rotate_now | ON |
| server_audit_file_rotate_size | 1073741824 |
| server_audit_file_rotations | 200 |
| server_audit_incl_users | |
| server_audit_loc_info | |
| server_audit_logging | ON |
| server_audit_mode | 1 |
| server_audit_output_type | file |
| server_audit_query_log_limit | 1024 |
| server_audit_syslog_facility | LOG_USER |
| server_audit_syslog_ident | mysql-server_auditing |
| server_audit_syslog_info | |
| server_audit_syslog_priority | LOG_INFO |
+-------------------------------+-------------------------------+
16 rows in set (0.00 sec)
1
cat /usr/local/mysql/auditlogs/server_audit.log

参数配置说明

  • server_audit:启用安全审计插件;
  • server_audit_output_type:指定日志输出类型,可为 SYSLOG或 FILE
  • server_audit_logging:启动或关闭审计
  • server_audit_events:指定记录事件的类型,可以用逗号分隔的多个值(connect,query,table),如果开启了查询缓存(query cache),查询直接从查询缓存返回数据,将没有 table 记录
  • server_audit_file_path:如 server_audit_output_type 为 FILE,使用该变量设置存储日志的文件,可以指定目录,默认存放在数据目录的 server_audit.log 文件中
  • server_audit_file_rotate_size:限制日志文件的大小
  • server_audit_file_rotations:指定日志文件的数量,如果为0日志将从不轮转
  • server_audit_file_rotate_now:强制日志文件轮转
  • server_audit_incl_users:指定哪些用户的活动将记录,connect将不受此变量影响,该变量比server_audit_excl_users优先级高
  • server_audit_syslog_facility:默认为LOG_USER,指定facility
  • server_audit_syslog_ident:设置ident,作为每个syslog记录的一部分
  • server_audit_syslog_info:指定的info字符串将添加到syslog记录
  • server_audit_syslog_priority:定义记录日志的syslogd priority
  • server_audit_excl_users:该列表的用户行为将不记录,connect将不受该设置影响
  • server_audit_mode:标识版本,用于开发测试

参考:

MariaDB Audit Plugin Options and System Variables

Mysql5.7安装server_audit审计

MySQL5.7审计功能windows系统

MySQL数据库启用安全审计功能

查看gcc版本

1
gcc -v

查看glibc版本

1
ldd --version
1
2
gcc -v
ldd --version

修改配置文件

前提:

  • 1,两台服务器都需要添加一个用户数据同步的帐号。
  • 2,端口,策略,数据库远程等互通。
  • 3,主库备份后,从库需要还原备份文件。

配置以下两台服务器互为主从。

配置:vim /usr/local/mysql/my.cnf

主1服务器配置:

1
2
3
4
5
6
auto_increment_increment=2         #步进值 auto_imcrement。一般有n台主MySQL就填n
auto_increment_offset=1 #起始值。一般填第n台主MySQL。此时为第一台主MySQL
binlog-ignore-db=mysql #忽略mysql库【可忽略不写】
binlog-ignore-db=information_schema #忽略information_schema库【可忽略不写】
binlog-ignore-db=performance_schema #忽略performance_schema库【可忽略不写】
log-slave-updates=on

主2服务器配置:

1
2
3
4
5
6
auto_increment_increment=2         #步进值auto_imcrement。一般有n台主MySQL就填n
auto_increment_offset=2 #起始值。一般填第n台主MySQL。此时为第二台主MySQL
binlog-ignore-db=mysql #忽略mysql库【可忽略不写】
binlog-ignore-db=information_schema #忽略information_schema库【可忽略不写】
binlog-ignore-db=performance_schema #忽略performance_schema库【可忽略不写】
log-slave-updates=on

主1完整配置:

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
[mysql]
socket=/var/lib/mysql/mysql.sock
# set mysql client default chararter
default-character-set=utf8
#
[mysqld]
socket=/var/lib/mysql/mysql.sock
bind-address=0.0.0.0
# set mysql server port
port = 3306 #默认是3306,防止这种情况发生,可以避免使用3306mysql默认端口
# set mysql install base dir
basedir=/usr/local/mysql
# set the data store dir
datadir=/usr/local/mysql/data
# set the number of allow max connnection
max_connections=200000
# set server charactre default encoding
character-set-server=utf8
# the storage engine
default-storage-engine=INNODB
# lower_case_table_names=1
max_allowed_packet=16M
explicit_defaults_for_timestamp=true

sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

# 服务器唯一ID
server-id=1

# 要生成二进制日志文件 主服务器一定要开启
log-bin=/usr/local/mysql/binlogs/bin-log

binlog_format=ROW
expire_logs_days=7
max_binlog_size=100M
binlog_cache_size=4M
max_binlog_cache_size=512M

auto_increment_increment=2
auto_increment_offset=1
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
binlog-ignore-db=performance_schema

log-slave-updates=on

#skip-grant-tables=1

[mysql.server]
user=mysql
basedir=/usr/local/mysql

配置主从

互相配置主从服务器。

主1服务器:192.123.75.68;
主2服务器:192.123.3.87;

登陆到主1服务器,执行一下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 查看 主 复制状态
show master status \G

change master to master_host='192.123.3.87',
master_port=3306,
master_user='slave',
master_password='123456',
master_log_file='bin-log.000005',
master_log_pos=74562307;

# 开始复制
start slave;

# 查看 从 复制状态
# 输出结果中应该看到 I/O 线程和 SQL 线程都是 YES, 就表示成功。
show slave status \G

# 主服务器复制状态
show master status\G

登陆到主2服务器,执行一下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 查看 主 复制状态
show master status \G

change master to master_host='192.123.75.68',
master_port=3306,
master_user='slave',
master_password='123456',
master_log_file='bin-log.000005',
master_log_pos=74562307;

# 开始复制
start slave;

# 查看 从 复制状态
# 输出结果中应该看到 I/O 线程和 SQL 线程都是 YES, 就表示成功。
show slave status \G

# 主服务器复制状态
show master status\G

简介

Appium 是一个开源的自动化测试工具,支持 Android、iOS 平台上的原生应用,支持 Java、Python、PHP 等多种语言。

Appium 封装了 Selenium,能够为用户提供所有常见的 JSON 格式的 Selenium 命令以及额外的移动设备相关的控制命令,比如:多点触控手势、屏幕朝向等。

配置环境

Java环境

右键 This PC(此电脑) -> Properties(属性) -> Advanced system settings(高级系统设置) -> Environment Variables(环境变量)

微信截图_20201223105939.png

新建/修改 CLASSPATH 变量

微信截图_20201223110109.png

Path 变量末尾添加 ;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;

微信截图_20201223110433.png

Android-sdk

新建环境变量 ANDROID_HOME,变量值为 android-sdk 位置,
如:E:\BaiduNetdiskDownload\appium\android-sdk\android-sdk-windows

在 Path 变量值的末尾添加:
;%ANDROID_HOME%\tools;%ANDROID_HOME%\build-tools\30.0.0-preview;%ANDROID_HOME%\platform-tools

微信截图_20201223111155.png

mumu模拟器

通过安卓的 adb 连接虚拟机,需要在控制台执行 adb connect 127.0.0.1:7555 命令,让 adb 连接上虚拟机,在 cmd 控制台输入 adb devices 查看当前连接的虚拟机。

Android真机

开启开发者模式

荣耀V9手机,荣耀V10、荣耀V20、华为P20、华为P30等型号:

1,进入手机的设置项 设置 - 关于手机
2,点击 版本号 7次进入开发者模式的,选择 返回 就可以看到 开发者选项 的菜单。

进入开发者选项 -> 开启开发者选项,并分别开启:USB调试、USB安装、USB调试(安全设置)选项,USB连接时,选择 文件传输

如果手机是第一次链接电脑可能还需要安装一下驱动: Android手机驱动。

使用

1,启动 Appium 和 mumu(如果使用Android真机,可以忽略开启mumu)

微信截图_20210104135431.png

2,

参考:

Python + Appium 自动化操作微信入门看这一篇就够了

Readlink 是 Linux 系统中一个常用工具,主要用来找出符号链接所指向的位置。

语法格式:Readlink [参数] [文件]

常用参数:

-f 递归跟随给出文件名的所有符号链接以标准化,除最后一个外所有组件必须存在
-e 递归跟随给出文件名的所有符号链接以标准化,所有组件都必须存在
-n 不输出尾随的新行
-s 缩减大多数的错误消息
-v 报告所有错误消息
参考实例

查看软链文件真实文件:

1
2
[root@sj0002 local]# readlink mysql
/usr/local/mysql

参考:

Readlink命令

安装dotnet-svcutil

1
dotnet tool install --global dotnet-svcutil

生成

1
2
dotnet-svcutil --outputFile Test1Information.cs -n "http://tempuri.org/,API.ServiceReference.Services1"  --outputDir Services1 http://172.2.22.12/FRXXServices/Services1.asmx
dotnet-svcutil --outputFile Test2Services.cs -n "http://server.test.com,API.ServiceReference.Services2" --outputDir Services2 http://172.2.22.12:8000/services/Services2?WSDL

参考:

https://docs.microsoft.com/en-us/dotnet/core/additional-tools/dotnet-svcutil-guide?tabs=dotnetsvcutil2x

passwd命令

1
2
3
4
5
6
[root@host-192-1-1-82 ~]# passwd
更改用户 root 的密码 。
新的 密码:
无效的密码: 密码少于 8 个字符
重新输入新的 密码:
passwd: 鉴定令牌操作错误

解决

1
2
lsattr /etc/passwd  # 可选 /etc/shadow /etc/group
----i----------- /etc/shadow

i:文件的隐藏属性,这里需要将i去掉;

1
2
# 去掉 i 属性
chattr -i /etc/shadow

重新修改密码即可。

注:tomcat 8不生效

修改context.xml

vim /usr/local/apache-tomcat-8.5.40/conf/context.xml

1
2
3
4
5
6
7
8
9
10
11
12
<Context caseSensitive="false">

<!-- Default set of monitored resources. If one of these changes, the -->
<!-- web application will be reloaded. -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>

<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
</Context>

重启

1
2
systemctl status tomcat8
systemctl restart tomcat8

验证

1
2
3
# 查看监听的端口
# Tomcat默认8080端口
netstat -lnpt

定义消息类型

先看一个 proto3 的查找请求参数的消息格式的例子,这个请求参数例子模仿分页查找请求,他有一个请求参数字符串,有一个当前页的参数还有一个每页返回数据大小的参数,proto 文件内容如下:

1
2
3
4
5
6
7
syntax = "proto3";

message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
  • 第一行的含义是限定该文件使用的是 proto3 的语法,如果没有,则默认为 syntax = “proto3”;
  • SearchRequest 定义有三个承载消息的属性,每一个被定义在 SearchRequest 消息体中的字段,都是由 数据类型 和 属性名称 组成。

指定字段类型

在上面的例子中,所有的属性都是标量,两个整型 ( page_number 、 result_per_page )和一个字符串( query ),你还可以在指定复合类型,包括 枚举类型 或者 其他的消息类型。

分配标量

每一个被定义在消息中的字段都会被分配给一个唯一的标量,这些标量用于标识你定义在二进制消息格式中的属性,标量一旦被定义就不允许在使用过程中再次被改变。标量的值在1~15的这个范围里占一个字节编码

指定属性规则

消息属性规则如下:

  • singular: 一个正确的消息可以有零个或者多个这样的消息属性(但是不要超过一个).
  • repeated: 这个属性可以在一个正确的消息格式中重复任意次数(包括零次),

在 proto3 中,标量数字类型的重复字段默认使用压缩编码。

添加更多的消息类型

在一个 proto 文件中可以定义多个消息类型,你可以在一个文件中定义一些相关的消息类型,上面的例子 proto 文件中只有一个请求查找的消息类型,现在可以为他多添加一个响应的消息类型,具体如下:

1
2
3
4
5
6
7
8
9
10
11
syntax = "proto3";

message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}

message SearchResponse {
....
}

添加注释

proto 文件中的注释使用的是 /c++ 中的单行注释 // 语法风格。

如下:

1
2
3
4
message SearchRequest {
string query = 1;
int32 page_number = 2; // 当前页数
int32 result_per_page = 3; // 每页数据返回的数据量

保留属性

为了避免在加载相同的 .proto 的旧版本,包括数据损坏,隐含的错误等,这可能会导致严重的问题的方法是指定删除的字段的字段标签(和/或名称,也可能导致 JSON 序列化的问题)被保留。 如果将来的用户尝试使用这些字段标识符,协议缓冲区编译器将会报错。

保留字段的使用例子:

1
2
3
4
message Foo {
reserved 2;
reserved "foo", "bar";
}

上述例子定义保留属性为 “foo”, “bar” ,定义保留属性位置为2,即在2这个位置上不可以定义属性,如: string name=2; 是不允许的,编译器在编译 proto 文件的时候如果发现,2这个位置上有属性被定义则会报错。

数据类型

.proto文件的值类型和 java 的值类型的对照表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.proto Type	Java Type
double double
float float
int32 int
int64 long
uint32 int
uint64 long
sint32 int
sint64 long
fixed32 int
fixed64 long
sfixed32 int
sfixed64 long
bool boolean
string String
bytes ByteString

默认值

当 proto 消息被解析成具体的语言的时候,如果消息编码没包含特定的元素,则消息对象中的属性会被设置默认值,这些默认值具体如下:

  • string 类型,默认值是空字符串,注意不是null
  • bytes 类型,默认值是空bytes
  • bool 类型,默认值是false
  • 数字 类型,默认值是0
  • 枚举 类型,默认值是第一个枚举值,即0
  • repeated 修饰的属性,默认值是空(在相对应的编程语言中通常是一个空的list).

枚举

proto 允许你在定义的消息类型的时候定义枚举类型,如下例,在消息类型中定义并使用枚举类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
enum Corpus {
UNIVERSAL = 0;
WEB = 1;
IMAGES = 2;
LOCAL = 3;
NEWS = 4;
PRODUCTS = 5;
VIDEO = 6;
}
Corpus corpus = 4;
}

如上例中所示, Corpus 枚举类型的第一个枚举值是0,每一个枚举值定义都会与一个常量映射,而这些常量的第一个常量值必须为0,原因如下:

必须有一个0作为值,以至于我们可是使用0作为默认值
第一个元素的值取0,用于与第一个元素枚举值作为默认值的proto2语义兼容
枚举类型允许你定义别名,别名的作用是分配不中的标量,使用相同的常量值,使用别名只需要在定义枚举类型的第一行中添加 allow_alias 选项,并将值设置为 true 即可,如果没有设置该值就是用别名,在编译的时候会报错。

官网例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
enum EnumAllowingAlias {
option allow_alias = true;
UNKNOWN = 0;
STARTED = 1;
RUNNING = 1;
}
enum EnumNotAllowingAlias {
UNKNOWN = 0;
STARTED = 1;
//如果解除这个注释编译器在编译该proto文的时候会报错
// RUNNING = 1;
}

proto 支持的枚举值的范围是 32 位的整形,即 Java 中的 int 类型,其他请参看官网。

引用其他的消息类型

你可以在定义消息类型的时候饮用其他已经定义好的消息类型作为新消息类型的属性,官网例子如下:

1
2
3
4
5
6
7
8
9
message SearchResponse {
repeated Result results = 1;
}

message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}

在上面的消息例子中,SearchResponse 这个响应消息类型的属性 results,返回的是一个 Result 类型的消息列表。

导入其他proto中定义的消息

在上面的例子中,Result 和 SearchResponse 消息类型被定义在同一个 .proto 文件中,如果把他们分成两个文件定义,应该如何引用呢?

proto 中为我们提供了 import 关键字用于引入不同 .proto 文件中的消息类型,你可以在你的 .proto 文件的顶部加入如下语句因为其他 .proto 文件的消息类型:import "myproject/other_protos.proto";

例子:

  • 文件名称 search_response.proto
1
2
3
4
5
6
7
8
syntax = "proto3";
import "test/result.proto";
package test1;

message SearchResponse {
//包名.消息名
repeated test2.Result results = 1;
}
  • 文件名称 result.proto,在与search_response.proto同级目录的test下
1
2
3
4
5
6
7
8
syntax = "proto3";
package test2;

message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}

如果两个 .proto 文件在同一个目录下直接这样 import “result.proto”; 倒入即可。

内嵌类型

我们还可以在消息类型中定义消息,例子如下:

1
2
3
4
5
6
7
8
message SearchResponse {
message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}
repeated Result results = 1;
}

在上面的例子中在 SearchResponse 消息体中定义了一个 Result 消息并使用。

如果想在其他的消息体引用 Result 这个消息,可以 Parent.Type 这样引用,例子:

1
2
3
message SomeOtherMessage {
SearchResponse.Result result = 1;
}

消息还可以深层的嵌套定义,如下例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
message Outer {                  // Level 0
message MiddleAA { // Level 1
message Inner { // Level 2
int64 ival = 1;
bool booly = 2;
}
}
message MiddleBB { // Level 1
message Inner { // Level 2
int32 ival = 1;
bool booly = 2;
}
}
}

Map

proto 支持 map 属性类型的定义,语法如下:

1
map<key_type,value_type> map_field = N;

key_type 可以是任何整数或字符串类型(除浮点类型和字节之外的任何标量类型,枚举类型也是不合法的key类型),value_type可以是任何类型的数据。

可以为 proto 文件指定包名,防止消息命名冲突。

例子如下:

1
2
package foo.bar;
message Open { ... }

当你在为消息类型定义属性的时候,你可以通过 命名.类型 的形式来使用已经定义好的消息类型,如下:

1
2
3
4
5
Message Foo {
...
foo.bar.Open open = 1;
...
}

服务定义

如果你想在 RPC 中使用已经定义好的消息类型,你可以在 .proto 文件中定一个消息服务接口, protocol buffer 编译器会生成对应语言的接口代码。

接口定义例子:

1
2
3
4
service SearchService {
// 方法名 方法参数 返回值
rpc Search(SearchRequest) returns (SearchResponse);
}

选项

  • file_extension:文件扩展
  • base_namespace:命名空间

参考:

https://developers.google.com/protocol-buffers/docs/reference/csharp-generated#compiler_options

原因

由于在 openssl1.1.0 版本中,废弃了 EVP_CIPHER_CTX_cleanup 函数,要用这个函数 EVP_CIPHER_CTX_reset() 代替。

解决

使用 vim 编辑 /usr/local/lib/python2.7/dist-packages/shadowsocks/crypto/openssl.py

1
vim /usr/local/lib/python2.7/dist-packages/shadowsocks/crypto/openssl.py

搜索 EVP_CIPHER_CTX_cleanup ,总共两处:52行,111行,将 cleanup 改为 reset 。

1
2
3
libcrypto.EVP_CIPHER_CTX_cleanup
# 改为
libcrypto.EVP_CIPHER_CTX_reset

微信截图_20201105141624.png

参考:

AWS-AttributeError: /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1: undefined symbol: EVP_CIPHER_CTX_

安装依赖

1
yum -y install wget gcc automake autoconf libtool make

安装

1
2
3
4
5
6
7
8
9
10
11
mkdir /shadowsocks
cd /shadowsocks
wget https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tgz

tar -zxvf Python-3.9.0.tgz
cd Python-3.9.0
./configure
make && make install

# 检查版本
python3 -V

简介

lsof 命令用于查看你进程开打的文件,打开文件的进程,进程打开的端口(TCP、UDP)。找回/恢复删除的文件。是十分方便的系统监视工具,因为lsof命令需要访问核心内存和各种文件,所以需要 root 用户执行。

在 linux 环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。所以如传输控制协议 (TCP) 和用户数据报协议 (UDP) 套接字等,系统在后台都为该应用程序分配了一个文件描述符,无论这个文件的本质如何,该文件描述符为应用程序与基础操作系统之间的交互提供了通用接口。因为应用程序打开文件的描述符列表提供了大量关于这个应用程序本身的信息,因此通过lsof工具能够查看这个列表对系统监测以及排错将是很有帮助的。

阅读全文 »
0%