Skip to main content

· 2 min read
aweffr

Motivation

安卓测试机的插口已经有点接触不良了,稍微操作一下屏幕就会断开连接,但调试需要实时连接 RN的metro bundler端口8081, cable连接下调试老是断开,很烦。。

遂赶紧学习了一下Wifi 连接的新姿势,很简单

Prerequisite

  • adb
  • 手机能正常cable连接到电脑进入adb shell
  • 稳定的wifi, 建议开启DHCP静态IP分配, 在RN开发下会很方便

Method

  • 手机数据线连接电脑,确认adb能开启连接。
    • adb devices
  • 手机和电脑连接上同一个wifi网络, 然后查找确认设备ip
    • adb shell "ip addr show wlan0 | grep -e wlan0$ | cut -d\" \" -f 6 | cut -d/ -f 1"
  • 让设备监听端口,例:5555
    • adb tcpip 5555
  • 断开数据线,然后用 adb connect 连接
    • adb connect 192.168.31.102:5555

至此,即可摆脱连接线的困扰。

Reference

· 2 min read
aweffr

Motivation

今天新起了一个RN 0.68.1 的项目来调研Fabric能不能开起来战未来。顺便升级一下cocapods。发现常规的 HTTP_PROXY, HTTPS_PROXY 似乎 gem 和 pod 不遵守。 于是google了一下发现ruby系的要用小写的环境变量和参数。

Method

  1. 升级 cocoapods:
  • sudo gem install --http-proxy http://127.0.0.1:<your port> cocoapods
  1. pod install:
  • export http_proxy=http://127.0.0.1:<your port>
  • export https_proxy=http://127.0.0.1:<your port>
  • pod install

通过查看proxy日志发现这样就生效了。

...
2022/04/13 23:40:44 127.0.0.1:62226 accepted //cdn.jsdelivr.net:443 [out-0]
2022/04/13 23:40:44 127.0.0.1:62227 accepted //cdn.jsdelivr.net:443 [out-0]
2022/04/13 23:40:44 127.0.0.1:62228 accepted //cdn.jsdelivr.net:443 [out-0]
2022/04/13 23:40:49 127.0.0.1:62370 accepted //cdn.cocoapods.org:443 [out-0]
2022/04/13 23:40:53 127.0.0.1:62385 accepted //cdn.cocoapods.org:443 [out-0]
2022/04/13 23:40:53 127.0.0.1:62398 accepted //cdn.cocoapods.org:443 [out-0]
2022/04/13 23:40:53 127.0.0.1:62390 accepted //cdn.cocoapods.org:443 [out-0]
2022/04/13 23:40:53 127.0.0.1:62435 accepted //cdn.cocoapods.org:443 [out-0]
2022/04/13 23:40:53 127.0.0.1:62394 accepted //cdn.cocoapods.org:443 [out-0]
...

另: boost 安装问题

在安装中, pod install 一直在 boost(1.76.0) 上卡住。

通过 pod install --verbose 看到, 是卡在了用 curl下载 boost 的 release 包这一步上。 下载地址是固定的: https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.bz2 调试改地址发现地址会重定向到一个s3的带签名的下载地址上。然后本地折腾proxy环境变量无果。

遂决定走个捷径:

直接找到对应的 pod file, 我先浏览器下载一份, 搞一个http server可以curl下载的地址, 把地址给替换了。

通过搜索找到了pod file 位置: ./node_modules/react-native/third-party-podspecs/boost.podspec

文件内容:

...
spec.authors = 'Rene Rivera'
spec.source = { :http => 'https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.bz2',
:sha256 => 'f0397ba6e982c4450f27bf32a2a83292aba035b827a5623a14636ea583318c41' }
...

随手起个python http.server, 将文件的地址替换为 'http://127.0.0.1:5000/boost_1_76_0.tar.bz2' 后再pod install,顺利绕过了该问题。

Reference

  1. StackOverflow: gem install by proxy
  2. StackOverflow: pod install proxy issue

· One min read
aweffr

在配置 Jenkins checkout代码目录本来是很简单:

git branch: 'master',
credentialsId: '12345-1234-4696-af25-123455',
url: 'ssh://git@your-gitlab.com:company/repo.git'

但是在实际中, 遇到了一个小问题, 优雅的 git 命令似乎解决不了子模块的问题, 通过了一阵测试之后, 确定work的pipeline代码片段如下:

checkout([
$class: 'GitSCM',
branches: [[name: "${params.BRANCH}"]],
doGenerateSubmoduleConfigurations: false,
extensions: [[
$class: 'SubmoduleOption',
disableSubmodules: false,
parentCredentials: true,
recursiveSubmodules: true,
reference: '',
trackingSubmodules: false
]],
submoduleCfg: [],
userRemoteConfigs: [[
credentialsId: '12345-1234-4696-af25-123455',
url: 'ssh://git@your-gitlab.com:company/repo.git'
]]
])

参考文档

· 6 min read
aweffr

Motiviation

