linux & mac

  1. 产生core文件方法
  • 在当前环境下生成coredump文件,运行 ulimit -c unlimited
  • 永久生成coredump文件,在 /etc/profile 文件中追加一行 ulimit-c unlimited
  1. 默认coredump文件生成在当前工作目录,修改文件 /proc/sys/kernel/core_pattern/data/coredump/core.%e.%p
    其中%e表示程序名,%p表示进程id,路径为/data/coredump目录
  2. 编译时要加上-g选项,这个才能用gdb调试的coredump
  3. linux使用加载gdb加载coredump文件进行调试
    1
    2
    3
    4
    5
    gdb coredumpfile
    #或者
    gdb execfile
    #加载完成后再输入
    core-file coredumpfile
  4. mac使用lldb加载coredump文件进行调试
    1
    2
    cd /cores
    lldb -c coredumpfile
  • ulimit -c 显示核心转储文件大小的最大值,如果这里是零:禁止核心转储(对于本进程和它的子进程)。
  • 默认情况下,mac core文件均存在/cores目录下,linux core文件存在当前工作目录。
    • 可以通过ulimit -c unlimited来设置core文件生成路径。
    • 可以通过ulimit -c size来设置core文件大小。
    • 可以通过ulimit -c 0来禁止生成core文件。

windows

windows 请查看这篇文章Windows C++ 程序崩溃收集工具

这几年一直在linux上开发,用的gcc版本比较高,最近把gcc降到4.8.5(centos 7默认版本)后,出现了一些成员变量初始化的问题。

看示例:

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
#include <iostream>

class Test
{
public:
Test() = default;
// Test(const Test& value) = default;
// Test& operator=(const Test &value) = default;
~Test() = default;
int GetA() { return m_a; }
void SetA(int value) { m_a = value; }
private:
int m_a;
};

int main(int argc, char **args)
{
Test test;
Test test2 = test;
std::cout << test.GetA() << std::endl;
std::cout << test2.GetA() << std::endl;
test.SetA(1000);
Test test3 = {};
std::cout << test.GetA() << std::endl;
std::cout << test3.GetA() << std::endl;
Test test4 = {test};
std::cout << test.GetA() << std::endl;
std::cout << test4.GetA() << std::endl;
return 0;
}
编译器 debug release
gcc 4.8 2147483647或者-2147483648 0
gcc 8 0 0
gcc 9.3 0 0
vs2019 msvc 142 随机数 0
clang 7 随机数 随机数
clang 10 x86 1 随机数
clang 10 x64 0 随机数

gcc 4.8 好像不同硬件上会不一样,在另一 服务器上测试都为0

看来还是使用旧式显式初始化靠谱一些,或者这样int m_a = 0;进行显式初始化(需要编译器支持c++11)

一、配置环境
• 安装XCode
https://developer.apple.com/xcode/
xcode-select --install
• 安装JDK
https://docs.oracle.com/javase/8/docs/technotes/guides/install/mac_jdk.html
• 安装Homebrew
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
• 安装工具
brew install git python make curl
• 安装MacPort
https://www.macports.org/install.php
• 安装工具
POSIXLY_CORRECT=1 sudo port install gmake libsdl git gnupg
二、创建磁盘镜像

hdiutil create -type SPARSE -fs 'Case-sensitive Journaled HFS+' -size 200g ~/Documents/android/android.dmg
hdiutil resize -size 250g ~/Documents/android/android.dmg.sparseimage #重新设置映像的大小
hdiutil attach ~/Documents/android/android.dmg.sparseimage -mountpoint /Volumes/android #挂载
hdiutil detach /Volumes/android #弹出映像

三、配置环境变量.bash_profile

# set the number of open files to be 1024
ulimit -S -n 1024
# Compiler cache
export USE_CCACHE=1
# mount the android file image
function mountAndroid { hdiutil attach ~/Documents/android/android.dmg.sparseimage -mountpoint /Volumes/android; }
# unmount the android file image
function umountAndroid() { hdiutil detach /Volumes/android; }
export PATH="/opt/local/bin:/opt/local/sbin:$PATH"
export PATH=~/Documents/android/bin:$PATH
export ANDROID_JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
export PATH=$ANDROID_JAVA_HOME/bin:$PATH
export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/'

四、下载AOSP源代码
• 下载repo并设置权限

mkdir ~/Documents/android/bin
curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo > ~/Documents/android/bin/repo
chmod a+x ~/Documents/android/bin/repo

• 初始化仓库

mountAndroid
cd /Volumes/android
mkdir WORKING_DIRECTORY
cd WORKING_DIRECTORY

repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-8.1.0_r62
repo init -u git://aosp.tuna.tsinghua.edu.cn/aosp/platform/manifest
repo init -u git://aosp.tuna.tsinghua.edu.cn/aosp/platform/manifest -b android-8.1.0_r62
repo sync -c

五、编译AOSP源代码

cd /Volumes/android/WORKING_DIRECTORY/ 
# Set ccache
prebuilts/misc/darwin-x86/ccache/ccache -M 50G 
# Clean out directory
make clobber 
# Jack server configuration
export JACK_SERVER_VM_ARGUMENTS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx6g"
./prebuilts/sdk/tools/jack-admin kill-server
./prebuilts/sdk/tools/jack-admin start-server 
# Setup environment 
source build/envsetup.sh

# support Mac OS Catalina 10.15
# change ./build/soong/cc/config/x86_darwin_host.go
  darwinSupportedSdkVersions = []string{
          "10.10",
          "10.11",
          "10.12",
          "10.13",
          "10.14",
          "10.15",  // 增加该行
      }
# Segmentation fault
# change ./system/sepolicy/tests/Android.bp
  stl: "libc++_static", // 去除该行

# Select device target
lunch
# Build sources (cofee time)
make -j8

六、安装

cd out/target/product/<product_name> 
adb reboot bootloader
fastboot oem unlock 
fastboot flashall -w

#烧入
adb reboot bootloader
fastboot flash boot boot.img
fastboot flash system system.img
fastboot flash userdata userdata.img
fastboot flash ramdisk ramdisk.img
fastboot flash vendor vendor.img
fastboot erase cache
fastboot reboot

七、重新编译单个包

cd WORKING_DIRECTORY
source build/envsetup.sh 
# Select device target
lunch
# Rebuil single pacage (exemple Dialer)
mmm packages/apps/dialer/

# Recompiled package output
cd /out/target/product/<device_targeted>/obj/APPS/<app_name>_intermediates

adb install -r out/target/product/<device_targeted>/system/priv-app/<app_name>/<app_name>.apk
adb reboot

八、编译系统UI

cd WORKING_DIRECTORY
source build/envsetup.sh
# Select device target
lunch
# Rebuil single pacage (exemple Dialer)
mmm frameworks/base/packages/SystemUI/

adb install -r out/target/product/<device_targeted>/system/priv-app/SystemUI/SystemUI.apk
adb reboot

九、编译Framework
• Build Framework JAR only: mmm framework/base/
• Build Framework Resources only: mmm framework/base/core/res/

# Root the device
adb root
adb disable-verity
adb reboot
adb remount
# Remove older framework
adb shell
cd /system/framework/
rm framework-res.apk
exit
# Push the new Framework
adb push out/target/product/<device_targeted>/system/framework/framework-res.apk /system/framework/
# Reboot the device
adb reboot

十、签名
标准 Android 版本使用四个密钥,所有这些密钥都位于 :build/target/product/security
• testkey:不指定密钥的包的通用默认键。
• platform:作为核心平台一部分的包的测试密钥。
• shared:家庭/联系人进程中共享的内容的测试密钥。
• media:作为媒体/下载系统一部分的包的测试密钥。
资料来源:https://source.android.com/devices/tech/ota/sign_builds#certificates-keys
若要使用现有密钥之一对应用进行签名,请使用以下指令 (LOCAL_CERTIFICATE)到关联的makefile Android.mk:
LOCAL_CERTIFICATE := platform

一、配置环境

1
2
3
4
sudo apt install git-core gnupg flex bison gperf build-essential \
zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 \
lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev libgl1-mesa-dev \
libncurses5 libxml2-utils python xsltproc unzip

