tcp server in bash

我想通过nc+bash创建一个tcp server, nc负责收发数据,bash负责处理数据,如何将nc和bash结合起来呢?

思路1: 通过nc的-c选项实现

思路2: 只要能想办法将nc的标准输入和标准输入重定向给bash脚本就行了; 我们常见的管道、进程替换都只能同时做重定向标准输入或标准输出的其中一件事情; 如:

或:

这两个都是单向的

思路3: 我们通常使用exec来做重定向,似乎也比较麻烦

思路4: bash中提供了一个coproc关键字,似乎用在这里再合适不过了

 

方法1:

handler.sh

server.sh

这里利用了nc 的-c选项;

注意:

  • 这里的handler.sh 必须有可执行权限
  • handler.sh 必须在$PATH 里面,nc不参考当前目录
  • 为了规避这两个问题,可以这样:
  • 这种情况下,对于每一个连接都会启动一个-c指定的进程来处理,类似于cgi的模式;如果client 离开的太快,handler.sh echo时会遇到pipe broken的错误,需要处理一下
  • 需要仔细处理read ,避免client离开时,handler.sh还在无休止地循环,而且还占用 100% 的cpu

这里是通过两个文件来实现的,对于脚本程序来讲,如果一个文件能实现会方便很多;那么 nc 的 -c 选项能否接受一个bash 的function呢?直接写function显然是不行的,我们知道,环境变量是可以继承的,但是function 是不行的(参考: https://phpor.net/blog/post/9188),而且我们也不能把function赋值给一个变量; 或者可以这么实现:

但是,显得好不优雅; 而且,最大的问题就是,一不小心就可能成为fork炸弹💣

 

方法2:server.sh

注意:

  • 方法二的原理和方法一是不同的;这里的handler是一个常驻进程,不需要每次请求都fork一个handler,似乎更好一些,但是,handler无法区分不同的请求,client A可能接受到client B的请求的响应

问题:

  • 这个server可以服务很多请求,但是无法实现服务完一个请求后主动断开
  • 如何nc先退出了,handler如何判断

 

参考:

总结:

  • bash写个简版的东西还挺方便,写完善就不好弄了
  • 方法一似乎更加合理一些
  • 千万别用bash来实现tcpserver

 

bash 获取所有pid

 

ls 可以list /proc 目录下所有的pid,但是线程id是list不到的,如:

我们 ls /proc 的时候,只能看到 24 这个目录,看不到25 26 27 这些目录,那么线程的信息如何访问到呢?

实际上,虽然我们不能ls /proc 看到线程,但是,如果有了线程id,还是可以通过 /proc/$thread_id 来访问的,如:

count words in bash without wc

如何计算字符串中单词的数量,但是不使用wc? eg:

如果字符串的内容在文件中,则可以直接 read -a arr 来读入到指定数组中,然后再获取数组的长度即可

 

参考:

cfree ( free in container)

 

 

阿里云oss 之 ossfs

缘起

阿里云OSS比云硬盘要便宜很多,而且阿里云提供一个叫做ossfs的工具,可以将OSS挂载成本地文件系统,如果使用docker的话,也可以很容易实现一个docker volume的插件,岂不快哉!

测试几种情况:

ossfs挂载成本地文件系统后:

head -c 100 会不会很快?

测试发现,不会很快,ossfs会在/tmp目录生成一个临时文件,下载的数据远不止100字节; 所以,对于特别到的文件来讲,是受制于本地磁盘的容量的。

写入是如何实现的?写大文件时,会不会占用大量内存或本地磁盘?

写入大文件时,会在 /tmp 下创建一个临时文件(该文件打开后立即删除的,只能通过ossfs进程来看),写完后再上传到oss上; 所以,写入的文件大小同样受制于本地磁盘的容量。

ls 命令会不会快?

当目录下文件很多时,ls会非常慢。原因:ls不仅仅是一个http请求拉取文件列表,而是在拉取文件列表之后,还要通过head请求获取每个文件的元数据,假如一个目录下有几万个文件,就需要几万次请求

总结:

ossfs 将oss挂载成本地文件系统后:

  • 上传和下载时总是先写入本地磁盘 (/tmp 目录);
  • 整体读写效率较差;
  • 对于单个的大文件的情况,要考虑本地磁盘容量是否够用;
  • 下载时,虽然先下载到临时目录,但是文件并不缓存;再次访问依然需要重新下载
  • 上传时,虽然先写本地文件,应用层依然要等到文件上传完毕后才能返回(因为oss是对象存储,写入对象前必须先知道对象的大小);具体表现为,fclose触发ossfs的文件上传,但是需要等到文件上传完成后,fclose才算执行完; 对于 PHP 来讲,文件的fclose即使不显式调用,结束前也会隐式调用的
  • 所以:
    • ossfs 需要考虑适用场景
    • ossfs比较适合小文件的场景
    • ossfs不解决单个文件超过本地磁盘容量的问题;或者说,可能通过操作多个文件,而且有可能多个文件的大小之和会超过本地磁盘容量
  • 对象存储毕竟是对象存储,不能因为可以挂载到本地文件系统就变成了块儿存储

关于Mysql 索引

 

索引滥用

 

表索引情况如下:

我们发现,buss_no 开头的索引就有三个,从名字上来看,是个类似于唯一号的字段,从buss_no 的索引类型来看,不是唯一索引,很可能就是不唯一的;但是,直觉判断,不能看像类型、状态之类的字段有超大的重复度。实际分析发现,每个buss_no 不会超过10条记录;对于这种情况,下面的两个buss_no开头的联合索引就是非常多余的,因为后面的两个联合索引总是先定位buss_no,在定位其他字段的;由于buss_no已经把结果集缩小到10条记录一下了,对于10条记录集的数据量完全可以自己在程序中进行排序、查找等处理,大可不必再创建联合索引,这样会导致索引很大,现在这个表的索引数据情况为:

不难发现,索引空间比表数据空间都大很多了

 

注意: 有些情况下,使用的覆盖索引和这种情况有些许类似,但不可等而视之

 

不给唯一性小的字段创建索引

如: 类型、状态字段,值往往只有很少的几个,创建索引的意义不大

如何忽略指定索引

面对已经存在了大量索引,如何验证使用索引和不使用索引的执行效率差别的大小呢?

直接删掉不想用的索引自然是个办法,但是我们的操作可能是线上的,随意删除和创建索引太不专业了;幸好mysql早就帮我们想好了,我们可以在sql语句中指定是否启用和禁用指定的索引:https://www.cnblogs.com/lcngu/p/6023179.html

 

参考: