9月 192018
 

缘起:

docker stop 时往往会比较慢,起原因多半是docker 容器的init进程没有正确处理信号所致;docker stop的行为为: 先发送一个SIGTERM(15) 信号给init进程,如果一段时间(默认10s)后,依然没有退出,就直接发送 -9 信号,常常我们会登上10s,最终,进程的退出依然是仓促的;所以,实现一个好的init进程非常重要。

想用bash写一个docker 的init进程,当收到SIGTERM信号时,通知容器中的其他进程退出,其他进程退出后自己再退出,这样的话,其他进程可以有时间优雅退出,而且stop操作还可能很快完成。

版本1:

实际并不凑效; 原因: bash 在执行外部命令的时候,是不处理信号的

 

改进:

不足:当有信号到时,依然要等sleep 睡足才能处理信号,如果每次sleep 时间足够短,则总是启动sleep进程也非常不优雅,本身总是看到一个sleep进程已经够闹心的了

 

改进:

优点:

  1. 看不到sleep函数了
  2. read line 并不消耗多少资源
  3. 虽然 read 函数是阻塞的,但是却不影响bash实时处理信号

缺点:

  1. 创建容器时需要 -it 选项,因为bash标准输入需要是正常的,才能是的read不会失败而正常阻塞,否则,read会一直失败,导致死循环占用100% CPU ; 安全一些的做法是,发现read失败直接退出

 

测试脚本:

执行该脚本,然后发送信号15给bash进程,发现:

  • 当执行到sleep 10 的时候,不能实时处理信号
  • 当阻塞在read时,可以实时处理信号
 Posted by at 下午 5:08
7月 272018
 

有些时候,我们通过如下方式执行命令:

这样,cmd.sh 中就能看到变量var ; 但是千万别写成:

这里的 $var 绝对不是1; 因为$var 是在var=1被解释之前解释的

 

如下:

 Posted by at 下午 5:21
7月 172018
 

我想通过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

 

 Posted by at 下午 2:50
7月 162018
 

场景:

对于多个部分的命令行会打印到多行,如下:

其实,printf就是这个表现的,如下:

也就是说,最后一个 %s 是不能吃掉多余的参数的,相反, printf 是如下方式消费参数的:

 Posted by at 下午 4:16
7月 162018
 

 

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

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

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

 Posted by at 下午 3:54
7月 162018
 

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

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

 

参考:

 Posted by at 上午 11:10
7月 162018
 

 

 

 Posted by at 上午 10:30
6月 112018
 

排序一般使用sort命令,但是,sort命令是基于行的:

这个是不会输出 : a b c d 的

可以这样:

也或者:

总之,把空白换成换行

 Posted by at 上午 11:18