二、配置环境变量.bash_profile

1
2
3
4
5
6
7
# Compiler cache
export USE_CCACHE=1
export PATH="/opt/local/bin:/opt/local/sbin:$PATH"
export PATH=~/Documents/android/bin:$PATH
export ANDROID_JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
export PATH=$ANDROID_JAVA_HOME/bin:$PATH
export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/'

四、下载AOSP源代码
• 下载repo并设置权限

1
2
3
mkdir ~/Documents/android/bin
curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo > ~/Documents/android/bin/repo
chmod a+x ~/Documents/android/bin/repo

• 初始化仓库

1
2
3
4
cd ~/Documents/android_8.1
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-8.1.0_r62
repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b android-8.1.0_r62
repo sync -c

五、编译AOSP源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cd ~/Documents/android_8.1
# Set ccache
prebuilts/misc/linux-x86/ccache/ccache -M 50G
# Clean out directory
make clobber
# Jack server configuration
export JACK_SERVER_VM_ARGUMENTS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx6g"
./prebuilts/sdk/tools/jack-admin kill-server
./prebuilts/sdk/tools/jack-admin start-server
# Setup environment
source build/envsetup.sh

# Select device target
lunch
# Build sources (cofee time)
make -j8

六、编译单项

1
2
3
source build/envsetup.sh
cd external/tinyxml
mm

在同一个Android.mk中编写就行:

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
LOCAL_PATH:= $(call my-dir)

#此段是预编译第三方库部分
include $(CLEAR_VARS)
LOCAL_MODULE := libaspmodule
LOCAL_MODULE_TAGS := optional
#LOCAL_SRC_FILES := libaspmodule.so
#32位、64位两者都编译
LOCAL_MULTILIB := both
LOCAL_SRC_FILES_arm:= armeabi-v7a/libaspmodule.so
LOCAL_SRC_FILES_arm64:= arm64-v8a/libaspmodule.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
LOCAL_MODULE_STEM :=$(LOCAL_MODULE)
LOCAL_MODULE_SUFFIX := $(suffix $(LOCAL_SRC_FILES))
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
include $(BUILD_PREBUILT)

#此段是预编译第三方静态库部分
include $(CLEAR_VARS)
LOCAL_MODULE := libnexsound
#LOCAL_SRC_FILES := libnexsound.a
#32位、64位两者都编译
LOCAL_MULTILIB := both
LOCAL_SRC_FILES_arm:= armeabi-v7a/libnexsound.a
LOCAL_SRC_FILES_arm64:= arm64-v8a/libnexsound.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
LOCAL_MODULE_CLASS := STATIC_LIBRARIES
LOCAL_MODULE_SUFFIX:=.a
include $(BUILD_PREBUILT)

#此段是调用前面第三方库编译JNI生成a和so部分
include $(CLEAR_VARS)
LOCAL_C_INCLUDES:= external/tinyalsa/include
LOCAL_SRC_FILES:= com_ecovacs_lib_digmic_DigMic.c
LOCAL_MODULE := libdigmic
LOCAL_SHARED_LIBRARIES:= libcutils libutils libtinyalsa libaspmodule
LOCAL_STATIC_LIBRARIES := libnexsound
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)

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
#!/bin/bash

OS_NAME=$( cat /etc/os-release | grep ^NAME | cut -d'=' -f2 | sed 's/\"//gI' )

case "$OS_NAME" in
"CentOS Linux")
sudo yum install ntpdate ntp -y

sudo timedatectl set-timezone UTC
sudo ntpdate -u ntp.aliyun.com time.windows.com time.apple.com time.google.com time.cloudflare.com
sudo hwclock --systohc # 写入硬件

sudo systemctl enable ntpd
sudo systemctl start ntpd
;;
"Ubuntu" | "Linux Mint")
sudo apt install ntpdate ntp -y

sudo timedatectl set-timezone UTC
sudo ntpdate -u ntp.aliyun.com time.windows.com time.apple.com time.google.com time.cloudflare.com
sudo hwclock --systohc # 写入硬件

sudo systemctl enable ntp
sudo systemctl start ntp
;;
esac

killall命令使用进程的名称来杀死进程,使用此指令可以杀死一组同名进程。我们可以使用kill命令杀死指定进程PID的进程,如果要找到我们需要杀死的进程,我们还需要在之前使用ps等命令再配合grep来查找进程,而killall把这两个过程合二为一,是一个很好用的命令。

语法

1
killall(选项)(参数)

选项

1
2
3
4
5
6
7
8
9
-e:对长名称进行精确匹配;
-l:忽略大小写的不同;
-p:杀死进程所属的进程组;
-i:交互式杀死进程,杀死进程前需要进行确认;
-l:打印所有已知信号列表;
-q:如果没有进程被杀死。则不输出任何信息;
-r:使用正规表达式匹配要杀死的进程名称;
-s:用指定的进程号代替默认信号“SIGTERM”;
-u:杀死指定用户的进程。

参数

进程名称:指定要杀死的进程名称。

实例

杀死所有同名进程

1
killall vi

pgrep命令以名称为依据从运行进程队列中查找进程,并显示查找到的进程id。每一个进程ID以一个十进制数表示,通过一个分割字符串和下一个ID分开,默认的分割字符串是一个新行。对于每个属性选项,用户可以在命令行上指定一个以逗号分割的可能值的集合。

语法

1
pgrep(选项)(参数)

选项

1
2
3
4
5
6
7
-o:仅显示找到的最小(起始)进程号;
-n:仅显示找到的最大(结束)进程号;
-l:显示进程名称;
-P:指定父进程号;
-g:指定进程组;
-t:指定开启进程的终端;
-u:指定进程的有效用户ID。

参数

进程名称:指定要查找的进程名称,同时也支持类似grep指令中的匹配模式。

之前查看进程id一直使用ps aux | grep <进程名>,这个指令像是一个进化版本。

今天下班后收拾东西时,看到很久没有使用的移动硬盘,通电后在资料中翻出这样一段话,从04年到11年的几乎每个压缩包中都有。
但从12年往后就越来越少,最近这几年就不在加这个注释,一是压缩软件由之前的winrar换成了7zip,系统慢慢换成linux,二是一直在忙于生计,似乎离理想越来越远。
今年碰到疫情,在老家待了几个月,觉得现在的状态似乎不是自己想要的,其实包括最近这两年,似乎一直有这样的想法。
那么自己的想要的到底是什么呢?
十岁时的电视里成功经理人的梦想?还是十五岁时看到的介绍比尔盖茨的用技术改变世界的梦想?
是刚工作时的CTO?还是最近的多多赚钱?
似乎都是,又似乎都不是。
没工作时,想着先找个工作,养家糊口。
有工作时,想着能不能做的更好一些,最后发现努力半天,因为诸多原因一次次报废。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
      \\\|///
     \\ -.- //
     ( @.@ )
+----oOOo----(_)------------+
|               |
| 为了理想          |
|  要付出代价        |
|   我想我会坚持      |
|    并努力走下去     |
|               |
|        Rise Worlds |
|               |
+------------------oOOo-----+
      |__|__|
       || ||
      ooO Ooo

插曲
最近这次工作开始时有几个地方可以选,最后选了一个薪水最少的,只因之前认识。
来到后也很努力,比之前工作都要努力,因为是个二线城市(二线top 5+),招来的人技术差不多差了一个层次,很多事情短时间没办法安排下去,只有自己搞。
从c++到php,从mysql到nodejs,到React Native,从后端到前端。
计划手里事情忙的差不多了,把比较闲的人给培训一下,有后台的给换走。反而因为把有的人空下来了,然而这时另一个项目组换了个新头,比较会来事,和领导关系好,把自己这有用没用的人都给要走了。
后面基本上剩自己一个人坚持抗着整个后端,其实这个项目真的不需要人吗?不是,是需要很多人。
问题来了,搞了半年也没搞的非常出色,甚至还不如自己这两个人撑着的项目。结果年会的时候还得了几个奖,甚至还有加班最长时间奖(真搞笑,无效加班叫加班吗?)。
如果问为啥要人时一声不吭?因为有的人本来就不想要,而恰恰开始要的就是不想要的人,之后又没人补上,工作已经铺不开了,索性就要谁给谁吧,因为我觉得大家思维都在线(要谁给谁,放哪都不正常),没人项目怎么继续?
年后疫情期间,运营那边要上很多新功能,要的又急,实在不想这样撑着了,撑不动了,脑子都转不过来,运营不清晰的描述(主要是很多功能运营还不确定),从后端到前端的功能逻辑,两个娃的网课。
不知道其他人会怎么想,按着我的思维方式是,A项目不重要?B关系不如另个项目组的好?C项目不想搞了?至最后撑不下去的时候,嗯,可能都存在,于是就不撑着了呗。
到现在接手自己工作的4、5个人(问题有的工作还不一定能接的下来),做我之前就准备要做的一些事情,想来真的很悲哀。
现在想想自己的问题就是没事的时候让他们闲着了,应该搞些可有可无的工作把坑占着,哈哈。


