作者归档:zhiwei

ipv6 vpn

查看本机的ipv6 route表

$  ip -6 route show
::1 dev lo proto kernel metric 256 pref medium
2408:84f1:ff22:aea1::/64 dev enp0s20f0u3 proto kernel metric 100 pref medium
2408:84f1:ff22:aea1::/64 dev enp0s20f0u3 proto kernel metric 256 expires 3575sec pref medium
fe80::/64 dev enp0s20f0u3 proto kernel metric 100 pref medium
fe80::/64 dev enp0s20f0u3 proto kernel metric 256 pref medium
default via fe80::e4c0:61ff:fe60:e0fa dev enp0s20f0u3 proto ra metric 1024 expires 3575sec hoplimit 64 pref high

ipv6 规则

ip -6 rule show
0: from all lookup local
32766: from all lookup main

ipv6转发

cat /proc/sys/net/ipv6/conf/all/forwarding
1

在IPv6中,没有广播机制。 启用IPv6的主机不是必须从DHCP获取IP地址或手动配置。

它可以自动配置其自己的IP,IPv6网络中的主机能够使用唯一的链路本地地址自动配置自身。

 启用IPv6的主机不需要任何DHCPv6服务器获取IP地址,因为它们可以自动配置。 他们也不需要DHCPv6定位DNS服务器,因为可以通过ICMPv6邻居发现协议发现和配置DNS。 然而DHCPv6服务器可以用于提供这些信息。

ARP已被ICMPv6邻居发现协议替代。

自动配置

IPv6中,当主机开机时,会检查本地网络,看看有没有其他主机使用了自己的 IP 地址。如果地址没有被使用,就接着查询本地的 IPv6 路由器,找到后就向它请求一个 IPv6 地址。然后这台主机就可以连上互联网了 —— 它有自己的 IP 地址,和自己的默认路由器。

多用户多开

Android的这个“用户”并不是等同于linux下的用户概念。Android是基于Linux的OS,Linux下有一套自己的账户管理体系,而Android对此有一些封装和改动。同时,Android也引进了自己的多用户功能。

pm命令选项

create-user [–profileOf USER_ID] [–managed] [–restricted] [–ephemeral]
[–guest] USER_NAME
用给定的用户名,创建新用户.打印新用户的id

remove-user USER_ID
删除指定用户ID相关的所有数据(用户配置,应用程序)

pm grant [–user USER_ID] Packagename permission  授权
pm revoke [–user USER_ID] Packagename permission 撤销

pm get-max-users  得到最多可多开的用户个数
Maximum supported users: 1

pm get-max-running-users
Maximum supported running users: 6

force-dex-opt PACKAGE  对指定的包立即执行优化

hide [–user USER_ID] PACKAGE_OR_COMPONENT
unhide [–user USER_ID] PACKAGE_OR_COMPONENT

enable [–user USER_ID] PACKAGE_OR_COMPONENT
disable [–user USER_ID] PACKAGE_OR_COMPONENT

查看用户信息
dumpsys user

pm list users
Users:
	UserInfo{0:机主:13} running
	UserInfo{900:分身空间:80300810} running
	UserInfo{901:分身空间:80300810} running
	UserInfo{902:分身空间:80300810} running
	UserInfo{903:分身空间:80300810} running
	UserInfo{904:分身空间:80000810} running
	UserInfo{905:分身空间:80100810} running
	UserInfo{906:分身空间:80200810} running
	UserInfo{907:分身空间:80300810} running
	UserInfo{908:分身空间:80300810} running
	UserInfo{909:分身空间:80300810} running
	UserInfo{910:分身空间:80300810} running
	UserInfo{911:分身空间:80300810} running
	UserInfo{912:分身空间:80300810} running
	UserInfo{913:分身空间:80300810} running
	UserInfo{914:分身空间:80300810} running
	UserInfo{915:分身空间:80300810} running

启动新用户
am start-user 905

得到包的安装路径
pm path com.android.settings
package:/system/priv-app/ZuiSettings/ZuiSettings.apk

第0步:
try {
Method method = Class.forName(UserHandle.class.getName()).getMethod(SUPPORTS_MULTI_SPACE, new Class[0]);
method.setAccessible(true);
if (((Boolean) method.invoke(null, new Object[0])).booleanValue()) {
mSupportsMultiSpace = 1;
return true;
}
} catch (Exception unused) {
Log.w(TAG, DONOT_SUPPORT_MULTISPACE);
}

