艾莉亚的猫 Time is limited, To be a better man

实现shell脚本中的转圈、进度条等一些效果

要将shell脚本做的好玩好看,核心就是echo的使用问题,还有就是一些实现上的小技巧,从网上学习整理了一些做个备份。

一、Echo

  • 开始shell光标闪烁

echo -e "\033[5m . \033[0m"

二、转圈效果

#!/bin/bash
function waiting()
{
    i=0
    while [ $i -le 100 ]
    do
        for j in '\\' '|' '/' '-'
        do
            printf "\t\t\t\t%c%c%c%c%c test waiting %c%c%c%c%c\r" \
            "$j" "$j" "$j" "$j" "$j" "$j" "$j" "$j" "$j" "$j"
            sleep 0.1
        done
        let i=i+4
    done
}
waiting

三、进度条效果

  • 通过符号#填充[ ]完成进度
#!/bin/bash
i=0
str=""
arry=("\\" "|" "/" "-")
while [ $i -le 100 ]
do
    let index=i%4
    printf "[%-100s] %d %c\r" "$str" "$i" "${arry[$index]}"
    sleep 0.1
    let i=i+1
    str+="#"
done
echo ""
  • 每个阶段有不同颜色区分进度
#!/bin/bash
i=0
str=""
arry=("\\" "|" "/" "-")
while [ $i -le 100 ]
do
    let index=i%4
    if [ $i -le 20 ]; then
        let color=44
        let bg=34
    elif [ $i -le 45 ]; then
        let color=43
        let bg=33
    elif [ $i -le 75 ]; then
        let color=41
        let bg=31
    else
        let color=42
        let bg=32
    fi
    printf "\033[${color};${bg}m%-s\033[0m %d %c\r" "$str" "$i" "${arry[$index]}"
    usleep 30000
    let i=i+1
    str+="#"
done
echo ""
  • 按照百分比显示进度

printf %3d为显示百分比预留了3位,循环条件i每次递增5主要是为了减少进度条显示的长度

i每次递增5,取模之后的index值还是依次循环,保证了转圈圈的方向和频率

改用其他数字,转圈的显示效果没有add=4n+1时的好

#!/bin/bash
i=0
str=""
arry=("|" "/" "-" "\\")
while [ $i -le 100 ]
do
    let index=i%4
    printf "%3d%% %c%-20s%c\r" "$i" "${arry[$index]}" "$str" "${arry[$index]}"
    sleep 0.2
    let i=i+5
    str+="*"
done
echo ""
  • 进度条递进填充

ssty size获取终端X轴和Y轴长度

total=total_stdx-2head 用来控制整个进度条的长度,左右各预留了head长度

per和remain相加永远是total大小

y;xH设置光标位置,${total_stdy};0H设置光标在终端的左下角

%${n}s指定了宽度为n个字符,%${per}s+%${remain}s的总宽是total不变的

设置两个不同颜色的宽度区域,用来显示进度变化,参数赋值空字符串

#!/bin/bash

total_stdy="$(($(stty size|cut -d' ' -f1)))"
total_stdx="$(($(stty size|cut -d' ' -f2)))"