插曲结束,回到之前的问题。
其实结合时至今日所见所得,自己想要的应该是温饱之余,那一丝丝成就感吧。
至于那一丝丝成就感是什么?
可能是解决了一个技术问题(其实最近这些年技术上没有什么长进,一直在吃老本,靠着逆向和跳跃思维活着),
也可能是赚了不少钱(例如通过一系列预测操盘股票赚了),
或许是项目上线(用户量很大,技术支撑的住),
或许。。。。。。

62. 不同路径

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

问总共有多少条不同的路径?

示例 1:

1
2
3
4
5
6
7
输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向右 -> 向下
2. 向右 -> 向下 -> 向右
3. 向下 -> 向右 -> 向右

示例 2:

1
2
输入: m = 7, n = 3
输出: 28

提示:

  • 1 <= m, n <= 100
  • 题目数据保证答案小于等于 2 * 10 ^ 9

解题思路

由于我们的目的是从左上角到右下角一共有多少种路径,那我们就定义 dp[i][j]的含义为:当机器人从左上角走到(i, j) 这个位置时,一共有 dp[i][j] 种路径。 那么,dp[m-1][n-1] 就是我们要的答案了。

步骤

找出关系数组元素间的关系式想象以下,机器人要怎么样才能到达 (i, j) 这个位置?由于机器人可以向下走或者向右走,所以有两种方式到达一种是从 (i-1, j) 这个位置走一步到达一种是从(i, j - 1) 这个位置走一步到达因为是计算所有可能的步骤,所以是把所有可能走的路径都加起来,所以关系式是 dp[i][j] = dp[i-1][j] + dp[i][j-1]
找出初始值显然,当 dp[i][j] 中,如果 i 或者 j 有一个为 0,那么还能使用关系式吗?答是不能的,因为这个时候把 i - 1 或者 j - 1,就变成负数了,数组就会出问题了,所以我们的初始值是计算出所有的 dp[0][0….n-1] 和所有的 dp[0….m-1][0]
这个还是非常容易计算的,相当于计算机图中的最上面一行和左边一列。因此初始值如下:
dp[0][0…n-1] = 1; // 相当于最上面一行,机器人只能一直往左走
dp[0…m-1][0] = 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
class Solution
{
public:
int uniquePaths(int m, int n)
{
if (m <= 0 || n <= 0)
{
return 0;
}
if (m == 1 || n == 1)
{
return 1;
}

vector<vector<int>> dp(m, vector<int>(n)); //创建大小为m*n的数组
// 初始化
for (int i = 0; i < m; i++)
{
dp[i][0] = 1;
}
for (int i = 0; i < n; i++)
{
dp[0][i] = 1;
}
// 推导出 dp[m-1][n-1]
for (int i = 1; i < m; i++)
{
for (int j = 1; j < n; j++)
{
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[m - 1][n - 1];
}
};

优化

根据公式 dp[i][j] = dp[i-1][j] + dp[i][j-1],我们可以知道,当我们要计算第 i 行的值时,除了会用到第 i - 1 行外,其他第 1 至 第 i-2 行的值我们都是不需要用到的,因为计算某一行的时候,依赖的是左一结果和上一结果,所以我们存一行的记录,只要这一行包含当前元素的左一结果和上一结果即可。我们只需要用一个一维的 dp[] 来保存一行的历史记录就可以了。然后在计算的过程中,不断着更新 dp[] 的值。
所以在dp[n]这个数组里面,dp[0]...dp[j-1]是本一行的,dp[j]...dp[n]是上一行。

代码

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
class Solution {
public:
int uniquePaths(int m, int n) {
if (m <= 0 || n <= 0)
{
return 0;
}
if (m == 1 || n == 1)
{
return 1;
}

vector<int> dp(n);
// 初始化
for (int i = 0; i < n; i++)
{
dp[i] = 1;
}
// 推导出 dp[m-1][n-1]
for (int i = 1; i < m; i++)
{
// 第 i 行第 0 列的初始值
dp[0] = 1;
for (int j = 1; j < n; j++)
{
dp[j] = dp[j - 1] + dp[j];
}
}
return dp[n - 1];
}
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public:
int strStr(string haystack, string needle) {
int n = haystack.size(), m = needle.size();
if (!m) return 0;
if (!n) return -1;
for (int i = 0; i < n - m + 1; ++i)
{
int j = 0;
for( ; j < m; ++j)
{
if(haystack[i + j] != needle[j])
break;
}
if (j == m)
return i;
}
return -1;
}
};

时间复杂度 $O(M*N)$

力扣27题《移除元素》

题目描述不允许使用额外的数组空间,所以只能在原数组上操作。

我们使用两个指针,一个快指针 i 和一个慢指针 k 。i 每次移动一步,而 k 只在添加新的被需要的值时才移动一步。

因为我们的新数组的长度会小于等于旧数组,调用者在调用函数时根据返回的长度,它会打印出数组中该长度范围(k)内的所有元素。因此,范围外的元素不会输出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int k = 0;
for(int i = 0; i < nums.size(); ++i)
{
if(nums[i] != val)
{
nums[k] = nums[i];
++ k;
}
}
return k;
}
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
--QPTreasureDB为需要清除日志的数据库名称
USE [master]
GO
ALTER DATABASE QPTreasureDB SET RECOVERY SIMPLE WITH NO_WAIT
GO
ALTER DATABASE QPTreasureDB SET RECOVERY SIMPLE   --简单模式
GO
USE QPTreasureDB
GO
DBCC SHRINKFILE (N'QPTreasureDB_Log' , 11, TRUNCATEONLY) --设置压缩后的日志大小为11M,可以自行指定
GO

USE [master]
GO
ALTER DATABASE QPTreasureDB SET RECOVERY FULL WITH NO_WAIT
GO
ALTER DATABASE QPTreasureDB SET RECOVERY FULL  --还原为完全模式
GO

由于有些规定,要保密个人信息,只能通过这种方法来把个人信息给过滤掉。

修改OLD_EMAIL为要替换的旧邮箱,NEW_NAMENEW_EMAIL为新的个人名字和邮箱,修改完成后强制更新到服务器。

这样只能一个人一个人的修改,其他人重新克隆仓库,如果要修改文件内容,请看初次使用 git 的“核弹级选项”:filter-branch 从仓库中删除文件

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

#!/bin/bash



git filter-branch --env-filter '

OLD_EMAIL="rise.worlds@outlook.com"

NEW_NAME="rise"

NEW_EMAIL="rise.worlds@live.com"

if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]

then

export GIT_COMMITTER_NAME="$NEW_NAME"

export GIT_COMMITTER_EMAIL="$NEW_EMAIL"

fi

if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]

then

export GIT_AUTHOR_NAME="$NEW_NAME"

export GIT_AUTHOR_EMAIL="$NEW_EMAIL"

fi

' --tag-name-filter cat -- --branches --tags

# 覆盖到远程仓库

# git gc

# git push --force --tags origin 'refs/heads/*'

如果要针对个别的仓库这样,要在完成后在仓库中设置新的名字和邮箱

1
2
3
4
5

git config user.name 'rise'

git config user.email 'rise.worlds@live.com'