调用 UserHandle.supportsMultiSpace 判断是否支持

第1步:
createProfile(profileName, pkgName, isMultipleSpace)

    private void createProfile(String ProfileName, String PakageName, boolean isMultipleSpace) {
        this.mManagedProfileUserInfo = this.getUsefulUser(ProfileName, PakageName, isMultipleSpace);
    }





    private UserInfo getUsefulUser(String profileName, String pkgname, boolean isMultipleSpace) {
        UserInfo userInfo;
        StringBuilder sb = new StringBuilder();
        UserManager userManager = (UserManager) this.mContext.getSystemService("user");
        List[userinfo] users = userManager.getUsers();
        this.mMultipleSpaceCount = 0;
        users.sort(new Comparator[userinfo]() {
            public int compare(UserInfo userInfo, UserInfo userInfo2) {
                return userInfo.getMultipleSpaceId() - userInfo2.getMultipleSpaceId();
            }
        });
        if (users == null || users.size() <= 1) {
            userInfo = null;
        } else {
            userInfo = null;
            for (UserInfo userInfo2 : users) {
                boolean isSecuritySpaceUser = MultiSpaceConstant.isSecuritySpaceUser(userInfo2.id);
                if ((!z && isSecuritySpaceUser) || (z && userInfo2 != null && userInfo2.isMultipleSpace() && !isSecuritySpaceUser)) {
                    if (TextUtils.isEmpty(sb.toString())) {
                        sb.append(userInfo2.id);
                    } else {
                        StringBuilder sb2 = new StringBuilder();
                        sb2.append(",");
                        sb2.append(userInfo2.id);
                        sb.append(sb2.toString());
                    }
                    if (!isSecuritySpaceUser) {
                        this.mMultipleSpaceCount++;
                    }
                    if (userInfo == null) {
                        if ((!z && isSecuritySpaceUser) || !isInstalled(str2, userInfo2.id)) {
                            userInfo = userInfo2;
                        }
                    }
                }
            }
        }
        this.mSplitUserIsExist = true;
        if (userInfo != null) {
            return userInfo;
        }
        if (this.mMultipleSpaceCount >= 4 && !z) {
            return userInfo;
        }
        this.mSplitUserIsExist = false;

        Secure.putString(this.mContext.getContentResolver(), KEY_MULTI_SPACE_USERS, sb.toString());
        创建用户
        UserInfo createUser = userManager.createUser(str, getUserInfoFlag(isMultiSpace) | 16);
        Secure.putString(this.mContext.getContentResolver(), KEY_MULTI_SPACE_USERS, null);
        String str3 = TAG;
        StringBuilder sb3 = new StringBuilder();
        sb3.append("Creating managed profile with name ");
        sb3.append(str);
        sb3.append(" ");
        sb3.append(str2);
        sb3.append(" targetUserInfo = ");
        sb3.append(createUser);
        Log.v(str3, sb3.toString());
        return createUser;
    }




  private int getUserInfoFlag(boolean isMultiSpace) {
        try {
            Class cls = Class.forName(UserInfo.class.getName());
            return cls.getField(isMultiSpace ? FLAG_MULTIPLE_SPACE : FLAG_SECURITY_SPACE).getInt(cls);
        } catch (Exception e) {
            Log.v(TAG, "getUserInfoFlag error", e);
            return 0;
        }
    }

https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/content/pm/UserInfo.java
public static final int FLAG_PRIMARY = 0x00000001;
public static final int FLAG_ADMIN = 0x00000002;
public static final int FLAG_GUEST = 0x00000004;
public static final int FLAG_RESTRICTED = 0x00000008;

public static final int FLAG_INITIALIZED = 0x00000010;
public static final int FLAG_MANAGED_PROFILE = 0x00000020;

private static final int FLAG_MASK_MULTIPLE_SPACE_ID = 0xff00000;
public static final int FLAG_MULTIPLE_SPACE = -7ffff800;
80300800

小米9
pm get-max-running-users
Maximum supported running users: 3
pm get-max-users
Maximum supported users: 4

qcom modem重启