帮一位同学开始系统地学计算机, 考虑到CS61A/B/C路线对英文和找资料有比较高的要求, 遂为其转进国内优秀课程路线. 为了能够使用上配套的OJ, 先搞定一下C语言mac开发环境.

入门这块OJ很重要,毕竟, 想成为一名好程序员, 编程这门手艺活还是得6啊.

总体步骤

  1. 安装XCode
  2. VS Code 安装插件
    1. C/C++ Extension Pack
    2. Code Runner
  3. 新建项目
    1. mkdir learning-c-programming && cd learning-c-programming && mkdir {.vscode,build}
  4. 使用VS Code打开目录, 新建以下文件
    1. tasks.json # 用于编译c++文件
    2. launch.json # 用于使用vscode自带的debug工具(左侧的小虫图标)
    3. c_cpp_properties.json # 用于使用vscode自带的代码提示工具如 IntelliSense
    4. settings.json # 添加 Code Runner 相关配置

Workspace 配置文件

配置 tasks.json

快捷键 Command+Shift+B, vscode会执行tasks.json中的任务.

文件内容如下:

{
"version": "2.0.0",
"tasks": [
{
"label": "C/C++: clang++ 生成活动文件",
"type": "shell",
"command": "clang",
"args": [
"-Wall",
"-Wno-unused-variable",
"-std=c++17",
"-g",
"${file}",
"-o",
"${workspaceFolder}/build/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${workspaceFolder}"
},
"problemMatcher": [
"$gcc"
],
"group": "build"
}
]
}

配置 c_cpp_properties.json

c_cpp_properties.json 的作用是:代码提示、代码跳转等

{
"configurations": [
{
"name": "Mac",
"includePath": [
"${workspaceFolder}/**",
"/Library/Developer/CommandLineTools/usr/include",
// 注意, clang的include文件位置需要根据实际安装结果修改
"/Library/Developer/CommandLineTools/usr/lib/clang/12.0.5/include",
"/usr/local/include"
],
"defines": [],
"macFrameworkPath": [
"/System/Library/Frameworks",
"/Library/Frameworks"
],
"compilerPath": "/usr/bin/clang++",
"cStandard": "c11",
"cppStandard": "c++17",
"intelliSenseMode": "clang-x64"
}
],
"version": 4
}

配置 launch.json

launch.json是调用vscode debug功能的配置文件

{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "clang++ - 生成和调试活动文件",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/${fileBasenameNoExtension}",
"args": [
"args", "can", "be", "there"
],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/build",
"environment": [],
"externalConsole": false,
"MIMode": "lldb",
"preLaunchTask": "C/C++: clang++ 生成活动文件"
}
]
}

配置 settings.json

配置 Code Runner 来快捷执行代码。

  • Control+Option+N 编译并执行代码
  • Control+Option+M 终止执行
{
"files.associations": {
"__bit_reference": "c",
"__string": "c",
"cstring": "c",
"cstdio": "c"
},
"code-runner.executorMap": {
"c": "cd $dir && clang -Wall -Wno-unused-variable -Wno-implicit-function-declaration -std=c11 $fileName -o $workspaceRoot/build/$fileNameWithoutExt && cd $workspaceRoot/build && ./$fileNameWithoutExt",
"cpp": "cd $dir && clang++ -Wall -Wno-unused-variable -Wno-implicit-function-declaration -std=c++17 $fileName -o $workspaceRoot/build/$fileNameWithoutExt && cd $workspaceRoot/build && ./$fileNameWithoutExt"
}
}

使用说明

c程序示例 处理输入

/**
* @file bubble-sort.cpp
* @author aweffr (aweffr@foxmail.com)
* @brief 提交OJ模板, 演示: 1. 读数组数据 2. 按环境区分如何处理输入
* @version 0.1
* @date 2022-03-12
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>

#define MAX_INPUT_SIZE 50000

#define __DEV__ 0
#define __DEV_FILE__ "/Users/aweffr/Developer/learning-c-programming/problem-set1/input.txt"

void swap(int *arr, int i, int j);

/**
* @brief 根据 __DEV__ 决定是从编写的测试input文件还是OJ的stdin读取输入
*
* @return FILE*
*/
FILE *get_input()
{
FILE *fptr = stdin;
if (__DEV__)
{
printf("[DEBUG]Reading input from %s ...\n", __DEV_FILE__);
fptr = fopen(__DEV_FILE__, "r");
if (fptr == NULL)
{
printf("Open File Error!");
exit(1);
}
}
return fptr;
}

int main(int argc, char *argv[])
{
int N = 0;

FILE *fptr = get_input();

fscanf(fptr, "%d\n", &N);

int input_arr[MAX_INPUT_SIZE];
memset(input_arr, 0, MAX_INPUT_SIZE);

for (int i = 0; i < N; i++)
{
fscanf(fptr, "%d\n", &input_arr[i]);
}

for (int i = 0; i < N; i++)
{
for (int j = 0; j < N - 1; j++)
{
if (input_arr[j] > input_arr[j + 1])
{
swap(input_arr, j, j + 1);
}
}
}

printf("sorted result: ");
for (int i = 0; i < N; i++)
{
const char *fmt = (i == 0) ? " %d" : ", %d";
printf(fmt, input_arr[i]);
}
printf("\n");

return 0;
}