打开项目文件夹下 node_modules/react-native/local-cli/runIOS/findMatchingSimulator.js

查找

1
2
3

if (!version.startsWith('iOS') && !version.startsWith('tvOS'))

修改为

1
2
3

if (!version.startsWith('com.apple.CoreSimulator.SimRuntime.iOS') && !version.startsWith('com.apple.CoreSimulator.SimRuntime.tvOS'))

查找

1
2
3

simulator.isAvailable !== 'YES'

修改为

1
2
3

if (simulator.isAvailable !== true)

原方法地址 https://github.com/facebook/react-native/issues/21498#issuecomment-476621627

1. 名词解释

  1. 创世节点(BIOS) 用于创建初始区块,加载基础合约,供其它节点同步连接。

  2. 矿工节点(BP) 主要用于生产同步区块,计算合约产生的费用归矿工账号所有。

  3. 查询节点 不产生区块,同步区块信息,提供区块信息查询功能。

  4. 私钥 用来进行签名操作,私钥可以生成唯一对应公钥。

  5. 公钥 用来对私钥的签名进行验证。

  6. 钱包 生成和保存私钥的地方,当需要进行签名操作时,会从钱包读取私钥列表,进行签名。

  7. 带宽 带宽分为cpu带宽和net带宽两种,每次执行合约都会消耗一定的带宽(从账号中扣取)。

  8. 合约 一段在链上可执行代码,绑定在账号上,每个账号只能绑定一份合约。

  9. 账号 存储用户信息,包括余额、带宽、合约(如果有)等。

  10. 总票数 总票数=总发行的货币数量。

  11. 投票 投票者抵押货币投票给矿工,当矿工投票数大于总票数的15%时创世节点停止产生区块,转由矿工生产区块。

    所谓的矿工节点与查询节点,只是为了区分是否生产区块的不同配置。

2. 节点代码编译、程序安装

注意:后面编译依赖GIT,所以务必保证代码根目录的.git完整,以及系统安装有git。

以下以ubuntu系统为例,其它系统步骤类似。

  1. 先安装GIT,如果已经安装则忽略这一步

    1
    2
    3

    sudo apt update && sudo apt install git -y

  2. 从GIT上克隆最新代码

    1
    2
    3

    git clone https://github.com/eosio/eos --recursive --depth 1

  3. 使用eosio_build.sh自动编译

    脚本会检查系统依赖库,并自动安装,请注意管理员权限提示,如果下载依赖库时中断请检查网络状态,然后再次执行。

    1
    2
    3
    4
    5
    6
    7

    cd eosio

    export LOCAL_CMAKE_FLAGS="-DEOSIO_ROOT_KEY=EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV -DCORE_SYMBOL_NAME=EOS"

    ./script/eosio_build.sh

    正式环境可以使用LOCAL_CMAKE_FLAGS环境变量指定根公钥EOSIO_ROOT_KEY和系统货币符号CORE_SYMBOL_NAME

  4. 打包和安装

    编译成功会出现’EOSIO’的ASCII图样提示,请执行以下操作,把程序安装到系统,如果出现编译错误,请提交错误提示给相关人员查看解决。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    cd build/packages

    bash ./generate_package.sh [brew|deb|rpm]

    ls



    #ubuntu

    sudo dpkg -i eosio-v1.7.3.deb



    #redhat

    sudo yum install eosio-v1.7.3.rpm

    #或者

    sudo rpm -ivh eosio-v1.7.3.rpm

    参数说明:

    • brew mac系统

    • deb ubuntu系系统

    • rpm redhat系系统

  5. 重新编译

    如果有修改代码,或者进行版本更新,请先关闭当前运行的钱包和节点程序,以及清除安装到系统的想着程序,再编译。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    pkill -2 keosd nodeos

    #ubuntu

    sudo apt remove eosio

    #redhat

    sudo yum remove eosio

3. 默认配置文件所在目录

Linux: ~/.local/share/eosio/nodeos/config

Mac: ~/Library/Application Support/eosio/nodeos/config

4. 创建默认钱包和公私钥

  1. 启动钱包服务

    1
    2
    3

    keosd --unlock-timeout 3600 # 3600秒后钱包重新锁定

  2. 创建钱包

    请保存输出的钱包密码,下次打开钱包时用的到。

    1
    2
    3
    4
    5
    6
    7
    8
    9

    cleos wallet create -n default



    #打开钱包

    cleos wallet open -n default

  3. 创建公私钥

    1
    2
    3

    cleos create key

  4. 把上步生成的私钥导入钱包

    1
    2
    3

    cleos wallet import -n default --private-key [private key]

5. 通用配置

| 参数名 | 示例 | 说明 |

| ———————– | ———————————————————————————————————————- | —————————————————————————————————————- |

| agent-name | p2p网络中标识自己的节点的名字 | “eosio bios” |

| producer-name | 矿工的账号名 | “eosio” |

| signature-provider | 矿工的公钥私钥,用于签名 | EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
=KEY:5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3 |

| p2p-server-address | p2p服务监听地址,默认监听0.0.0.0:9876 | “0.0.0.0:9876” |

| http-server-address | http服务器监听地址,如果不想提供http服务,可以把地址留空,则不http服务不启动。注意不填写会使用默认地址127.0.0.1:8888 | “127.0.0.1:8888” |

| enable-stale-production | 启动后立即开始生产块。如果不是BIOS节点,这里填false。 | true |

| p2p-peer-address | 其它节点的p2p同步地址,用于同步数据,此参数可以有多个,即连接到多个节点。 | “192.168.0.2:9876” |

6. 创世节点配置

6.1. 启动参数配置

  1. 创建eosio系统账号的公私钥,参见4. 创建钱包和公私钥

  2. 修改genesis.json的initial_key为上一步生成的公钥

  3. 启动节点,注意填写第1步生成的公私钥

    1
    2
    3
    4
    5
    6
    7
    8
    9

    nodeos --agent-name "eosio bios" --producer-name "eosio" \

    --signature-provider [public key]=KEY:[private key] \

    --plugin eosio::chain_plugin --plugin eosio::chain_api_plugin \

    --p2p-server-address "0.0.0.0:9876" --http-server-address "127.0.0.1:8888" --enable-stale-production

6.2. 部署系统合约

  1. 下载编译合约编译器

    1
    2
    3
    4
    5
    6
    7
    8
    9

    git clone https://github.com/eosio/eosio.cdt.git --recursive --depth 1

    cd eosio.cdt

    ./build.sh

    sudo ./install.sh

  2. 下载编译合约

    1
    2
    3
    4
    5
    6
    7

    git clone https://github.com/eosio/eosio.contracts.git --depth 1

    cd eosio.contracts

    ./build.sh

  3. 创建系统账号

    OwnerKey与ActiveKey相同,参见6.1生成的公钥

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    cleos create account eosio eosio.token [OwnerKey] [ActiveKey] -p eosio

    cleos create account eosio eosio.msig [OwnerKey] [ActiveKey] -p eosio

    cleos create account eosio eosio.bpay [OwnerKey] [ActiveKey] -p eosio

    cleos create account eosio eosio.names [OwnerKey] [ActiveKey] -p eosio

    cleos create account eosio eosio.ram [OwnerKey] [ActiveKey] -p eosio

    cleos create account eosio eosio.ramfee [OwnerKey] [ActiveKey] -p eosio

    cleos create account eosio eosio.saving [OwnerKey] [ActiveKey] -p eosio

    cleos create account eosio eosio.stake [OwnerKey] [ActiveKey] -p eosio

    cleos create account eosio eosio.vpay [OwnerKey] [ActiveKey] -p eosio

    如果使用LOCAL_CMAKE_FLAGS参数指定了根公钥,则这里必须相同。

  4. 部署货币合约,请确认在合约代码根目录执行,参见6.2.2下载编译合约

    1
    2
    3
    4
    5

    cleos set contract eosio.token build/eosio.token -p eosio.token

    cleos set contract eosio.msig build/eosio.msig -p eosio.msig

  5. 创建货币

    1
    2
    3
    4
    5

    cleos push action eosio.token create '["eosio", "1000000000000.0000 EOS", 0, 0, 0]' -p eosio.token

    cleos push action eosio.token issue '["eosio", "1000000000000.0000 EOS", "issue"]' -p eosio

    如果使用LOCAL_CMAKE_FLAGS参数指定了系统货币符号,则这里必须相同。

  6. 部署系统合约,请确认在合约代码根目录执行,参见6.2.2下载编译合约

    1
    2
    3
    4
    5
    6
    7

    cleos set contract eosio build/eosio.system -p eosio

    cleos push action eosio init '[0, "4,EOS"]' -p eosio@active

    cleos push action eosio setpriv '["eosio.msig", 1]' -p eosio@active