/sys/bus/msm_subsys/devices/subsys0 -> ../../../devices/platform/soc/4080000.qcom,mss/subsys0

/sys/devices/platform/soc/4080000.qcom,mss/subsys0

restart_level
RELATED

/sys/bus/msm_subsys/devices/subsys0/name
modem

persist.vendor.ssr.restart_level: ALL_ENABLE

drivers/soc/qcom/subsystem_restart.c

int subsystem_restart(const char *name)
{
	int ret;
	struct subsys_device *dev = find_subsys(name);
	if (!dev)
		return -ENODEV;
	ret = subsystem_restart_dev(dev);
	put_device(&dev->dev);
	return ret;
}
EXPORT_SYMBOL(subsystem_restart);

qcom diag

boolean Diag_LSM_Init (byte* pIEnv);
作用:初始化诊断映射层,在一个进程里只应该被调用一次
pIENV可以为NULL

成功返回True

libdiag.so
————-
int register_callback(void)
libmmi.so
———

读取NV IMEI

26 26 02 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00

响应
26 26 02 08 3A 65 27 03 68 33 99 89 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00

———————————-
NV/Diag NV Read Extension Request

4B 30 01 00–26 02–01 00— 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00

NV_ID = 550
ContextID = 1
ItemData[0] = 0

4B 30 01 00– 26 02 —01 00— 08 3A 75 23 07 39 91 73
76 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00

================
4B 30 01 00 –26 02– 00 00 –00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00

中华人民共和国公民身份证校验算法

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

def getValidateCheckout(id17):
    weight=[7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2]   
    validate=['1','0','X','9','8','7','6','5','4','3','2']  

    sum=0
    mode=0
    for i in range(0,len(id17)):
        sum = sum + int(id17[i])*weight[i]
    mode=sum%11
    return validate[mode]

Postgresql数组

PostgreSQL允许将表的列定义为可变长度的多维数组。 可以创建任何内置或用户定义的基类型,枚举类型或复合类型的数组。

 Qrcodes    integer[];

初始化:要将数组值写为文字常量,请将元素值括在花括号中并用逗号分隔。 您可以在任何元素值周围加上双引号,如果它包含逗号或花括号,则必须这样做。 )因此,数组常量的一般格式如下:
‘{ val1 delim val2 delim … }’
实例:
‘{1,2,3,4,5}’

psycopg2会将array 作为一个字符串返回,而我希望它返回一个list

import psycopg2

query = """
    select array(select * from (values (1), (2)) s);
"""

conn = psycopg2.connect('dbname=cpn user=cpn')
cursor = conn.cursor()
cursor.execute(query)
rs = cursor.fetchall()

for l in rs:
    print l[0]

cursor.close()
conn.close()

运行结果
[1, 2]

另外一种只取一行,并返回字典

cursor = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
cursor.execute('select Qrcodes FROM SysConfigs WHERE channelid=2')
rs = cursor.fetchone()

print(rs['qrcodes'])

[50000, 60000, 70000, 80000, 90000, 100000]
返回一个tuple

插入数据

a = '16000,26000,36000'
b = '{' + a + '}'

psql = 'UPDATE SysConfigs SET Qrcodes=%s WHERE channelid=1'
cursor.execute(psql, (b,))

javascript获取URL查询参数

var getUrlParameter = function getUrlParameter(sParam) {
    var sPageURL = window.location.search.substring(1),
        sURLVariables = sPageURL.split('&'),
        sParameterName,
        i;

    for (i = 0; i < sURLVariables.length; i++) {
        sParameterName = sURLVariables[i].split('=');

        if (sParameterName[0] === sParam) {
            return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
        }
    }
};

另外一种写法

function getUrlParameter(name) {
    name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
    var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
    var results = regex.exec(location.search);
    return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
};

第三种写法

$.urlParam = function(name){
    var results = new RegExp('[\?&]' + name + '=([^]*)').exec(window.location.href);
    if (results==null){
       return null;
    }
    else{
       return results[1] || 0;
    }
}

Python Dictionary Comprehension

从配置表读出配置,第1列为配置名,第2列为配置内容
有多个配置

x = {}
for item in items:
     x[item['cfgname']] = item['cfgvalue']

import json
json.dumps(x)

改成dict comprehension

x = {item['cfgname']:item['cfgvalue'] for item in items}