void swap(int *arr, int i, int j)
{
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}

Code Runner 执行效果:

[Running] cd "/Users/aweffr/Developer/learning-c-programming/problem-set1/" && clang++ -Wall -Wno-unused-variable -Wno-implicit-function-declaration -std=c++17 bubble-sort.cpp -o /Users/aweffr/Developer/learning-c-programming/build/bubble-sort && cd /Users/aweffr/Developer/learning-c-programming/build && ./bubble-sort
[DEBUG]Reading input from /Users/aweffr/Developer/learning-c-programming/problem-set1/input.txt ...
sorted result: 1, 2, 3, 4, 8, 11, 111, 123, 12312, 12313

[Done] exited with code=0 in 2.958 seconds

参考文档

  1. segmentfault: mac vscode c++ 环境配置及异常的语法提示
  2. VS Code 官方文档: Using Clang in Visual Studio Code
  3. VS Code变量参考手册
  4. Clang 命令行手册
  5. CMU 15-123 C & Unix S11
  6. CMU 15-123 C & Unix N09

· 3 min read
aweffr

先配好DNS,本文以本站 aweffr.com 为例。

  1. 安装

网络情况好的情况下

# 最新版
curl https://get.acme.sh | sh

网络不好时acme.sh-2.9.0.tar.gz

tar zxvf acme.sh-2.9.0.tar.gz && cd acme.sh-2.9.0 && ./acme.sh --install

安装好后acme的程序和后续配置,证书都在~/.acme.sh

安装nginx

sudo apt install nginx-full

创建用于nginx访问let's encrypt challenge的目录

mkdir -p /var/www/le_root/.well-known/acme-challenge
chown -R root:www-data /var/www/le_root

创建文件 /etc/nginx/includes/letsencrypt-webroot

# /etc/nginx/includes/letsencrypt-webroot

location /.well-known/acme-challenge/ {
alias /var/www/le_root/.well-known/acme-challenge/;
}

然后 vim /etc/nginx/sites-enabled/default

# /etc/nginx/sites-enabled/default

server {
listen 80;
server_name aweffr.com;

# ....

# Let's Encrypt webroot
include includes/letsencrypt-webroot;
}

重启 nginx 生效 systemctl reload nginx.service

然后签发证书

acme.sh --issue -d aweffr.com -d www.aweffr.com -d git.aweffr.com -d api.aweffr.com -d blog.aweffr.com --ecc -w /var/www/le_root --keylength ec-256

# ...
# [Fri 01 Jan 2021 12:51:46 AM CST] Cert success.
# ...
# [Fri 01 Jan 2021 12:51:46 AM CST] Your cert is in /root/.acme.sh/aweffr.com_ecc/aweffr.com.cer
# [Fri 01 Jan 2021 12:51:46 AM CST] Your cert key is in /root/.acme.sh/aweffr.com_ecc/aweffr.com.key
# [Fri 01 Jan 2021 12:51:46 AM CST] The intermediate CA cert is in /root/.acme.sh/aweffr.com_ecc/ca.cer
# [Fri 01 Jan 2021 12:51:46 AM CST] And the full chain certs is there: /root/.acme.sh/aweffr.com_ecc/fullchain.cer

实际签发就是 aweffr.com 一张证书,里面dns记录包含 aweffr.com, www.aweffr.com, git.aweffr.com, api.aweffr.com, blog.aweffr.com。

然后告诉acme.sh如何install这个cert,它就会定时拷贝文件到/etc/nginx目录, 并自动reload nginx。

mkdir -p /etc/nginx/certs/aweffr.com
acme.sh --install-cert --ecc -d aweffr.com --cert-file /etc/nginx/certs/aweffr.com/cert --key-file /etc/nginx/certs/aweffr.com/key --fullchain-file /etc/nginx/certs/aweffr.com/fullchain --reloadcmd "systemctl reload nginx.service"

生成 dbparam:

openssl dhparam -dsaparam -out /etc/nginx/certs/aweffr.com/dhparam.pem 2048

具体nginx的ssl配置可以参考 Mozilla SSL Configuration Generator

最后往nginx的site里添加ssl配置

server {
...
listen 443 ssl http2;

ssl_certificate certs/aweffr.com/fullchain;
ssl_certificate_key certs/aweffr.com/key;
ssl_trusted_certificate certs/aweffr.com/fullchain;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;

# HSTS (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=63072000" always;

# DHE密码器的Diffie-Hellman参数
ssl_dhparam certs/aweffr.com/dhparam.pem;

# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
resolver_timeout 3s;

...
}

执行

openssl s_client -connect aweffr.com:443 -status -tlsextdebug < /dev/null 2>&1 | grep -i "OCSP response"

显示

OCSP response:
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response

说明 OCSP 已开启。

参考链接

  1. https://www.rmedgar.com/blog/using-acme-sh-with-nginx
  2. 从无法开启 OCSP Stapling 说起