7. 矿工节点配置

1. 注册矿工账号

  1. 创建矿工账号的公私钥,参见4. 创建钱包和公私钥

  2. 创建矿工账号

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    cleos system newaccount --stake-net [quantity] --stake-cpu [quantity] --buy-ram-kbytes 8192 \

    [creater] [name] [OwnerKey] [ActiveKey] -p [creater]

    # 参数说明

    # creater 矿工账号的创建者账号。

    # name 矿工账号的名字。

    # quantity 购买带宽的资源,从创建者账号扣取。

    # OwnerKey与ActiveKey相同,矿工账号的公钥,即上步生成的公钥。



    # 示例

    cleos system newaccount --stake-net "50.0000 EOS" --stake-cpu "50.0000 EOS" --buy-ram-kbytes 8888888 eosio eosnewbpa \

    EOS7n1U9Z2NQeVEvQZYjHCedNXRVWshmmuGH2j3r6bD4c8fH4U8QL EOS7n1U9Z2NQeVEvQZYjHCedNXRVWshmmuGH2j3r6bD4c8fH4U8QL -p eosio

  3. 转账给矿工账号

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    cleos transfer [from] [recipient] [amount] [momo]

    # 参数说明

    # from 转账账号

    # recipient 接收转账账号

    # amount 金额

    # momo 注释



    # 示例

    cleos transfer eosio eosnewbpa "9000000000.0000 EOS" "trans to eosnewbpa"

  4. 注册成矿工

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    cleos system regproducer [name] [ActiveKey] [url]

    # 参数说明

    # name 矿工账号

    # ActiveKey 矿工账号的公钥

    # url 矿工的网站



    #示例

    cleos system regproducer eosnewbpa EOS7n1U9Z2NQeVEvQZYjHCedNXRVWshmmuGH2j3r6bD4c8fH4U8QL https://192.168.0.57:8888

  5. 抵押相应的资源

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    cleos system delegatebw [name] [name] [stake_net_quantity] [stake_cpu_quantity]

    # 参数说明

    # name 矿工账号

    # stake_net_quantity 抵押的网络带宽资源

    # stake_cpu_quantity 抵押的CPU带宽资源



    # 示例

    cleos system delegatebw eosnewbpa eosnewbpa '4400000000.0000 EOS' '4400000000.0000 EOS'

  6. 投票给自己

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    cleos system voteproducer prods [voter] [producers] -p [voter]

    # 参数说明

    # voter 矿工账号

    # producers 抵押的网络带宽资源



    #示例

    cleos system voteproducer prods eosnewbpa eosnewbpa

2. 启动参数配置

  1. 创建eosio系统账号的公私钥,参见创建钱包和公私钥

  2. 修改genesis.json的initial_key为创世节点(BIOS)生成的公钥

  3. 启动节点,注意填写第1步生成的公私钥

    假设已知bios节点192.168.0.56:9876,BP节点192.168.0.58:9876。

    1
    2
    3
    4
    5
    6
    7
    8
    9

    nodeos --agent-name "eosnewbpa" --producer-name "eosnewbpa" \

    --signature-provider [public key]=KEY:[private key] \

    --p2p-server-address "0.0.0.0:9876" --http-server-address "127.0.0.1:8888" \

    --p2p-peer-address "192.168.0.56:9876" --p2p-peer-address "192.168.0.58:9876"

8. 查询节点配置

查询节点配置与矿工节点配置类似,只是不注册成矿工,查询节点常用来数据查询。建议开启mongo_db_plugin插件。

mongo_db_plugin是保存区块交易信息到mongodb的插件。

假设已知bios节点192.168.0.56:9876,BP节点192.168.0.57:9876、192.168.0.58:9876,并且这三个节点都开启了mongo_db_plugin插件。

1
2
3
4
5
6
7
8
9
10
11

nodeos --agent-name "eosnewbpb" --producer-name "eosnewbpb" \

--signature-provider [public key]=KEY:[private key] \

--p2p-server-address "0.0.0.0:9876" --http-server-address "127.0.0.1:8888" \

--p2p-peer-address "192.168.0.56:9876" --p2p-peer-address "192.168.0.57:9876" --p2p-peer-address "192.168.0.58:9876" \

--plugin eosio::mongo_db_plugin --mongodb-uri mongodb://127.0.0.1:27017/EOSIO

9. 建议

  1. 从安全角度来说,不要私钥泄露给他人,知道账户私钥后,可以随意操纵账户。

  2. 如果使用助记词生成的私钥,请使用复杂度较高的助记词。

  3. 上面传入很多参数都是演示用的,如果正式部署,建议使用配置文件的方式。

  4. 建议使用SIGINT信号来关闭节点,防止程序产生脏数据。

    1
    2
    3

    pkill -2 keosd nodeos

  5. 如果有脏数据产生,请使用–replay-blockchain参数或者–delete-all-blocks参数启动节点,重新同步数据。

  6. 节点启动前,请确认时间及时区正确,时间有偏移会影响区块数据验证。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

    sudo mv /etc/localtime /etc/localtime.bak

    sudo ln -s /usr/share/zoneinfo/UTC /etc/localtime

    # 使用 ntpdate 更新系统时间

    sudo apt install ntpdate ntp -y # yum install ntpdate ntp -y

    sudo timedatectl set-timezone UTC

    sudo ntpdate -u time.windows.com

    sudo hwclock --systohc # 写入硬件

    # 启动ntpd服务

    sudo systemctl enable ntp # systemctl enable ntpd

    sudo systemctl start ntp # systemctl start ntpd

最近老被一些人问些问题,其实都看过,只是印象不深刻,或者觉得不那么重要,就没花更多的精力去研究。

工作上的东西,也只是写在onenote或者公司的文档上,写完也没记,反正用时可以看文档。

我一直觉得这是我的一个大问题,用到的时候(过很长一段时间),要么印象不深,要不是是而非,而且在博客园的排名掉到600名外了,所以决定过段时间就把最近的总结一下,希望可以有足够的精力和毅力坚持下去。

大致想分为几大块:

  • 和工作有关的内容(在不涉密的情况下)

  • 一些经常用的内容

  • 区块链

  • 算法

  • 尝试新语言

  • 阿里云镜像
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 替换brew.git:

cd "$(brew --repo)"

git remote set-url origin https://mirrors.aliyun.com/homebrew/brew.git

# 替换homebrew-core.git:

cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core"

git remote set-url origin https://mirrors.aliyun.com/homebrew/homebrew-core.git

# 应用生效

brew update -v

# 替换homebrew-bottles(最好保存到配置文件):

export HOMEBREW_BOTTLE_DOMAIN=https://mirrors.aliyun.com/homebrew/homebrew-bottles

  • 中科大镜像
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

cd "$(brew --repo)"

git remote set-url origin https://mirrors.ustc.edu.cn/brew.git



cd "$(brew --repo)/Library/Taps/homebrew/homebrew-cask"

git remote set-url origin https://mirrors.ustc.edu.cn/homebrew-cask.git



cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core"

git remote set-url origin https://mirrors.ustc.edu.cn/homebrew-core.git

brew update -v

export HOMEBREW_BOTTLE_DOMAIN=https://mirrors.ustc.edu.cn/homebrew-bottles

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

const TX_TYPE_IN = 1;

const TX_TYPE_OUT = 2;