head="Progress bar: "
total=$[${total_stdx} - ${#head}*2]

i=0
loop=100
while [ $i -lt $loop ]
do
    let i=i+1
    
    per=$[${i}*${total}/${loop}]
    remain=$[${total} - ${per}]
    printf "\r\e[${total_stdy};0H${head}\e[42m%${per}s\e[47m%${remain}s\e[00m" "" ""
    sleep 0.1
done

echo ""

软件工程的事实与谬误

55个事实

管理

1.1人员

事实1:在软件开发中,最重要的因素不是程序员采用的工具和技术,而是程序员自身的质量

事实2:对“个体差异”的研究表明,最好的程序员要比最差的程序员强28倍之多。即使他们的报酬不同,优秀程序员也是软件业中最廉价的劳动力。

事实3:给延期的项目增加人手会使项目进一步延期。

事实4:工作环境对工作效率和产品质量具有深刻影响。

1.2工具和技术

事实5:夸大宣传是软件的瘟疫。多数软件工具对于效率和质量的提高幅度仅为5%~35%。但是总有人反复说提高幅度是“数量级”的

事实6:在学习新工具或者新技术的初期,程序员的工作效率和产品质量都会下降。只有克服了学习曲线以后,才可能得到实质性的效益。只有满足下面两个条件,采用新工具或新技术才有意义:(a)新东西确实有用;(b)要想获得真正的收益,必须耐心等待。

事实7:软件开发者对于工具说的多,评估的少,买的多,用的少。

1.3估算

事实8:项目失控的两个最主要的原因之一是糟糕的估算(另一个原因见事实23)

事实9:许多估算是在软件生命周期开始时完成的。后来,我们才认识到在需求定义之前,即理解问题之前进行项目估算是不正确的;也就是说,估算时机是错误的。

事实10:许多软件项目都是由高层管理人员或者营销人员来估算,而不是由真正构建软件的人或者他们的主管来进行估算。因此,估算软件的人员是错误的。

事实11:软件估算很少根据项目进度进行调整。因此,这些估算通常是错误的人在错误的时间得出的错误的结果。

事实12:因为估算的数据如此糟糕,所以在软件项目不能达到估算目标时,不应该再考虑估算。但是无论如何,每个人都在考虑它。

事实13:在管理者和程序员之间存在隔阂。对于一个未满足估算目标的项目的调查表明:从管理者看来这是一个失败的项目,而在技术人员看来确实最成功的项目。

事实14:对于可行性调研的回答几乎总是“可行”。

1.4复用

事实15:小规模的复用(子程序库)开始于50多年以前,这个问题已经得到很好的解决。

事实16:虽然每个人都认为大规模复用(组件)非常重要、非常急需,但是这个问题至今还没有基本解决。

事实17:大规模复用最好适用于相关的系统,也就是依赖于具体应用领域,这样就限制了它的应用范围。

事实18:有关复用问题,有两个“三倍原则”:(a)构建可复用的组件比使用组件难三倍;(b)在将组件收录到复用库并成为通用组件之前,应该在三个不同的应用中尝试应用该组件。

事实19:修改复用的代码特别容易引起错误。如果一个组件中超过20%~25%的代码需要修改,那么重新实现的效率会更高。

  • 由此引出的另外一个事实是:修改经过打包的商业性软件系统通常是错误的。

事实20:设计模式复用是解决代码复用中固有问题的一种方法。

1.5复杂性

事实21:问题的复杂性每增加25%,解决方案的复杂性就增加100%。这不是一个可改变的条件(即使人们都努力降低复杂性),而是客观存在的。

事实22:80%的软件工作是智力活动。相当大的比例是创造性地活动。很少是文书性的工作。

生命周期

2.1需求

事实23:导致项目失控的两个最常见原因之一是不稳定的需求(另一个见事实8所说的项目估算失误)。

事实24:在产品完成时修订需求错误的代价最大,在开发早期修订需求错误的代价最小。

事实25:遗漏需求是最难修订的需求错误。

  • 该事实的一个必然结论是:最持久的软件错误是遗漏逻辑错误,它可以逃过软件测试过程,进入发布的产品中。遗漏需求会导致遗漏逻辑。

2.2设计

事实26:从需求转入设计时,因为制定方案过程的复杂性,会激增出大量的衍生需求(针对一种特定设计方案的需求)。设计需求是原始需求的50倍之多。

事实27:对于一个软件问题,通常不存在唯一的最佳设计方案。

事实28:设计是一个复杂的、迭代的过程。最初的设计方案可能是错误的,当然也不是最优的。

事实29:从设计到编码阶段时,设计者按照自己掌握的水平,已经将问题分解为“原语”。如果编程者和设计者不是同一个人,二者的“原语”不吻合,就会出问题。

事实30:COBOL是一种非常糟糕的语言,但是其他的(用于商业数据处理的)语言也同样糟糕。

事实31:错误消除是软件生命周期中最耗时的阶段。

事实32:普通程序员认为已经彻底测试过的软件其实只执行了55%~60%的逻辑路径。采用覆盖分析器等自动工具,可以将上述比例提高到85%~90%。几乎不可能测试软件中100%的逻辑路径。

事实33:即使测试覆盖有可能达到100%,这种测试也不够。大约35%的错误是源于逻辑路径的缺失,还有40%的错误源于执行特定的路径组合。不可能实现100%的覆盖。

事实34:没有工具就无法做好错误消除工作。人们常用调试器,很少使用覆盖分析器等其他工具。

事实35:自动测试很少,也就是说有些测试可以也应该自动化,但是有许多测试任务不能自动完成。

事实36:程序员在程序中嵌入测试代码、目标代码中的编译参数等方法,都是测试工具的重要补充。

事实37:在运行第一个测试用例之前进行严格审查可以消除软件产品中多大90%的错误。

事实38:虽然严格审查有很多优点,但是不能也不应该代替测试。

事实39:通常认为,事后评审对于了解客户的满意度和改进过程都很重要。但是很多软件公司不开展事后评审。

事实40:同行评审涉及技术和社会两方面问题,忽视任何一方面都回产生严重的灾难。

2.7维护

事实41:维护开支通常占软件成本的40%~80%(平均为60%)。因此,维护可能是软件生命周期中最重要的阶段。

  • 由此引出的一个必然结论:古老的硬件会被抛弃,古老的软件每天都在使用。

事实42:增强功能大约占软件维护成本的60%,错误更正仅占17%。因此,软件维护的主体是在旧软件中加入新功能,而不是更正错误。

事实43:维护是解决方案,而不是解决问题。

事实44:比较软件开发和软件维护中的工作,除了维护中“理解现有的产品”这项工作之外,其他工作都一样。这项工作占据了大约30%的维护时间,是主要的维护活动。因此可以说维护比开发更难。

事实45:更好的软件工程开发导致更多而不是更少的维护。

3 质量

3.1质量

事实46:质量是一组属性的集合。

事实47:软件质量不是用户满意、满足需求、满足成本和时间表目标,或者可靠性。

3.2可靠性

事实48:绝大多数程序员都会犯某些错误。

事实49:错误通常聚集在一起。

事实50:没有唯一最好的消除软件错误的方法。

事实51:总会有残存的错误。我们的目标应该是消除严重错误,或者使之最少。

3.3效率

事实52:效率主要来自于优秀的设计,而不是优秀的编码。

事实53:高级语言(High-order language,HOL)代码配合适当的编译器优化,大约可以达到汇编语言90%的效率。对于一些复杂的现代体系结构,效率更高。

事实54:在空间和时间之间存在折中。通常,改进一方面会降低另一方面。

4 研究

事实55:许多软件研究者不是做调查,而是鼓吹。因此,(a)有些概念比鼓吹的糟糕、更少;(b)缺少有助于确定这些概念真是价值的评估性研究。

5+5谬误

管理

谬误1:你不能管理自己无法度量的东西。

谬误2:可以管理软件产品的质量。

5.1人员

谬误3:可以,也应该“忘我”地编程。

5.2工具和技术

谬误4:工具和技术是通用的。

谬误5:软件需要更多的方法论。

5.3估算

谬误6:要估算成本和时间表,应首先估算代码行数。

生命周期

6.1测试

谬误7:随机测试输入是优化测试的好方法。

谬误8:“假如有了足够多的关注,所有的bug都显而易见。”

6.2维护

谬误9:估计将来的维护成本和做出产品更新的决策需要参考过去的成本数据。

谬误10:教别人编程的方法是教别人写程序。

进程分析工具lsof strace pstack pstree使用

Linux环境中下面的这几个命令都很重要,特别是在跟踪定位后台问题时候,需要熟练运用。

1

strace命令是一种强大的工具,能够显示任何由用户空间发出的系统调用。Strace显示这些调用的参数并返回符号形式的值。

下面记录几个常用的option:

-f选项告诉strace同时跟踪fork和vfork出来的进程。

-o**.txt输出到某个文档。

-e execve只记录execve这类系统调用。

-p pid trace一个现有的进程。

strace -fp $pid


pstack是一个脚本工具,其核心实现是使用了gdb以及threadapply all bt 命令,下面使用pstack查看进程函数堆栈。

pstack pid


pstree命令以树状图显示进程间的关系(displaya tree of processes)。ps命令可以显示当前正在运行的那些进程的信息,但是对于它们之间的关系显示的并不清晰。在linux系统中,系统调用fork可以创建子进程,通过shell可以创建子进程,Linux系统中进程间的关系天生是一棵树,树的根就是进程PID为1的init进程。

pstree -p 以树状图显示系统进程关系

pstree -pa pid 以树状图显示进程PID为<pid>的进程以及子进程


lsof(list open files)是一个列出当前系统打开文件的工具。在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。所以如传输控制协议 (TCP) 和用户数据报协议 (UDP) 套接字等,系统在后台都为该应用程序分配了一个文件描述符,无论这个文件的本质如何,该文件描述符为应用程序与基础操作系统之间的交互提供了通用接口。因为应用程序打开文件的描述符列表提供了大量关于这个应用程序本身的信息,因此通过lsof工具能够查看这个列表对系统监测以及排错很有帮助。

  • losf常用指令
lsof <filename>    显示打开某个文件的进程
lsof +D <DIR>      显示所有打开该目录的进程,注意,如果不想显示其子目录的进程,可以使用+d
lsof -u <username>   显示某个用户启动进程所打开的文件
lsof -u^<username>   显示除了某个用户外的其他所以用户的启动进程打开的文件
lsof -i [4|6][@hostname|ip][:service|port]       显示打开某ip或者端口的进程 (可以和netstat 配合使用), 46 用来区分ip 协议
lsof -i    列出所有的网络连接(注意,网络连接也是文件)
lsof -i TCP:1-1024   列出所有使用TCP 协议,端口范围是1-1024 的网络连接
  • lsof输出列表的含义
FD  Represents the file descriptor. Some of the values of FDs are

cwd  Current Working Directory
txt  Text file
mem  Memory mapped file
mmap  Memory mapped device
NUMBER  Represent the actual file descriptor. The character after the number i.e 1u, represents the mode in which the file is opened. r for read, w for write, u for read and write.

TYPE  of files and its identification.

DIR  Directory
REG  Regular file
CHR  Character special file.
FIFO  First In First Out

参照链接

shawnwang_vip

5 simple ways to troubleshoot using Strace

strace介绍

使用RabbitMQ近一年时间的总结

遇到的一些问题

  • 交换器队列绑定有问题
  • 客户端代码编写问题
  • 没有选择合适的交换器类型
  • 客户端与MQ连接阻塞
  • 网络分区的发生与恢复方案
  • 非持久化镜像队列同步异常

性能优化

  • 优化网络配置(禁用Nagle算法,增加TCP缓存区大小)
  • 客户端代码优化(事务,普通confirm,批量confirm和异步confirm)
  • publisher confirm和comsumer ack,prefetchCount数值
  • 镜像队列的使用拉低整体性能
  • Erlang Hipe compile
  • 避免触发流控机制影响性能

消息传输保障

  • 生产者publisher confirm机制确保消息可靠传输到MQ中

  • 生产者配合使用mandatory或者备份交换器确保消息能够从交换器路由到队列中,进而能够保存下来而不会被丢弃

  • 交换器、消息、队列需要进行持久化处理

  • 消费者在消费消息的同时需要将autoAck设置为false,手动确认消息已经被正确消费

RabbitMQ没有消息去重机制,需要业务方根据自身的业务特性进行去重

运维监控

集群搭建

节点故障恢复

集群监控

  • 通过HTTP API接口提供监控数据
  • 通过客户端提供监控数据
  • 元数据管理与监控

跨级群和WAN部署

使用Federation和shovel可跨越集群(网络状态良好的LAN)界限,实现WAN部署

项目中待改善的细节

  • 使用rabbitmq达到一定规模后,可根据业务功能和场景进行归类拆分,为之分配不同vhost
  • 用户是访问控制的基本单元,单用户可跨多个vhost进行授权,需合理配置用户权限
  • 使用aliveness-test程序配合AMQPPing一起全面监控RabbitMQ服务
  • 加强元数据管理与监控,提供给业务方使用的用户只有可读可写权限,不能够变更元数据信息
  • 目前MQ程序异常是单纯通过守护脚本拉起,这其中逻辑需要完善,确保在启动时最后关闭的节点是第一个启动的

  • 没有对重要业务加以区分,制作备份交换器
  • 没有监控队列中可能存在的消息积压的情况,运维部分薄弱
  • 可考虑预先分配创建元数据资源,避免人为因素,代码缺陷导致的MQ使用问题
  • 格式化使用reset操作而非删除menisa数据

消息追踪和问题定位

  • 使用firehose和tracing插件追踪消息的处理过程
  • 在开启web管理插件的前提下,登陆操作界面查看问题
  • 合理利用amq.rabbitmq.log交换器,过滤不同级别日志信息
  • 查看日志文件分析定位问题
  • 使用操作管理命令(rabbitmqctl)和HTTP API接口

2018年阅读书单

高可用架构(第1卷)

程序员代码面试指南:IT名企算法与数据结构题目最优解

Docker生产环境实践指南

RabbitMQ实战指南

从零起步:素描基础教程

素描的诀窍(15周年畅销版)

Tensorflow:实战Google深度学习框架

软件工程的事实与谬误

Robot Framework 自动化测试修炼宝典

代码之外的功夫-程序员精进之路

十亿消费者

大规模分布式

如何看懂书法

如何写书法

诸遂良阴符经倪宽赞

诸遂良雁塔圣教序