Hello World !!!

1970-01-01 Thursday     misc

Hi, the world, I’m coooooooooming.

Oooops, just examples, ignore me, darling.

hello world logo

配色

静思

HEX
#81C2D6
RGB
129.194.214
CMYK
10.9.0.16
HEX
#8192D6
RGB
129.146.214
CMYK
40.32.0.16
HEX
#D9B3E6
RGB
217.179.230
CMYK
6.22.0.10
HEX
#DCF7A1
RGB
220.247.161
CMYK
11.0.35.3
HEX
#83FCD8
RGB
131.152.216
CMYK
48.0.14.1

Heading 2,目录 2

Heading 3, 目录 3

Heading 4,目录 4

Heading 5,目录 5
Heading 6, 目录 6

MISC

Separator,分割线

下面的效果是相同的。






The Fonts, 字体设置

This is emphasized 斜体. This is also emphasized 还是斜体.

Strong font 粗体 Also strong font 还是粗体

Water is H2O. 42=16. 上标、下标测试。

Code Use the printf() function,代码模块。

Code Use the printf() function,与上面功能一样。

There is a literal backtick (`) here.,额,还是代码模块。

The New York Times (That’s a citation). 引用测试,和斜体相似。

This is Underline. 下划线。

Code Snippets,代码高亮显示

Syntax highlighting via Pygments. css java sh c gas asm cpp c++

1
2
3
4
5
6
7
8
9
10
#container {
  float: left;
  margin: 0 -240px 0 0;
  width: 100%;
}
#container {
  float: left;
  margin: 0 -240px 0 0;
  width: 100%;
}
int main ()
{
   return 0;
}

Non Pygments code example

<div id="awesome">
    <p>This is great isn't it?</p>
</div>

Block Quote, 段引用

下面时关于段引用的测试。

单段的引用。Just one paragraph.

My conclusion after the trip was “well, now I know that there’s at least one company in the world that can succeed with the waterfall model” and I decided to stop bashing the waterfall model as hard as I usually do. Now, however, with all the problems Toyota are having, I’m starting to reconsider.q q q q q q q q q q q q q q qkkkkk

多段的引用,one more paragraphs.

My conclusion after the trip was “well, now I know that there’s at least one company in the world that can succeed with the waterfall model” and I decided to stop bashing the waterfall model as hard as I usually do. Now, however, with all the problems Toyota are having, I’m starting to reconsider.

My conclusion after the trip was “well, now I know that there’s at least one company in the world that can succeed with the waterfall model” and I decided to stop bashing the waterfall model as hard as I usually do. Now, however, with all the problems Toyota are having, I’m starting to .q q q q q

单段,但较为复杂的引用。

My conclusion after the trip was “well, now I know that there’s at least one company in the world that can succeed with the waterfall model” and I decided to stop bashing the waterfall model as hard as I usually do. Now, however, with all the problems Toyota are having, I’m starting to reconsider.

嵌套引用。

My conclusion after the trip was “well, now I know that there’s at least one company in the world

that can succeed with the waterfall model” and I decided to stop bashing the waterfall model as hard as I usually do. Now, how ever, with all the problems Toyota are having, I’m starting to re consider.

Unordered Lists,无序列表

如下是三种不同的表达方式。

Unordered Lists 1

  • Item one
  • Item two
  • Item three

Unordered Lists 2

  • Item one
  • Item two
  • Item three

Unordered Lists 3

  • Item one
  • Item two
  • Item three

其它

如下的各个列表项中,各个项之间表示为段落,而之前的不是,也就是说添加了 <p></p> ,所以现在看起来各个段之间空隙有点大。

  • Item one

  • Item two

  • Item three

Ordered Lists,有序列表

有序表的表达方式,只与顺序相关,而与列表前的数字无关。

Ordered Lists 1

  1. Item one
    1. sub item one
    2. sub item two
    3. sub item three
  2. Item two

Ordered Lists 2

  1. Item one
  2. Item two
  3. Item three

Ordered Lists 3

  1. Item one
  2. Item two
  3. Item three

Lists Tips,列表补记

列表项目标记通常是放在最左边,但是其实也可以缩进,最多 3 个空格,项目标记后面则一定要接着至少一个空格或制表符。

  • Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
  • Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse id sem consectetuer libero luctus adipiscing.

如下显示相同。

  • Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
  • Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse id sem consectetuer libero luctus adipiscing.

如下是在同一列表中,显示两个段落。

  1. This is a list item with two paragraphs. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.

    Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. Donec sit amet nisl. Aliquam semper ipsum sit amet velit.

  2. Suspendisse id sem consectetuer libero luctus adipiscing.

    This is the second paragraph in the list item. You’re only required to indent the first line. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.

Tables, 表格

kramdown 默认支持表格,只需要设置好 table thead tbody th tr td 对应的属性即可。

head1 head1 head1 head2 head2 head2 head3 head3 head3 head4 head4 head4
row1text1 row1text3 row1text3 row1text4
row2text1 row2text3 row2text3 row2text4

MathJax, 数学表达式

如下是一个数学表达式。

段内插入LaTeX代码是这样的:$\exp(-\frac{x^2}{2})$,试试看看吧

Pictures,图片显示

If the picture doesnt exist

aaaaa

Reference,引用

如下是一个简单的链接 an example,当然也可以使用网站的相对路径 About Me

也可以将网站的引用与 URL 分别区分开,如下是其中的示例,而且不区分大小写,RTEMSLinuxGUNGUN

Address already in use

该错误信息是由于返回了 EADDRINUSE 错误码,通常是由 TCP 套接字的 TIME_WAIT 状态引起,该状态在套接字关闭后会保留约 2~4 分钟,只有在该状态 TIME_WAIT 退出之后,套接字被删除,该地址才能被重新绑定而不出问题。

在 C 中,可以通过如下方式设置端口允许重用。

int opt = 1; setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

/linux-monitor-cpu.html ps -ax -o uid,pid,ppid,tpgid,pgrp,session,lstart,cmd

Linux查看某个文件被谁占用 当用户卸载某个目录的时候,因其他用户在当前目录或者当前目录在运行一个程序,卸载时报busy的处理办法:

1:fuser -av /mnt 查看占用mnt的程序以及pid,根据pid去kill -9

2:fuser -km /mnt 查看占用mnt的程序并自动kill -m是指定被占用的目录,-k是kill

3:losf /mnt 查看正在使用的某个文件 4:递归查看某个目录的文件信息 lsof +D /mnt/fat

5:列出某个用户打开的文件信息

lsof -u student

6:列出某个程序打开的文件信息

lsof -c mysql http://blog.csdn.net/kozazyh/article/details/5495532

System V IPC 分三类:消息队列、信号量、共享内存区,都采用 key_t 作为其内部使用的标示,该类型在 <sys/types.h> 中定义,一般是 32 位整数。

通常可以使用 ftok() 函数,也就是 file to key,把一个已存在的路径名和一个整数标识符转换成一个 key_t 值,该函数声明如下:

#include <sys/ipc.h> key_t ftok (const char *pathname, int proj_id);

pathname 通常是跟本应用相关的路径;proj_id 指的是本应用所用到的 IPC 的一个序列号,通常约定好,这样可以获取相同的 key_t 值。

注意,需要保证该路径应用程序可以访问,并且在运行期间不能删除。

#include          #include     #include <sys/stat.h>    int main()  {          char filename[50];          struct stat buf;          int ret;          strcpy(filename, "/home/satellite/" );          ret = stat( filename, &buf );          if(ret) {                  printf( "stat error\n" );                  return -1;          }            printf( "the file info: ftok( filename, 0x27 ) = %x, st_ino = %x, st_dev= %x\n", ftok( filename, 0x27 ), buf.st_ino, buf.st_dev );

        return 0;  }

通过执行结果可看出,ftok获取的键值是由ftok()函数的第二个参数的后8个bit,st_dev的后两位,st_ino的后四位构成的

semget

创建一个新的信号量或获取一个已经存在的信号量的键值。

#include <sys/sem.h> int semget(key_t key, int nsems, int semflg);

key: 为整型值,可以自己设定,有两种场景    1. IPC_PRIVATE 通常为 0,创建一个仅能被本进程给我的信号量。    2. 非 0 的值,可以自己手动指定,或者通过 ftok() 函数获取一个唯一的键值。 nsems: 初始化信号量的个数。 semflg: 信号量创建方式或权限,包括了 IPC_CREAT(不存在则创建,存在则获取);IPC_EXCL(不存在则建立,否则报错)。

#include #include <sys/sem.h>

int main() {  int semid;  semid = semget(666, 1, IPC_CREAT | 0666); // 创建了一个权限为666的信号量  printf(“semid=%d\n”, semid);  return 0; }

可以用 ipcs –s 来查看是否创建成功。 用 ipcrm -s semid 号来删除指定的信号量。

################################

CMake

################################

针对特定对象,可以通过如下方式指定特定的编译选项、头文件路径、宏定义。

target_compile_definitions(audio_decoder_unittests  PRIVATE “AUDIO_DECODER_UNITTEST”  PRIVATE “WEBRTC_CODEC_PCM16”) target_include_directories(audio_decoder_unittests  PRIVATE “interface”  PRIVATE “test”  PRIVATE “../codecs/g711/include”) target_compile_options(RTPencode PRIVATE “/wd4267”)

配置文件

CheckSymbolExists.cmake   宏定义检查

################################

Curl

################################

详细可以查看 http://php.net/manual/zh/function.curl-setopt.php https://moz.com/devblog/high-performance-libcurl-tips/

CURLOPT_NOSIGNAL

CURLOPT_WRITEFUNCTION 用于设置数据读取之后的回调函数,通过该函数可以保存结果,其函数声明如下。     size_t function( char *ptr, size_t size, size_t nmemb, void *userdata); CURLOPT_WRITEDATA 定义了上述函数声明中userdata的值。

#include #include <curl/curl.h>

size_t save_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {     size_t written;     written = fwrite(ptr, size, nmemb, stream);     return written; }

int main(void) {     CURL *curl;     CURLcode res;     FILE *fp;

    fp = fopen(“index.html”, “wb”);

    curl = curl_easy_init();     if (curl) {         curl_easy_setopt(curl, CURLOPT_URL, “www.baidu.com”);         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, save_data);         curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);         curl_easy_perform(curl);         curl_easy_cleanup(curl);         fclose(fp);     }

    return 0; }

CURLOPT_USERNAME CURLOPT_PASSWORD 分别设置用户名密码,低版本可以通过CURLOPT_USERPWD选项设置,其值为”user:password” 。

CURLOPT_TIMEOUT_MS 设置超时时间。

CURLOPT_MAXREDIRS CURLOPT_FOLLOWLOCATION 允许重定向,以及设置重定向的跳转次数。

CURLOPT_SSL_VERIFYPEER 验证证书,证书信息可以通过 CURLOPT_CAINFO 设置,或在 CURLOPT_CAPATH 中设置证书目录。

CURLOPT_SSL_VERIFYHOST 设置为 1 是检查服务器SSL证书中是否存在一个公用名(common name)。译者注:公用名(Common Name)一般来讲就是填写你将要申请SSL证书的域名 (domain)或子域名(sub domain)。 设置成 2,会检查公用名是否存在,并且是否与提供的主机名匹配。 0 为不检查名称。 在生产环境中,这个值应该是 2(默认值)。

./configure  \     –disable-shared –enable-static                     不使用动态库,而是静态编译     –without-libidn2 –without-winidn                   忽略国际化库  –disable-ipv6 –disable-unix-sockets                关闭IPV6以及Unix Socket  –without-ssl –without-gnutls –without-nss         关闭安全配置项1  –without-libssh2 –disable-tls-srp –without-gssapi 关闭安全配置项2     –without-zlib                                       不支持压缩  –disable-ares –disable-threaded-resolver        –without-librtmp  –disable-rtsp                    关闭不需要的协议1  –disable-ldap –disable-ldaps                       关闭不需要的协议2  –disable-dict –disable-file –disable-gopher  –disable-ftp –disable-imap –disable-pop3  –disable-smtp –disable-telnet –disable-tftp  –disable-sspi                                       Windows选项  –without-libpsl –without-libmetalink     –with-nghttp2   resolver:         ${curl_res_msg} Built-in manual:  ${curl_manual_msg} –libcurl option: ${curl_libcurl_msg} Verbose errors:   ${curl_verbose_msg} ca cert bundle:   ${ca}${ca_warning} ca cert path:     ${capath}${capath_warning} ca fallback:      ${with_ca_fallback} HTTP2 support:    ${curl_h2_msg}                                                                                Protocols:        ${SUPPORT_PROTOCOLS}

curl_code = curl_easy_perform (session); long http_code = 0; curl_easy_getinfo(session, CURLINFO_RESPONSE_CODE, &http_code);  /* 获取返回码 */

http://187.0.0.1:8080/status

使用 curl 测量 Web 站点的响应时间。

curl -o /dev/null -s -w ‘%{http_code}-%{time_namelookup}:%{time_connect}:%{time_appconnect}:%{time_pretransfer}:%{time_redirect}:%{time_starttransfer}:%{time_total}\n’ ‘http://187.0.0.1:8080/status’

time_namelookup     DNS解析时间,从请求开始到DNS解析完毕所用时间 time_connect     建立到服务器的 TCP 连接所用的时间 time_appconnect     连接建立完成时间,如SSL/SSH等建立连接或者完成三次握手时间 time_pretransfer    准备传输的时间,对于一些协议需要做一些初始化操作 time_redirect       重定向时间,包括到最后一次传输前的几次重定向的DNS解析、连接、预传输、传输时间 time_starttransfer 传输时间,在发出请求之后,服务器返回数据的第一个字节所用的时间 time_total          完成请求所用的时间 speed_download      下载速度,单位是字节/秒 http_code           返回码

注意,如果某一步失败了,该步骤对应的值实际上显示的是 0 ,此时需要通过总时间减去上一步的消耗时间。

上述的执行,是在执行 curl_easy_perform() 函数的时候开始的,在 docs/examples 目录下,有很多的参考实例。

const char *optstr; char *endptr = NULL; double v; long value;

/* NOTE: if optstr = NULL, strtol() will raise ‘Segmentation fault’ / optstr = “  not a number”; / errno=0, optstr == endptr / errno = 0; value = strtol(optstr, &endptr, / base = */ 0); assert(value == 0); assert(errno == 0); assert(optstr == endptr); printf(“errno=%d, optstr=%p, endptr=%p, endchar=’%c’/0x%02x, value=%ld\n”, errno, optstr, endptr, *endptr, *endptr, value);

optstr = “  12part number”; errno = 0; value = strtol(optstr, &endptr, /* base = */ 0); printf(“errno=%d, optstr=%p, endptr=%p, endchar=’%c’/0x%02x, value=%ld\n”, errno, optstr, endptr, *endptr, *endptr, value);

optstr = “  12”; errno = 0; value = strtol(optstr, &endptr, /* base = */ 0); printf(“errno=%d, optstr=%p, endptr=%p, endchar=’%c’/0x%02x, value=%ld\n”, errno, optstr, endptr, *endptr, *endptr, value);

memory-barriers https://www.kernel.org/doc/Documentation/memory-barriers.txt http://ifeve.com/linux-memory-barriers/ https://dirtysalt.github.io/memory-barrier.html http://preshing.com/20120625/memory-ordering-at-compile-time/ http://events.linuxfoundation.org/sites/events/files/slides/dbueso-elc2016-membarriers-final.pdf http://larmbr.com/2014/02/14/the-memory-barriers-in-linux-kernel(1)/ https://www.zhihu.com/question/47990356 http://www.wowotech.net/kernel_synchronization/Why-Memory-Barriers.html http://blog.csdn.net/qb_2008/article/details/6840570

网卡缓存 https://zrj.me/archives/1102

http://www.cnblogs.com/bodhitree/p/6018369.html sed高级用法 https://www.zhukun.net/archives/6975 http://gohom.win/2015/06/20/shell-symbol/ mysql core dump http://xiezhenye.com/2015/05/%E8%8E%B7%E5%8F%96-mysql-%E5%B4%A9%E6%BA%83%E6%97%B6%E7%9A%84-core-file.html 文件句柄数 http://blog.sina.com.cn/s/blog_919f173b01014vol.html http://www.opstool.com/article/166 rpm 升级到旧的版本 http://ftp.rpm.org/max-rpm/s1-rpm-upgrade-nearly-identical.html#S2-RPM-UPGRADE-OLDPACKAGE-OPTION https://stackoverflow.com/questions/2452226/master-branch-and-origin-master-have-diverged-how-to-undiverge-branches C hash算法 http://troydhanson.github.io/uthash/index.html

https://blog.zengrong.net/post/1746.html https://stackoverflow.com/questions/9537392/git-fetch-remote-branch

http://www.cnblogs.com/yuuyuu/p/5103744.html https://codeascraft.com/2011/02/15/measure-anything-measure-everything/

http://wkevin.github.io/2014/05/05/git-submodule/ http://xstarcd.github.io/wiki/sysadmin/ntpd.html ps -ax -o lstart,cmd

可以通过如下命令指定分支,提交后会修改原数据中的 Subproject commit 。 cd submodule_directory git checkout v1.0 cd .. git add submodule_directory git commit -m “moved submodule to v1.0” git push

http://docs.python-requests.org/zh_CN/latest/user/quickstart.html https://liam0205.me/2016/02/27/The-requests-library-in-Python/

https://github.com/MarkDickinson/scheduler https://github.com/Meituan-Dianping/DBProxy https://github.com/greensky00/avltree http://www.freebuf.com/sectool/151426.html http://www.freebuf.com/sectool/150367.html

tar 打包可以通过 –exclude=dir 排除。 通过 --transform 参数可以根据 sed 语法进行一些转换,例如增加前缀 's,^,prefix/,' 或者 s%^%prefix/%

支持数据类型float, int, str, text, log

支持函数:     abschange 计算最新值和上次采集值相减的绝对值,对于字符串0/相同、1/不同,1->5=4, 3->1=2

https://www.zabbix.com/documentation/3.0/manual/appendix/triggers/functions

支持数据类型:    Numeric (unsigned) - 64位无符号整数;    Numeric (float) - 浮点数,可以存储负值,范围是 [-999999999999.9999, 999999999999.9999],同时可以支持科学计算 1e+7、1e-4;    Character - 短文本数据,最大255字节;       Log - 具有可选日志相关属性的长文本数据(timestamp, source, severity, logeventid) Text - 长文本数据

Tim O’Reilly and Crew [5, p.726] The load average tries to measure the number of active processes at any time. As a measure of CPU utilization, the load average is simplistic, poorly defined, but far from useless.

Adrian Cockcroft [6, p. 229] The load average is the sum of the run queue length and the number of jobs currently running on the CPUs.

默认没有移动平均值计算,只是针对单个值进行计算。

threshold_tree 仍然通过format_name格式化名称。   目前分为了三种类型,分别为 Host > Plugin > Type ,需要按照层级进行排列,例如 Host 下面可以有 Plugin 和 Type 段;Plugin 下可以有 Type 但是不能有 Host 。

其它的配置项用于一些类似阈值的判断等,只能在 Type 下面配置。

FailureMax Value WarningMax Value  设置报警的上限值,如果没有配置则是正无穷。告警发送规则如下:     A) (FailureMax, +infty) 发送 FAILURE 通知;     B) (WarningMax, FailureMax] 发送 WARNING 通知;

FailureMin Value WarningMin Value  设置报警的下限值,如果没有配置则是负无穷。告警发送规则如下:     A) (-infty, FailureMin) 发送 FAILURE 通知;     B) [FailureMin, WarningMin) 发送 WARNING 通知;

Persist true|false(default)  多久发送一次报警,设置规则如下:     true) 每次超过阈值之后都会发送一次报警通知;     false) 只有在状态发生转换且前一次状态是OKAY时才会发送一次通知。

PersistOK true|false(default)  定义如何发送OKAY通知,设置规则如下:     true) 每次在正常范围内都会发送通知;     false) 当本次状态正常而且之前状态不正常时才发送一次OK通知。

Hysteresis Value  迟滞作用,用于处理在一个状态内重复变换,在该阈值范围内不会告警。

Hits Value     告警条件必须连续满足多少次之后才会发送告警。

Interesting true(default)|false  发现数据未更新时是否发送告警,会根据插件的采集时间间隔以及 Timeout 参数判断是否有事件发生。     true) 发送FAILURE报警;     false) 忽略该事件。

DataSource  <-> Types.db 中字段,例如midterm Host <-> host Plugin <-> plugin Type <-> type Instance <-> type_instance

  1. 根据value list中的参数获取到具体的配置。 2.
Invert true false
Percentage true false

以 loadavg 为例,其实现在 fs/proc/loadavg.c 中。 calc_global_load() 监控指标,其中监控插件包括了

https://en.wikipedia.org/wiki/Moving_average http://www.perfdynamics.com/CMG/CMGslides4up.pdf https://zh.wikipedia.org/wiki/%E7%A7%BB%E5%8B%95%E5%B9%B3%E5%9D%87

移动平均 (Moving Average) 可以处理短期波动,反映长期趋势或周期,从数学上看做是卷积。

简单移动平均

Simple Moving Average, SMA 将变量的前 N 值做平均。

SMA = (V1 + V2 + … + Vn) / n

当有新值之后,无需重复计算,只需要将最老的旧值删除,然后加入新值。

SMAn = SMAn-1 - V1/n + V/n

这样需要保存 N 个值。

加权移动平均

Weighted Moving Average, WMA 也就是在计算平均值时将部分数据乘以不同数值,

指数移动平均

Exponential Moving Average, EMA

—– 锁定用户该用户不能再次登录 ALTER USER username ACCOUNT LOCK; —– 解锁用户 ALTER USER username ACCOUNT UNLOCK;

aussdb plugin: Connect to database failed: FATAL:  The account has been locked. FATAL:  The account has been locked.

Zabbix上报数据格式 http://www.ttlsa.com/zabbix/zabbix-active-and-passive-checks/ Open-falcon 上报数据 http://blog.niean.name/2015/08/06/falcon-intro main_timer_loop() 周期计算定义的触发值,如果有事件发生,那么就直接写入到数据库中。

timer_thread()     main_timer_loop时间相关的处理 |-process_time_functions() | |-DCconfig_get_time_based_triggers() 从缓存中获取trigger表达式 | |-evaluate_expressions()       触发器表达式的主要处理函数,同时会产生事件 | | |-substitute_simple_macros() 宏分为两类,分别是{…} {$…} | | |-substitute_functions() | | | |-zbx_evaluate_item_functions() | | |   |-evaluate_function() | | |-evaluate() | | | |-DBbegin() | |-process_triggers() T:triggers | | |-process_trigger() | |   |-add_event()              会保存到内存的events数组中 | |-process_events()             处理事件,主要是将新事件插入数据库 | | |-save_events() T:events | | |-process_actions() T:actions | | |-clean_events() | |-DBcommit() | |-process_maintenance()

源码解析 https://jackywu.github.io/articles/zabbix_server%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/

表结构

{:.()}

hosts  包含了主机以及模板信息。     select hostid, host from hosts where status = 0;     hostid  主机ID  host    主机、模板名  status  0->主机 3->模板 goups   主机的逻辑分组 hosts_grous 分组和主机之间的关联关系 items 监控项,保存了每个主机的监控项,该监控项来自的模板ID     select itemid, name, key_, templateid, delay, status, units from items where hostid = 10107; triggers 触发器,其中表达式中使用的是function id  select triggerid, expression, status, value, description from triggers;  select * from functions where functionid = 13302; functions

Paxos协议解析 https://zhuanlan.zhihu.com/p/21438357?refer=lynncui

https://github.com/hanc00l/wooyun_public https://github.com/niezhiyang/open_source_team http://www.jianshu.com/p/43c604177c08 http://kenwheeler.github.io/slick/

http://lovestblog.cn/blog/2016/07/20/jstat/ http://blog.phpdr.net/java-visualvm%E8%AE%BE%E7%BD%AEjstat%E5%92%8Cjmx.html

http://metrics20.org/spec/ Stack Overflow 的架构 https://zhuanlan.zhihu.com/p/22353191 GCC部分文件取消告警 http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html http://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Warning-Options.html

SHELL反弹 https://segmentfault.com/a/1190000010975294 各种环境下反弹shell的方法 http://www.zerokeeper.com/experience/a-variety-of-environmental-rebound-shell-method.html

libev信号处理 http://blog.csdn.net/gqtcgq/article/details/49688027 信号相关参考 http://www.cnblogs.com/mickole/p/3191281.html

Joinable VS. Detached

默认创建的线程是 Joinable 的,也就是可以通过 pthread_join() 函数在任何其它线程中等待它的终止。

各个线程是独立运行的,也就意味着在调用 join 之前,目标线程可能已经终止了,那么如果一个线程是 Joinable ,POSIX 标准要求必须保持、维护一些信息,至少是线程 ID 以及返回值。

实际上,对于大多数系统,如 Linux、Sloaris 等,在实现时通过 Thread Control Block, TCB 保存一些相关的信息,包括线程 ID、属性、入口函数、参数、返回值;调度策略、优先级;信号掩码、信号栈等等;而且通常是一次性分配堆栈和 TCB,例如单次 mmap() 调用,并把 TCB 放在栈的开始位置处。

也就是说,不能立即释放对应的资源,这样就会造成浪费。

Detached

当设置为 Detached 时,表明对于开启的线程,如果一旦执行结束,则会立即清理资源。

可以在创建线程时设置该属性,或者调用 pthread_detach() 函数;当设置了该属性后,如果再次调用 pthread_join() 则会返回 EINVAL 错误。 #include #include #include #include #include #include

void *thread(void *dummy) { (void) dummy; sleep(1); return NULL; }

void detach_state(pthread_t tid, const char *tname) { int rc;

    rc = pthread_join(tid, NULL);
    if (rc == EINVAL)
            printf("%s is detached\n", tname);
    else if (rc == 0)
            printf("%s was joinable\n", tname);
    else
            printf("ERROR: %s rc=%d, %s\n", tname, rc, strerror(rc)); }

int main(void) { /* TODO: Check the return value */

    /* normal thread creation */
    pthread_t tid1;
    pthread_create(&tid1, NULL, thread, NULL);
    detach_state(tid1, "thread1"); /* joinable */

    /* detach thread from main thread */
    pthread_t tid2;
    pthread_create(&tid2, NULL, thread, NULL);
    pthread_detach(tid2);
    detach_state(tid2, "thread2"); /* detached */

    /* create detached thread */
    pthread_attr_t attr;
    pthread_t tid3;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    pthread_create(&tid3, &attr, thread, NULL);
    detach_state(tid3, "thread3");

    return EXIT_SUCCESS; }

对于该特性,需要注意如下的规则:

  1. 不要重复 join 一个线程,已经 join 线程的栈空间已经被回收,再次调用无法获取对应的信息;
  2. 不要 join 一个是 detach 的线程,分离的线程栈空间是由系统内部来做回收的;

sigprocmask() 函数能够根据

根据参数 how 实现对信号集的操作,主要包括如下三种:

  • SIG_BLOCK 在进程当前阻塞信号集中添加set指向信号集中的信号,相当于 mask=mask set;
  • SIG_UNBLOCK 如果进程阻塞信号集中包含set指向信号集中的信号,则解除对该信号的阻塞,相当于 mask=mask ~set;
  • SIG_SETMASK 更新进程阻塞信号集为set指向的信号集,相当于mask=set。

EPOLLIN 对应的文件描述符可读,包括对端 Socket 正常关闭(返回字节为 0); EPOLLOUT 对应的文件描述符可写; EPOLLPRI 所谓的带外数据,也就是在通过 send() 发送时指定 MSG_OOB 参数; EPOLLERR 发生本地错误; EPOLLHUP 表示客户端套接字已经断开连接; EPOLLET 使用边沿触发,默认是水平触发; EPOLLONESHOT 只监听一次事件,事件触发后会自动关闭,如果需要再次监听则需要重新设置。

1、listen fd,有新连接请求,触发EPOLLIN。 2、对端发送普通数据,触发EPOLLIN。 3、带外数据,只触发EPOLLPRI。

  1. 当对端正常关闭时,会触发 EPOLLIN 和 EPOLLRDHUP 事件,而非 EPOLLERR 和 EPOLLHUP,此时读缓冲区大小为 0 。

注意,如果是对端发生错误,不会主动触发 EPOLLERR 错误,只有在下次调用读写时才会触发。

文件描述符异常

一般来说,不需要手动从 epoll() 中删除,系统会自动删除掉,不过按照 man epoll(7) 的 Q6 介绍,需要保证文件描述符没有被 dup() 复制过。

同时注册两次

如果将相同的 fd 添加到 epoll_set 两次,接口会返回 EEXIST 报错,不过可以通过 dup 接口复制一份并添加,例如多线程中的使用。

关于 file descriptors and file descriptions

https://idea.popcount.org/2017-03-20-epoll-is-fundamentally-broken-22/ https://blog.codingnow.com/2017/05/epoll_close_without_del.html

边缘触发 VS. 水平触发

简单来说,两者区别如下:

  1. Level Triggered 水平触发:有事件触发时会通过 epoll_wait() 去处理,如果一次处理不完会持续通知,直到处理完成,当系统中有大量不需要的描述符时会大大降低处理效率。
  2. Edge Triggered 边缘触发:如果本次没有处理完成,那么即使下次调用 epoll_wait() 也不会再次通知,知道出现下次的读写事件时才会再次触发。

其中 select() poll() 的模型都是水平触发模式,信号驱动 IO 是边缘触发模式,epoll() 模型即支持水平触发,也支持边缘触发,默认是水平触发。

#include #include #include

#include #include <sys/stat.h> #include <sys/types.h>

int main(void) { glob_t globbuf; struct stat statbuf; int rc; size_t pathc; char **pathv;

    rc = glob("/var/run/haproxy[0-9]*.sock", GLOB_ERR | GLOB_NOSORT, NULL, &globbuf);
    if (rc != 0)
            return -1;

    pathv = globbuf.gl_pathv;
    pathc = globbuf.gl_pathc;
    printf("Got #%d matches\n", pathc);

    for (; pathc-- > 0; pathv++) {
            rc = lstat(*pathv, &statbuf);
            if (rc < 0 || !S_ISSOCK(statbuf.st_mode))
                    continue;
            printf("Match path: %s\n", *pathv);
    }

    globfree(&globbuf);
    return 0; }

mobius

aspire

介绍TCP流 http://kaiyuan.me/2015/09/04/TCP%E7%9A%84%E6%94%B6%E5%8F%91%E5%8C%85%E6%9C%BA%E5%88%B6%E8%A7%A3%E6%9E%90/

返回值:如果执行成功则返回子进程识别码(PID), 如果有错误发生则返回-1. 失败原因存于errno 中.

https://github.com/krallin/tini https://github.com/Yelp/dumb-init

tini

其功能类似于 init 进程,一般用于容器中,

在编译静态二进制文件时会依赖 glibc 的静态库,对于 CentOS 来说,需要通过 yum install glibc-static 安装。

可以通过该工程查看 CMake 的编写,以及编写类似 init 进程的注意事项。

在 /post/linux-kernel-process 中有关于孤儿进程和僵尸进程的介绍,简单来说:

  • 孤儿进程。当父进程被 kill 掉,其子进程就会成为孤儿进程 (Orphaned Process),并被 init(PID=1) 所接管。

孤儿进程如何被接管

在 Linux 内核中,有如下的代码 Kernel find_new_reaper() ,其开头的注释摘抄如下:

/*

  • When we die, we re-parent all our children, and try to:
    1. give them to another thread in our thread group, if such a member exists
    1. give it to the first ancestor process which prctl’d itself as a
  • child_subreaper for its children (like a service manager)
    1. give it to the init process (PID 1) in our pid namespace */

也就是说,接管分三步:A) 找到相同线程组里其他可用的线程;B) 如果没有找到则进行第二步C) 最后交由 PID=1 的进程管理。

SubReaper

当一个进程被标记为 child_subreaper 后,这个进程所创建的所有子进程,包括子进程的子进程,都将被标记拥有一个 subreaper。

那么当某个进程成为了孤儿进程时,会沿着它的进程树向祖先进程找一个最近的是 child_subreaper 且运行着的进程,这个进程将会接管这个孤儿进程。

http://adoyle.me/blog/orphaned-process-and-zombie-process-and-docker.html

https://stackoverflow.com/questions/9305992/if-threads-share-the-same-pid-how-can-they-be-identified/9306150#9306150

RBASH

restricted bash, rhash 也就是受限制的 bash,实际上这只是指向 bash 的软连接,也可以通过 bash -r 参数启动,作用相同。

此时,启动的这个 BASH 会在某些功能上受限制,包括:

  • 通过 cd 来改变工作目录
  • 设置或取消环境变量 SHELL、PATH、ENV、BASH_ENV
  • 命令名中不能包含目录分隔符 ‘/’

包含有 ‘/’ 的文件名作为内置命令 ‘.’ 的参数 hash 内置命令有 -p 选项时的文件名参数包含 ‘/’ 在启动时通过 shell 环境导入函数定义 在启动时通过 shell 环境解析 SHELLOPTS 的值 使用 >,>|, <>, >&, &>, » 等重定向操作符 使用 exec 内置命令 通过 enable 内置命令的 -f 和 -d 选项增加或删除内置命令 使用 enable 内置命令来禁用或启用 shell 内置命令 执行 command 内置命令时加上 -p 选项 通过 set +r 或 set +o restricted 关闭受限模式

逃逸

rbash 提供的受限环境的安全程度取决于用户能执行的命令,很多命令都能调用外部命令,从而导致逃逸出受限环境。

例如用 vim 打开一个文件,然后通过 !bash 执行外部命令,那么就可以启动一个不受限的 bash,这对 more,less,man 等命令同样有效。如果还能执行脚本,如 python、perl 等,则有更过的方式来启动一个不受限的 shell 。

也可以通过如下方式执行:

$ BASH_CMDS[a]=/bin/sh;a $ /bin/bash $ export PATH=$PATH:/bin:/usr/bin

要让 rbash 更安全,可以限制用户能够执行的命令,如我们让用户执行执行 ssh 命令。一种方法是,修改 PATH 环境变量。

例如我们创建一个 ruser 用户,让他只能执行 ssh 命令:

$ ls -s /bin/bash /bin/rbash

$ useradd -s /bin/rbash ruser

$ chown -R root:ruser /home/ruser/.bashrc /home/ruser/.bash_profile

$ chmod 640 /home/ruser/.bashrc /home/ruser/.bash_profile

$ mkdir /home/ruser/bin 然后修改 PATH 环境变量的值为 /home/ruser/bin,并将允许执行的命令放到这个目录下。:

$ echo “export PATH=/home/ruser/bin” » /home/ruser/.bash_profile 把用户可执行的命令链接到用户 PATH 路径下:

$ ln -s /user/bin/ssh /home/ruser/bin/ssh 这样就可以只让登录的用户执行 ssh 命令。

限制用户执行命令

git比较两个分支 https://blog.csdn.net/u011240877/article/details/52586664

一个简单的时序数据库 https://github.com/Cistern/catena

https://www.byvoid.com/zhs/blog/string-hash-compare http://www.open-open.com/lib/view/open1451882746667.html https://hitzhangjie.github.io/jekyll/update/2018/05/19/golang-select-case%E5%AE%9E%E7%8E%B0%E6%9C%BA%E5%88%B6.html

HTTP平滑升级 https://segmentfault.com/a/1190000004445975

WithCancel

func WithCancel(parent Context) (ctx Context, cancel CancelFunc)

当调用 Cencel() 函数时,相关的子协程可以通过 ctx.Done() 手动相关的请求。

###

https://deepzz.com/post/golang-context-package-notes.html https://juejin.im/post/5a6873fef265da3e317e55b6

常见问题

成员变量

cannot refer to unexported field or method ver

在 GoLang 中要提供给外面访问的方法或是结构体必须是首字母大写,否则会报错。

exec.Command() 新建一个对象,但是没有执行

Output() 会等待任务执行完成并收集输出。

GoReman 进程管理

https://github.com/polaris1119/The-Golang-Standard-Library-by-Example/blob/master/chapter10/10.1.md https://www.jianshu.com/p/49e83c39cffc

/post/linux-commands-text.html

AWK统计操作

grep ‘Got result’ /tmp/foobar.log | awk ‘{s[$2]++} END{ for(i in s){print i, s[i]} }’ | sort http://blog.51cto.com/6226001001/1659824 https://shaohualee.com/article/691

使用较多的是网络编程中,假设存在 A 调用 B 的 API,然后 B 再调用 C 的 API,如果要取消 A->B 的调用,按照正常的逻辑也应该要取消 B->C 的调用,那么此时就可以通过传递 Context 以及正常的逻辑判断来实现。

Linux内核的DEBUG方法 https://medium.com/square-corner-blog/a-short-guide-to-kernel-debugging-e6fdbe7bfcdf

#include #include #include #include #include <sys/socket.h>

#define log_it(fmt, args…) do { printf(fmt, ## args); putchar(‘\n’); } while(0)

int main() { pid_t pid; int fd2, rc, i; char buffer[1024];

    rc = socketpair(AF_LOCAL, SOCK_STREAM, 0, fd);
    if (rc < 0) {
            log_it("create sockpaire failed, %s", strerror(errno));
            return -1;
    }

    pid = fork();
    if (pid < 0) {
            log_it("fork failed, %s", strerror(errno));
            return -1;
    } else if (pid == 0) {
            close(fd[0]);
            strcpy(buffer, "hello socketpair");
            for (i = 0; i < 10; i++) {
                    write(fd[1], buffer, strlen(buffer));
                    usleep(200000);
            }
            strcpy(buffer, "exit");
            write(fd[1], buffer, strlen(buffer));
            close(fd[1]);
    } else {
            close(fd[1]);
            while (1) {
                    rc = read(fd[0], buffer, sizeof(buffer) - 1);
                    if (rc > 0) {
                            buffer[rc] = 0;
                            if (strcmp(buffer, "exit") == 0)
                                    break;
                            log_it("father: %s", buffer);
                    }
            }
            close(fd[0]);
    }

    return 0; }

查找 socketpair 的对端。

其中 /proc/<PID>/fd/<FD> 中显示的数字是虚拟套接字文件系统中套接字的 inode 编号,创建管道或套接字对时,每个端口都会连续接收一个 inode 编号

如下命令实际上很难查找到,并没有将内核的信息暴露出来。

lsof -c progname lsof -c parent -c child1 ls -l /proc/$(pidof server)/fd cat /proc/net/unix

$ ss -xp grep foobar

HTTP服务 http://fuxiaohei.me/2016/9/20/go-and-http-server.html

musl libc一个安全用户嵌入式设备的库 http://www.musl-libc.org/ http://www.etalabs.net/compare_libcs.html

Rootkit 是一套由入侵者留在系统中的后门程序,通常只有在系统被入侵后被安装进系统,用于长期控制,主要特征为:隐藏、操纵、收集数据。

Linux RooKit 可以简单地分为用户态和内核级,一些新的技术可能支持 BIOS、PIC、EFI 。

其中用户态通常是替换一些二进制文件,如 ps、netstat、ls 等,从而实现进程隐藏、网络连接信息隐藏、文件隐藏等功能。内核态由于隐蔽性好、攻击能力强,逐渐成为了主流,分为了 LKM 和 非LKM 类型。

一般其包含的功能有:远程指令执行、信息收集、文件隐藏、进程隐藏、网络连接隐藏、内核模块隐藏 。

https://github.com/mempodippy/vlany https://github.com/maK-/maK_it-Linux-Rootkit

http://www.freebuf.com/articles/network/185324.html https://github.com/iagox86/dnscat2 Netfilter RootKit https://github.com/zionlion67/rootkit

Wildpwn:Unix通配符攻击工具 http://www.freebuf.com/sectool/185276.html

anti-rootkit https://github.com/dgoulet/kjackal http://www.ywnds.com/?p=6905 http://rkhunter.sourceforge.net/ http://www.cis.syr.edu/~wedu/Teaching/cis643/LectureNotes_New/Set_UID.pdf

https://www.ibm.com/developerworks/cn/linux/l-overflow/index.html

SQLite http://huili.github.io/ http://www.iteye.com/blogs/subjects/deepfuture http://www.cnblogs.com/hustcat/archive/2009/02/26/1398896.html unix_dgram unix_stream unix_seqpacket

http://www.sqlite.org/howtocorrupt.html

Atomic Operation

所谓的原子操作就是 “不可中断的一个或一系列操作”,这里说的是硬件的原子操作能力。

在单处理器系统(UniProcessor)来说,能够在单条指令中完成的操作都可以认为是 “原子操作”,因为中断只能发生于指令之间。

而对称多处理器(Symmetric Multi-Processor)来说则会有很大区别,由于多个处理器同时在独立运行,即使能在单条指令中完成的操作也有可能受到干扰。

但是多核之间通常由于在共享内存空间会导致异常,为此在 x86 平台上,CPU 提供了在指令执行期间对总线加锁的手段。

简单来说,增加了 HLOCK 用来对总线进行加锁,从而在使用某个或者某段指令之间其它 CPU 无法访问内存,这样对于单个 CPU 来说,内存中的资源对于这个 CPU 就是独有的。

一般来说,CPU 使用较多的是针对单个数据类型的原子操作,最常见的是整形。

https://blog.csdn.net/qq100440110/article/details/51194563 https://my.oschina.net/jcseg/blog/316726 https://software.intel.com/zh-cn/blogs/2010/01/14/cpucpu

  1. 读取PIDFile,获取进程PID 1.1 检查进程是否存在 /proc/ 目录 不存在(通过kill -9强制杀死导致PIDFile未被清除)。 1.1.1 再次通过pidof检查所有进程,以防止PIDFile更新异常,或者被人为误更新PIDFile。 不存在,程序确实未启动,直接退出。 存在。发送kill信号,等待一个安全时间进程自动退出。 1.2 再次检查上次获取的PID及其子进程。 1.2.1 先向子进程组发送kill -9信号。 1.2.2 再向父进程组发送kill -9信号。 1.3 最后检查确保进程正常退出,如果未被清理输出告警信息。

/post/python-modules.html 搜索路径 一般来说,顺序为当前路径(' '),环境变量 PYTHONPATH 指定路径,通过 site 模块生成的路径。

/post/python-tips.html 带 * 参数

注意,在进行参数传递时,也可以通过 ** 进行字典的传参,示例如下。

#!/bin/python

def foobar(name, phone, addr): print name, phone, addr #foobar(“foobar”, “137-0123”, “US”) arg = dict(phone=”137-0123”, addr=”US”) foobar(“foobar”, **arg)

https://docs.python.org/2/library/sys.html#sys.path

https://matplotlib.org/faq/usage_faq.html

load 用来表示系统的负载,通过 top uptime w 命令或者 cat /proc/loadavg 查看当前系统前 1min 5min 15min 的负载平均值。

实际上在计算时采用的是指数平滑法,只是 Linux 内核中不允许直接做浮点运算,而且有多个 CPU 核,考虑到效率问题,从而导致计算的代码比较复杂。

简单来说,算法比较简单,但是

We take a distributed and async approach to calculating the global load-avg in order to minimize overhead.

The global load average is an exponentially decaying average of nr_running + nr_uninterruptible.

Once every LOAD_FREQ:

nr_active = 0; for_each_possible_cpu(cpu) nr_active += cpu_of(cpu)->nr_running + cpu_of(cpu)->nr_uninterruptible;

avenrun[n] = avenrun[0] * exp_n + nr_active * (1 - exp_n)

也就是说,核心的是:A) 多 CPU 中如何获取到整个系统的 nr_active;B) 定点计算指数平滑法。

CPU 核数

其实对于一台机器来说有几种类型:A) Multi Processor 也就是多个物理 CPU;B) Multi-Core Processor 一个物理 CPU 中有多个核。

另外,为了提高并行计算的性能,Intel 还引入了 Hyper-Threading 特性,此时,一个物理 CPU 对于操作系统来说表现为两个。

我们以 /proc/loadavg 为准,实际上实现在 fs/proc/loadavg.c

http://ilinuxkernel.com/?p=869 http://brytonlee.github.io/blog/2014/05/07/linux-kernel-load-average-calc/ https://www.teamquest.com/files/9214/2049/9761/ldavg1.pdf

内核计算负载的公式如下:

其中 $R$ 为 1 5 15 分别对应了 1min 5min 15min 的负载计算方法;$queue$ 对应了当前的运行队列长度。

通过 unsigned long avenrun[3]; 存放负载情况,因为无法进行浮点运算,所以低 11 位用来保存负载的小数部分,其余的高位用来保存整数部分。

内核在进程调度时会调用 calc_global_load() 函数来计算负载,一般是每 5s 更新一次。

unsigned long avenrun[3]; // 用于存放

#define FSHIFT 11 /* nr of bits of precision / #define FIXED_1 (1«FSHIFT) / 1.0 as fixed-point / #define LOAD_FREQ (5HZ+1) /* 5 sec intervals / #define EXP_1 1884 / 1/exp(5sec/1min) as fixed-point / #define EXP_5 2014 / 1/exp(5sec/5min) / #define EXP_15 2037 / 1/exp(5sec/15min) */

#define CALC_LOAD(load,exp,n) \ load = exp; \ load += n(FIXED_1-exp); \ load »= FSHIFT;

the CXX compiler identification is unknown

也就是 CMake 找不到 C++ 对应的编译器,在 CentOS 可以通过 yum install gcc-c++ 来安装。

/post/git-tips.html

—– 对一些修改增加着色 git config –global color.ui true

#include #include #include #include #include #include <sys/prctl.h>

#define THREAD_NAME_MAX 16

//#define HAVE_SETNAME_NP 1

static void *threadfunc(void attribute((unused)) *args) { #ifndef HAVE_SETNAME_NP if (prctl(PR_SET_NAME, “FOOOOO”) < 0) fprintf(stderr, “set thread name failed, %s.\n”, strerror(errno)); #endif sleep(60);

    return NULL; }

int main(void) { int rc; pthread_t thread;

    rc = pthread_create(&thread, NULL, threadfunc, NULL);
    if (rc != 0) {
            fprintf(stderr, "create thread failed, %s.\n", strerror(rc));
            return -1;
    }

#ifdef HAVE_SETNAME_NP char thdname[THREAD_NAME_MAX];

    rc = pthread_getname_np(thread, thdname, sizeof(thdname));
    if (rc != 0)
            fprintf(stderr, "get thread_np name failed, %s.\n", strerror(rc));
    fprintf(stdout, "current thread name is '%s'.\n", thdname);

    strncpy(thdname, "FOOBAR", sizeof(thdname) - 1);
    rc = pthread_setname_np(thread, thdname);
    if (rc != 0)
            fprintf(stderr, "set thread_np name failed, %s.\n", strerror(rc)); #endif

    rc = pthread_join(thread, NULL);
    if (rc != 0) {
            fprintf(stderr, "join thread failed, %s.\n", strerror(rc));
            return -1;
    } }

SendFile

sendfile:Linux中的”零拷贝” https://blog.csdn.net/caianye/article/details/7576198 http://fred-zone.blogspot.com/2011/03/linux-kernel-sendfile-server.html

一般来说通过 SendFile 优化之后至少会有 2 倍的效率提升。

kHTTPd 一个内核中的HTTP服务器 http://www.fenrus.demon.nl/

Life of a HTTP request, as seen by my toy web server 极限优化WEB服务器的性能 https://tia.mat.br/posts/2014/10/06/life_of_a_http_request.html https://jvns.ca/blog/2016/01/23/sendfile-a-new-to-me-system-call/ https://blog.plenz.com/2014-04/so-you-want-to-write-to-a-file-real-fast.html

可以通过 man 2 sendfile 查看相关的帮助文档。

#include <sys/sendfile.h> ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

其中 in_fd 必须是一个支持 mmap 的文件描述符,而 out_fd 在 2.6.33 之前只支持 socket ,在此之后支持任意的文件描述符。

    size_t count = 0;
    int filefd;
    struct stat filestat;

    filefd = open(argv[3], O_RDONLY);
    fstat(filefd, &filestat);

    char buff[1024];
    int sock, connfd;
    int rc;
    struct sockaddr_in address, cliaddr;
    socklen_t addrlen = sizeof(cliaddr);

    bzero(&address, sizeof(address));
    address.sin_family = AF_INET;
    inet_pton(AF_INET, argv[1], &address.sin_addr);
    address.sin_port = htons(atoi(argv[2]));

    sock = socket(PF_INET, SOCK_STREAM, 0);
    bind(sock, (struct sockaddr *)&address, sizeof(address));
    listen(sock, 5);

    connfd = accept(sock, (struct sockaddr *)&cliaddr, &addrlen);
    while (1) {
            rc = read(filefd, buff, sizeof(buff));
            count += rc;
            write(connfd, buff, rc);
    }

    close(connfd);
    close(sock);

https://blog.csdn.net/hnlyyk/article/details/50856268

灰度发布 全链路压测

在 Nginx 中,通过 sticky 模块根据 Cookie 中的 mode 字段进行转发,包括了:A) 空 (真正业务流量);B) gray 灰度流量,用来发布测试;C) shadow 影子流量。

进行全链路压测时,实际上流量应该与真正用户相同,只是使用的是影子表,所以在 Nginx 做负载均衡时,实际上也可以将 mode 置空,那么此时就不会转发到不同的服务器。

https://www.kancloud.cn/kancloud/xorm-manual-zh-cn/56003

Casbin

Casbin 一个支持 Access Control List, ACL RBAC ABAC 的开源方案。

PERM stands for Policy, Effect, Request, Matchers.

用户 (User, Subject) 发起操作的主体。 对象 (Object) 操作所针对的目标,例如订单、文件等。 操作 (Action) 执行的动作,例如创建用户、文章等。

ACL

全称为 Access Control List 。

最早也是最基本的一种访问控制机制,原理非常简单:每项资源都配有一个列表,这个列表记录的就是哪些用户可以对这项资源执行 CRUD 中的那些操作。

当访问某项资源时,会先检查这个列表中是否有关于当前用户的访问权限,从而确定当前用户可否执行相应的操作。总得来说,ACL 是一种面向资源的访问控制模型,它的机制是围绕资源展开的。

ACL 简单,但缺点也是很明显。由于需要维护大量的访问权限列表,ACL 在性能上有明显的缺陷。另外,对于拥有大量用户与众多资源的应用,管理访问控制列表本身就变成非常繁重的工作。

自主访问控制 Discretionary Access Control, DAC

当获得授权之后,可以将相关的权限转移给他人使用。

强制访问控制 Mandatory Access Control, MAC

RBAC

也就是基于角色的访问控制,其全称为 Role-Based Access Control 。简单来说,就是每个用户关联一个或多个角色,每个角色关联一个或多个权限,从而可以实现了非常灵活的权限管理。

ABAC

基于属性的权限验证,全称为 Attribute-Based Access Control ,被认为是权限系统设计的未来。

通过动态计算一个或一组属性来是否满足某种条件来进行授权判断,属性通常来说分为四类:用户属性 (如用户年龄)、环境属性 (如当前时间)、操作属性 (如读取) 和对象属性 (如一篇文章),理论上能够实现非常灵活的权限控制,几乎能满足所有类型的需求。

不过 ABAC 的管理太过复杂,实际使用较多的还是 RBAC 。

https://dinolai.com/notes/others/authorization-models-acl-dac-mac-rbac-abac.html https://callistaenterprise.se/blogg/teknik/2017/09/11/go-blog-series-part11/ https://marcus.se.net/hystrix-go-intro/ https://github.com/callistaenterprise/goblog http://www.ru-rocker.com/2017/04/24/micro-services-using-go-kit-hystrix-circuit-breaker/ https://dzone.com/articles/go-microservices-part-11-hystrix-and-resilience https://github.com/tcnksm-sample/hystrix-go

N 的最小 2 次幂

其英文解释为 Smallest power of 2 greater than or equal to N.

Method 1

通过纯数学的计算方法。

  1. 计算 N 底为 2 的对数,并取其 ceil 值。
  2. 再计算其指数。

Method 2

获取数字中的最高位信息。

  1. 判断是否已经是 0 或者 2 的 N 次幂。
  2. 向右移位并获取最高位的值,同时需要统计移位次数。
  3. 按照移位次数向左移动。

Method 3

与方法 2 类似,不需要再统计位移的次数。

https://jameshfisher.com/2018/03/30/round-up-power-2.html https://jeffreystedfast.blogspot.com/2008/06/calculating-nearest-power-of-2.html

#include #include #include #include

unsigned int next_pow2_1(unsigned int v) { return pow(2.0, ceil((log(v) / log(2.0)) + 0.5)); }

unsigned int next_pow2_2(unsigned int v) { int c = 0;

    if (v && !(v & (v - 1)))
            return v;

    for (c = 0; v; c++)
            v >>= 1;

    return 1 << c; }

unsigned int next_pow2_3(unsigned int v) { unsigned int p = 1;

    if (v && !(v & (v - 1)))
            return v;

    while (p < v)
            p <<= 1;

    return p; }

int main(void) { printf(“xxxxx %d\n”, next_pow2_1(5));

    return 0; }

applyAll()

Snapshot

设置

applyAll() |-triggerSnapshot() 通过apply的次数判断是否需要执行Snapshot

在执行备份的时候,可以通过如下命令主动生成 snapshot 。

ENDPOINTS=’127.0.0.1:15379,127.0.0.1:25379,127.0.0.1:35379’ ETCDCTL_API=3 ./etcdctl –endpoints=${ENDPOINTS} snapshot save snap.db

测试

为了方便进行测试,在启动时添加 --snapshot-count '100' 参数,并通过如下脚本生成测试用的数据。

#!/bin/sh -e

ENDPOINTS=’127.0.0.1:15379,127.0.0.1:25379,127.0.0.1:35379’ for ((i=1; i<=150; i ++)); do uuid=uuidgen echo “ETCDCTL_API=3 ./etcdctl –endpoints=${ENDPOINTS} put ${uuid} ‘${uuid}-hello’” done

Progress

Leader 会通过 Progress 维护各个 Follower 的状态,会根据该状态向 Follower 发送日志信息(msgApp)。

对应的实现在 raft/progress.go 中,其中包括了两个重要的属性:

  • match

ins *inflights 发送数据的滑动窗口,最大值为MaxSizePerMsg

becomeProbe

resetState()

https://github.com/metametaclass/libev-aliasing-warning/blob/master/test_alias.c

Protobuf 如果连续发包会导致粘包。

首先会判断是否为新的接口,也就是 XXX_Unmarshal() 的定义。

pb.Reset() 重置报文

SA_RESTART http://www.cnblogs.com/mickole/p/3191832.html commitC 的数据从何而来?

通过 publishEntries()[raft.go] 将已经提交的数据添加到 commitC 管道中,而已经提交数据是从 Ready() 中获取。

初步判断,在 publishEntries() 函数中会添加

注意这里的处理方式有问题?

pthread_setname_np() 函数是在 glibc 的 2.12 版本之后添加的,可以查看其源码实际上如果是本线程也是通过 prctl() 添加,而非本线程则实际修改的 /proc/self/task/%u/comm 文件的内容。

在 C 中,可以通过 goto 跳转到同一个函数的某个 label 处,但是不能在不同的函数之间跳转。实际上,C 另外提供了 setjmp()longjmp() 来完成这种类型的分支跳转。

实现这种类型的跳转,有点类似于操作系统中任务的上下文切换,这里只需要恢复 label 标签所处函数的上下文即可,一般函数上下文包括:

  • 函数栈帧,主要是栈帧指针 BP 和栈顶指针 SP;
  • 程序指针 PC,也就是修改为指向 label 语句处的地址;
  • 其它寄存器,这和 CPU 的体系相关,例如在 x86 体系下需要保存 AX BX CX 等等。

在执行跳转语句时,直接恢复 label 处的上下文,即完成跳转到 label 处的功能。

在 C 语言中 setjmp()longjmp() 就提供了完成保存上下文和切换上下文的工作。

http://www.cnblogs.com/hazir/p/c_setjmp_longjmp.html gcc 关键字 __thread https://blog.csdn.net/liuxuejiang158blog/article/details/14100897

/post/details-about-dstat.html 页面优化

类似于top命令,但是监控的是进程的网络带宽 https://github.com/raboof/nethogs https://zhoujianshi.github.io/articles/2017/Linux%20%E8%8E%B7%E5%8F%96TCP%E8%BF%9E%E6%8E%A5%E4%B8%8Epid%E7%9A%84%E6%98%A0%E5%B0%84%EF%BC%8C%E5%8F%8A%E7%9B%91%E6%B5%8B%E8%BF%9B%E7%A8%8B%E7%9A%84TCP%E6%B5%81%E9%87%8F/index.html

其中 /proc/net/dev 包含了网络设备的相关统计,而 /proc/<pid>/net/dev 包含了进程相关的统计信息。注意,如果进程添加到了网络的 namespace 中 (man ip-netns) ,那么进程中的文件就只有指定的网络设备。

关于CacheLine的介绍 http://cenalulu.github.io/linux/all-about-cpu-cache/

https://blog.csdn.net/muxiqingyang/article/details/6615199 http://www.pandan.xyz/2016/09/23/mesi%20%E7%BC%93%E5%AD%98%E4%B8%80%E8%87%B4%E6%80%A7%E5%8D%8F%E8%AE%AE/

False Sharing

http://blog.yufeng.info/archives/783

参考

详细可以查看 Intel 的文档 Avoiding and Identifying False Sharing Among Threads 中相关介绍,或者本地文档。

虽然目前 Python 在 AI 领域使用的越来越多,不过其在 DevOps、安全领域使用的还比较多,例如可以通过 Python 脚本来简化日常的运维工作。

在 Linux 中可以通过多个命令查看当前系统的信息,例如 pstopfree 等等,如果这样就需要通过类似 subprocess 的模块进行调用,并解析其返回的结果。

实际上,存在一个 psutil (process and system utilities) 可用来获取当前系统的信息,支持 Linux Unix OSX Windows 等多个平台。

这里简单介绍,并提供一个 C 库。

psutil

如果 pip 源配置好之后,可以直接通过 pip install psutil 命令安装,提供的接口详细可以查看 GitHub psutil 中的介绍。

libsysx

主要是参考 Python 中的 psutil 包使用以及实现方式,提供一个 C 实现的 API 接口,实现一个信号安全、可重入的库。

Linux安全审计 https://cisofy.com/downloads/lynis/ https://dacat.cc/1984.html

  1. Cron
  2. PS
  3. lsof
  4. Pipe

Jaeger源码相关的解析 https://github.com/jukylin/blog

Interface Description Language, IDL 接口描述语言

PSUtils 支持 Windows Mac Linux 等 https://www.jianshu.com/p/64e265f663f6 –>



如果喜欢这里的文章,而且又不差钱的话,欢迎打赏个早餐 ^_^


About This Blog

Recent Posts

Categories

Related Links

  • RTEMS
    RTEMS
  • GNU
  • Linux Kernel
  • Arduino

Search


This Site was built by Jin Yang, generated with Jekyll, and hosted on GitHub Pages
©2013-2019 – Jin Yang