export const CreateUtxos = async (address: string, data: any) => {

let mapData = new Map();

let temp = new Map();

for (const iter of data) {

mapData.set(iter.hash, iter);

// console.log(iter.hash);

let type = TX_TYPE_IN;

for (const input of iter.inputs) {

if (input.coin.coinbase) continue;

if (address == input.coin.address) {

type = TX_TYPE_OUT;

}

}

let out = -1;

let balance = 0;

for (const output of iter.outputs) {

out++;

if (address == output.address) {

balance = output.value;

break;

}

}

temp.set(iter.hash, { type, out, balance, spentTxid: null, spentHeight: 0 });

}



for (const [key, value] of mapData) {

for (const input of value.inputs) {

if (input.coinbase) continue;

if (temp.has(input.prevout.hash)) {

const pre = temp.get(input.prevout.hash);

const local = temp.get(key);

if (pre.spentHeight <= 0 && (pre.type != local.type || local.type == TX_TYPE_OUT)) {

pre.spentTxid = value.hash;

pre.spentHeight = value.height;

}

}

}

}

let balance = 0;

let unspentList: Array<any> = [];

for (const [key, value] of temp) {

if (value.spentHeight === 0) {

balance += value.balance;

// console.info(key, value.out);

unspentList.push(value);

} /*else {

temp.delete(key);

}*/

}



// return {balance, unspentList: Array.from(temp.values())}

return { balance, unspentList };

}



使用阿里源

新建一个init.gradle 文件到$USER_HOME/.gradle/目录下,这们就省的翻墙了。

init.gradle 文件内容如下:

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

allprojects {

repositories {

maven {

url 'https://maven.aliyun.com/repository/public/'

}

maven {

url 'https://maven.aliyun.com/repository/google/'

}



all { ArtifactRepository repo ->

if (repo instanceof MavenArtifactRepository) {

def url = repo.url.toString()



if (url.startsWith('https://repo.maven.apache.org/maven2/') || url.startsWith('https://repo.maven.org/maven2')

|| url.startsWith('https://repo1.maven.org/maven2') || url.startsWith('https://jcenter.bintray.com/')

|| url.startsWith('https://maven.google.com/') || url.startsWith('https://dl.google.com/dl/android/maven2/')) {

//project.logger.lifecycle "Repository ${repo.url} replaced by $REPOSITORY_URL."

remove repo

}

}

}

}



buildscript {

repositories {

maven{ url 'https://maven.aliyun.com/repository/public/'}

maven{ url 'https://maven.aliyun.com/repository/google/'}



all { ArtifactRepository repo ->

if (repo instanceof MavenArtifactRepository) {

def url = repo.url.toString()

if (url.startsWith('https://repo1.maven.org/maven2') || url.startsWith('https://jcenter.bintray.com/')

|| url.startsWith('https://dl.google.com/dl/android/maven2/')) {

//project.logger.lifecycle "Repository ${repo.url} replaced by $REPOSITORY_URL."

remove repo

}

}

}

}

}



}

全局翻墙代理配置

同样新建一个gradle.properties 文件到$USER_HOME/.gradle/目录下,如果放在项目目录下,则只对当前项目生效。

gradle.properties 文件内容如下:

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

## For more details on how to configure your build environment visit

# http://www.gradle.org/docs/current/userguide/build_environment.html

#

# Specifies the JVM arguments used for the daemon process.

# The setting is particularly useful for tweaking memory settings.

# Default value: -Xmx1024m -XX:MaxPermSize=256m

# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8

#

# When configured, Gradle will run in incubating parallel mode.

# This option should only be used with decoupled projects. More details, visit

# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects

# org.gradle.parallel=true

#Wed Apr 10 21:30:10 CST 2019

systemProp.https.nonProxyHosts=127.0.0.1

systemProp.http.proxyHost=127.0.0.1

systemProp.https.proxyPort=8787

systemProp.http.nonProxyHosts=127.0.0.1

systemProp.https.proxyHost=127.0.0.1

systemProp.http.proxyPort=8787

  • 转账的时候需要手动寻找每一笔未花费记录实在太费时。

  • 比特币转账需要提取或合并所有未花费的交易中的比特币,才能实现交易。

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

import * as bitcoin from 'bitcoinjs-lib';

import fetch, { Response } from 'node-fetch';



const quantitySat = 0.0001 * 1e8;

const feeSat = 0.0001 * 1e8;



(async () => {

try {

let NETWORK = bitcoin.networks.testnet;

const keyPair = bitcoin.ECPair.fromWIF(from_pvtkey, NETWORK);

const p2pkh = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey, network: NETWORK });

let from = p2pkh.address;

const utxoResponse: Response = await fetch(`https://api.blockcypher.com/v1/btc/test3/addrs/${from}`);

const json = await utxoResponse.json();

console.log(json);

let balance = json.balance;

let unspentList: Array<any> = [];

// 过滤掉已经被花费了的交易和未确认的交易,以及自己不在接收列表的交易

const txrefs = json.txrefs;

const unconfirmed_txrefs = json.unconfirmed_txrefs;

if (unconfirmed_txrefs && unconfirmed_txrefs.length > 0) {

// 要把未确认的余额给去掉

balance += json.unconfirmed_balance;

unspentList = unspentList.concat(unconfirmed_txrefs.filter((item: any) => !item.spent_by && item.tx_output_n !== -1));

}

if (txrefs.length > 0) {

unspentList = unspentList.concat(txrefs.filter((item: any) => !item.spent_by && item.tx_output_n !== -1));

}



// 构建交易对象

let txb = new bitcoin.TransactionBuilder(NETWORK);



// 批量插入未花费交易

unspentList.forEach((item: any) => txb.addInput(item.tx_hash, item.tx_output_n));

// 转出账户

txb.addOutput(to, quantitySat);

// 预留手续费

txb.addOutput(from, balance - quantitySat - feeSat);

// 批量签名,根据索引即可

unspentList.forEach((item: any, index: any) => { txb.sign(index, keyPair) });

// 序列化交易

let tx = txb.build();

console.log(tx.getHash().toString('hex'));



// 在一个测试链的节点把交易广布出去

const result = await fetch('https://api.blockcypher.com/v1/btc/test3/txs/push',{

method:'post',

headers:{'Content-Type':'application/json'},

body:JSON.stringify({tx: tx.toHex()})

});





} catch (error) {

console.error(error);

}

})();

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567

https://torrent.ubuntu.com/announce

https://ipv6.torrent.ubuntu.com/announce

http://torrent.centos.org:6969/announce

http://ipv6.torrent.centos.org:6969/announce



http://182.176.139.129:6969/announce

http://5.79.83.193:2710/announce

http://91.218.230.81:6969/announce

http://atrack.pow7.com/announce

http://bt.henbt.com:2710/announce

http://mgtracker.org:2710/announce

http://mgtracker.org:6969/announce

http://open.touki.ru/announce.php

http://p4p.arenabg.ch:1337/announce

http://pow7.com:80/announce

http://retracker.krs-ix.ru:80/announce

http://secure.pow7.com/announce

http://t1.pow7.com/announce

http://t2.pow7.com/announce

http://thetracker.org:80/announce

http://torrentsmd.com:8080/announce

http://tracker.bittor.pw:1337/announce

http://tracker.dutchtracking.com:80/announce

http://tracker.dutchtracking.nl:80/announce

http://tracker.edoardocolombo.eu:6969/announce

http://tracker.ex.ua:80/announce

http://tracker.kicks-ass.net:80/announce

http://tracker1.wasabii.com.tw:6969/announce

http://tracker2.itzmx.com:6961/announce

http://www.wareztorrent.com:80/announce

udp://62.138.0.158:6969/announce

udp://eddie4.nl:6969/announce

udp://explodie.org:6969/announce

udp://shadowshq.eddie4.nl:6969/announce

udp://shadowshq.yi.org:6969/announce

udp://tracker.eddie4.nl:6969/announce

udp://tracker.mg64.net:2710/announce

udp://tracker.sktorrent.net:6969

udp://tracker2.indowebster.com:6969/announce

udp://tracker4.piratux.com:6969/announce

http://atrack.pow7.com/announce

http://bt.henbt.com:2710/announce

http://mgtracker.org:2710/announce

http://mgtracker.org:6969/announce

http://open.touki.ru/announce.php

http://p4p.arenabg.ch:1337/announce

http://pow7.com:80/announce

http://retracker.krs-ix.ru:80/announce

http://secure.pow7.com/announce

http://t1.pow7.com/announce

http://t2.pow7.com/announce

http://thetracker.org:80/announce

http://torrentsmd.com:8080/announce

http://tracker.bittor.pw:1337/announce

http://tracker.dutchtracking.com/announce

http://tracker.dutchtracking.com:80/announce

http://tracker.dutchtracking.nl:80/announce

http://tracker.edoardocolombo.eu:6969/announce

http://tracker.ex.ua:80/announce

http://tracker.kicks-ass.net:80/announce

http://tracker.mg64.net:6881/announce

http://tracker.tfile.me/announce

http://tracker1.wasabii.com.tw:6969/announce

http://tracker2.itzmx.com:6961/announce

http://tracker2.wasabii.com.tw:6969/announce

http://www.wareztorrent.com:80/announce

udp://bt.xxx-tracker.com:2710/announce

udp://eddie4.nl:6969/announce

udp://shadowshq.eddie4.nl:6969/announce

udp://shadowshq.yi.org:6969/announce

udp://tracker.eddie4.nl:6969/announce

udp://tracker.mg64.net:2710/announce

udp://tracker.mg64.net:6969/announce

udp://tracker.opentrackr.org:1337/announce

udp://tracker.sktorrent.net:6969

udp://tracker2.indowebster.com:6969/announce

udp://tracker4.piratux.com:6969/announce

udp://tracker.coppersurfer.tk:6969/announce

http://tracker.opentrackr.org:1337/announce

udp://zer0day.ch:1337/announce

http://explodie.org:6969/announce

udp://tracker.leechers-paradise.org:6969/announce

udp://9.rarbg.com:2710/announce

udp://p4p.arenabg.com:1337/announce

udp://tracker.sktorrent.net:6969/announce

http://p4p.arenabg.com:1337/announce

udp://tracker.aletorrenty.pl:2710/announce

http://tracker.aletorrenty.pl:2710/announce

http://tracker.bittorrent.am/announce

udp://tracker.kicks-ass.net:80/announce

http://tracker.kicks-ass.net/announce

http://tracker.baravik.org:6970/announce

udp://tracker.piratepublic.com:1337/announce

udp://torrent.gresille.org:80/announce

http://torrent.gresille.org/announce

http://tracker.skyts.net:6969/announce

http://tracker.internetwarriors.net:1337/announce

udp://tracker.skyts.net:6969/announce

http://tracker.dutchtracking.nl/announce

udp://tracker.yoshi210.com:6969/announce

udp://tracker.tiny-vps.com:6969/announce

udp://tracker.internetwarriors.net:1337/announce

udp://mgtracker.org:2710/announce

http://tracker.yoshi210.com:6969/announce

http://tracker.tiny-vps.com:6969/announce

udp://tracker.filetracker.pl:8089/announce

udp://tracker.ex.ua:80/announce

udp://91.218.230.81:6969/announce

https://www.wareztorrent.com/announce

http://www.wareztorrent.com/announce

http://tracker.filetracker.pl:8089/announce

http://tracker.ex.ua/announce

http://tracker.calculate.ru:6969/announce

udp://tracker.grepler.com:6969/announce

udp://tracker.flashtorrents.org:6969/announce

udp://tracker.bittor.pw:1337/announce

http://tracker.tvunderground.org.ru:3218/announce

http://tracker.grepler.com:6969/announce

http://tracker.flashtorrents.org:6969/announce

http://retracker.gorcomnet.ru/announce

http://bt.pusacg.org:8080/announce

http://87.248.186.252:8080/announce

udp://tracker.kuroy.me:5944/announce

udp://182.176.139.129:6969/announce

http://tracker.kuroy.me:5944/announce

http://retracker.krs-ix.ru/announce

http://open.acgtracker.com:1096/announce

udp://open.stealth.si:80/announce

udp://208.67.16.113:8000/announce

http://tracker.dler.org:6969/announce

http://bt2.careland.com.cn:6969/announce

http://open.lolicon.eu:7777/announce

http://tracker.opentrackr.org:1337/announce

http://explodie.org:6969/announce

http://p4p.arenabg.com:1337/announce

http://tracker.aletorrenty.pl:2710/announce

http://tracker.bittorrent.am/announce

http://tracker.kicks-ass.net/announce

http://tracker.baravik.org:6970/announce

http://torrent.gresille.org/announce

http://tracker.skyts.net:6969/announce

http://tracker.internetwarriors.net:1337/announce

http://tracker.dutchtracking.nl/announce

http://tracker.yoshi210.com:6969/announce

http://tracker.tiny-vps.com:6969/announce

http://www.wareztorrent.com/announce

http://tracker.filetracker.pl:8089/announce

http://tracker.ex.ua/announce

http://tracker.calculate.ru:6969/announce

http://tracker.tvunderground.org.ru:3218/announce

http://tracker.grepler.com:6969/announce

http://tracker.flashtorrents.org:6969/announce

http://retracker.gorcomnet.ru/announce

http://bt.pusacg.org:8080/announce

http://87.248.186.252:8080/announce

http://tracker.kuroy.me:5944/announce

http://retracker.krs-ix.ru/announce

http://open.acgtracker.com:1096/announce

http://bt2.careland.com.cn:6969/announce

http://open.lolicon.eu:7777/announce

https://www.wareztorrent.com/announce

udp://213.163.67.56:1337/announce

http://213.163.67.56:1337/announce

udp://185.86.149.205:1337/announce

http://74.82.52.209:6969/announce

udp://94.23.183.33:6969/announce

udp://74.82.52.209:6969/announce

udp://151.80.120.114:2710/announce

udp://109.121.134.121:1337/announce

udp://168.235.67.63:6969/announce

http://109.121.134.121:1337/announce

udp://178.33.73.26:2710/announce

http://178.33.73.26:2710/announce

http://85.17.19.180/announce

udp://85.17.19.180:80/announce

http://210.244.71.25:6969/announce

http://85.17.19.180/announce

http://213.159.215.198:6970/announce

udp://191.101.229.236:1337/announce

http://178.175.143.27/announce

udp://89.234.156.205:80/announce

http://91.216.110.47/announce

http://114.55.113.60:6969/announce

http://195.123.209.37:1337/announce

udp://114.55.113.60:6969/announce

http://210.244.71.26:6969/announce

udp://107.150.14.110:6969/announce

udp://5.79.249.77:6969/announce

udp://195.123.209.37:1337/announce

udp://37.19.5.155:2710/announce

http://107.150.14.110:6969/announce

http://5.79.249.77:6969/announce

udp://185.5.97.139:8089/announce

udp://194.106.216.222:80/announce

udp://91.218.230.81:6969/announce

https://104.28.17.69/announce

http://104.28.16.69/announce

http://185.5.97.139:8089/announce

http://194.106.216.222/announce

http://80.246.243.18:6969/announce

http://37.19.5.139:6969/announce

udp://5.79.83.193:6969/announce

udp://46.4.109.148:6969/announce

udp://51.254.244.161:6969/announce

udp://188.165.253.109:1337/announce

http://91.217.91.21:3218/announce

http://37.19.5.155:6881/announce

http://46.4.109.148:6969/announce

http://51.254.244.161:6969/announce

http://104.28.1.30:8080/announce

http://81.200.2.231/announce

http://157.7.202.64:8080/announce

http://87.248.186.252:8080/announce

udp://128.199.70.66:5944/announce

udp://182.176.139.129:6969/announce

http://128.199.70.66:5944/announce

http://188.165.253.109:1337/announce

http://93.92.64.5/announce

http://173.254.204.71:1096/announce

udp://195.123.209.40:80/announce

udp://62.212.85.66:2710/announce

udp://208.67.16.113:8000/announce

http://125.227.35.196:6969/announce

http://59.36.96.77:6969/announce

http://87.253.152.137/announce

http://158.69.146.212:7777/announce

udp://tracker.coppersurfer.tk:6969/announce

udp://zer0day.ch:1337/announce

udp://tracker.leechers-paradise.org:6969/announce

udp://9.rarbg.com:2710/announce

udp://p4p.arenabg.com:1337/announce

udp://tracker.sktorrent.net:6969/announce

udp://tracker.aletorrenty.pl:2710/announce

udp://tracker.kicks-ass.net:80/announce

udp://tracker.piratepublic.com:1337/announce

udp://torrent.gresille.org:80/announce

udp://tracker.skyts.net:6969/announce

udp://tracker.yoshi210.com:6969/announce

udp://tracker.tiny-vps.com:6969/announce

udp://tracker.internetwarriors.net:1337/announce

udp://mgtracker.org:2710/announce

udp://tracker.filetracker.pl:8089/announce

udp://tracker.ex.ua:80/announce

udp://91.218.230.81:6969/announce

udp://tracker.grepler.com:6969/announce

udp://tracker.flashtorrents.org:6969/announce

udp://tracker.bittor.pw:1337/announce

udp://tracker.kuroy.me:5944/announce

udp://182.176.139.129:6969/announce

udp://open.stealth.si:80/announce

udp://208.67.16.113:8000/announce

udp://tracker.coppersurfer.tk:6969/announce

http://tracker.opentrackr.org:1337/announce

udp://zer0day.ch:1337/announce

http://explodie.org:6969/announce

udp://tracker.leechers-paradise.org:6969/announce

udp://9.rarbg.com:2710/announce

udp://p4p.arenabg.com:1337/announce

udp://tracker.sktorrent.net:6969/announce

http://p4p.arenabg.com:1337/announce

udp://tracker.aletorrenty.pl:2710/announce

http://tracker.aletorrenty.pl:2710/announce

http://tracker.bittorrent.am/announce

udp://tracker.kicks-ass.net:80/announce

http://tracker.kicks-ass.net/announce

http://tracker.baravik.org:6970/announce

udp://tracker.piratepublic.com:1337/announce

udp://213.163.67.56:1337/announce

http://213.163.67.56:1337/announce

udp://185.86.149.205:1337/announce

http://74.82.52.209:6969/announce

udp://94.23.183.33:6969/announce

udp://74.82.52.209:6969/announce

udp://151.80.120.114:2710/announce

udp://109.121.134.121:1337/announce

udp://168.235.67.63:6969/announce

http://109.121.134.121:1337/announce

udp://178.33.73.26:2710/announce

http://178.33.73.26:2710/announce

http://85.17.19.180/announce

udp://85.17.19.180:80/announce

http://210.244.71.25:6969/announce

http://85.17.19.180/announce

ibus黑屏修复

百度出来的fcitx安装方法,都要卸载ibus,如果没有注意同时卸载掉的依赖包的话,gnome桌面中的一些关键库也没被卸载。

修复方法很简单,重新安装Gnome

1
2
3
4
5
6
7

sudo yum -y groups install "GNOME Desktop"

sudo systemctl set-default graphical.target

sudo reboot

安装 fcitx

1
2
3
4
5
6
7

sudo yum install fcitx fcitx-table-chinese

sudo yum install fcitx-configtool

sudo yum install fcitx-googlepinyin fcitx-cloudpinyin

在/etc/profile或~/.bashrc最后增加以下内容

1
2
3
4
5
6
7

export GTK_IM_MODULE=fcitx

export QT_IM_MODULE=fcitx

export XMODIFIERS="@im=fcitx"

关闭gnome-shell 对键盘的监听,然后切换输入法为fcitx:

1
2
3
4
5
6
7

sudo pkill ibus-daemon

gsettings set org.gnome.settings-daemon.plugins.keyboard active false

imsettings-switch fcitx

重新启动系统,fcitx自己主动启动,但图标藏在桌面右下角的通知栏中

打开fcitx的配置工具,选择输入法标签点”+”能够搜索并加入输入法

安装搜狗拼音

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

sudo yum install dpkg

mkdir sogou

cd sogou

#下载搜狗拼音

wget http://cdn2.ime.sogou.com/dl/index/1524572264/sogoupinyin_2.2.0.0108_amd64.deb\?st\=_oXccusI8bHHg5uWqiue_g\&e\=1567251976\&fn\=sogoupinyin_2.2.0.0108_amd64.deb -O sogoupinyin_2.2.0.0108_amd64.deb

ar vx sogoupinyin_2.2.0.0108_amd64.deb

sudo tar -xvf data.tar.xz -C /

sudo cp /usr/lib/x86_64-linux-gnu/fcitx/fcitx-sogoupinyin.so /usr/lib64/fcitx/

sudo yum install -y im-chooser

imsettings-switch fcitx #不要使用root

sudo alternatives --config xinputrc #按照提示选择fcitx.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

<?php



namespace app\http\middleware;



class CrossDomain

{

public function handle($request, \Closure $next)

{

header('Access-Control-Allow-Origin: *');

header("Access-Control-Allow-Headers: Authorization, Sec-Fetch-Mode, DNT, X-Mx-ReqToken, Keep-Alive, User-Agent, If-Match, If-None-Match, If-Unmodified-Since, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Accept-Language, Origin, Accept-Encoding");

header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE');

header('Access-Control-Max-Age: 1728000');

if (strtoupper($request->method()) == "OPTIONS") {

return response();

}



return $next($request);

}

}

启用WSL

VirtualMachinePlatform是WSL2依赖功能,需要系统支持(build 18917+),硬件支持VM功能并开启,安装完成后要重启计算机。

1
2
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform

升级WSL到WSL2

1
2
3
wsl --set-version ubuntu 2 #设置为1则降级
wsl --set-default-version 2 #设置默认版本
wsl -l -v #显示已安装的列表

文件读写权限配置

修改/etc/wsl.conf添加如下内容

1
2
3
4
5
6
7
8
[automount]
enabled=true
root="/mnt/"
options="metadata,uid=1000,gid=1000,umask=22,fmask=111"
mountFsTab=true
[network]
generateHosts=true
generateResolvConf=true

修改源为阿里云镜像

1
2
3
4
5
6
sudo vim /etc/apt/sources.list
#替换成阿里云镜像
:%s/security.ubuntu/mirrors.aliyun/g
:%s/archive.ubuntu/mirrors.aliyun/g

sudo apt update && sudo apt upgrade -y

关闭git文件模式,解决wsl与windows上一边操作后,另一边git提示有文件修改问题。

1
2
git config core.filemode false
git config core.autocrlf true #如果windows上也配置了这个选项,则不建议关闭。

配置WSL2虚拟机内存与处理器数量

保存.wslconfig在用户目录下,Build 19041以上版本有效

1
2
3
[wsl2]
memory=4GB
processors=2

Linux加载WSL VDHX

1
2
3
4
5
sudo apt install libguestfs-tools #ubuntu
sudo yum install libguestfs-tools #centos

sudo virt-list-filesystems /path/to/vhdx
sudo guestmount -a /path/to/vhdx -m /dev/xxxx -r /path/to/mountpoint -o allow_other

VDHX扩容

  1. 使用wsl –shutdown关闭所有WSL实例
  2. 通过完成以下命令调整 WSL 2 VHDX 的大小:
    1
    2
    3
    4
    5
    diskpart
    list vdisk #如果这里未列出相应的虚拟磁盘,使用第5步查找
    Select vdisk file="<pathToVHD>"
    expand vdisk maximum="<sizeInMegaBytes>"
    #sizeInMegaBytes为更改后的大小,单位MB
  3. 启动 WSL 分发版
  4. 通过从 Linux 分发版命令行运行以下命令,让 WSL 知道它可以扩展其文件系统的大小:
    1
    2
    3
    sudo mount -t devtmpfs none /dev
    mount | grep ext4
    sudo resize2fs /dev/sdXX
  5. 找到 WSL 2 安装使用的 VHDX 文件
    a. 查找你的分发版安装包名称
    使用 PowerShell(其中,“distro”是分发版名称)输入以下命令:
    1
    Get-AppxPackage -Name "*<distro>*" | Select PackageFamilyName
    b. 找到 WSL 2 安装使用的 VHD 文件 fullpath,这将是你的 pathToVHD
    1
    %LOCALAPPDATA%\Packages\<PackageFamilyName>\LocalState\<disk>.vhdx