Apr
28
想要计算一个区域里对角线的和,但SUMIF里面的那个criteria实在太简陋了,只能用vba来实现,大概长这样:
然后这么用:
引用
Function sum_diag(n As Integer, ParamArray args() As Variant) As Variant
result = 0
For i = LBound(args) To UBound(args)
For Each elem In args(i)
If elem.Row + elem.Column = n Then
result = result + elem.Value
End If
Next elem
Next i
sum_diag = result
End Function
result = 0
For i = LBound(args) To UBound(args)
For Each elem In args(i)
If elem.Row + elem.Column = n Then
result = result + elem.Value
End If
Next elem
Next i
sum_diag = result
End Function
然后这么用:
引用
=sum_diag(ROW()+COLUMN(), $B$1:$D$3)
Sep
21
虽然我们使用的腾讯云自带了一份监控,但是实在太弱,不好用(上次因为crontab导致postfix的maildrop把inode用光,腾讯云没有任何报警信息),所以我们额外搭建了一套Zabbix用于线上服务的监控,用来发现更细粒度的系统问题,例如io过载、cpu过载、内存不足、磁盘空间不足、服务down了之类的事件。
发现了事件需要及时报警,但是zabbix自带的那个邮件通知太弱(不支持需要用户名和密码的smtp服务器),所以需要自定义通知。zabbix文档在有对自定义通知的说明,但是太粗略了,折腾了好久终于搞明白,这里记录一下备查。
1. 编写通知发送脚本
参照Custom alertscripts,写一个脚本,接受三个命令行参数 "to subject body" (即收件人、标题、正文),把消息发送出去。例如我们的短信通知是这样的(注: message.test.com是我们内部的统一通知服务):
文件名: sms
除此之外我们还配置了通过 email、sentry 报警的脚本。
2. 将通知脚本置于 zabbix_server.conf 配置的 AlertScriptsPath 目录下
注意:必须在这个目录下、zabbix进程有执行权限
3. 在zabbix控制台配置通知脚本
4. 配置用户支持的通知方法
4. 配置触发器
5. 触发事件测试效果
根据情况启动若干个耗cpu的进程,例如:
$ cat /dev/urandom | md5sum
发现了事件需要及时报警,但是zabbix自带的那个邮件通知太弱(不支持需要用户名和密码的smtp服务器),所以需要自定义通知。zabbix文档在有对自定义通知的说明,但是太粗略了,折腾了好久终于搞明白,这里记录一下备查。
1. 编写通知发送脚本
参照Custom alertscripts,写一个脚本,接受三个命令行参数 "to subject body" (即收件人、标题、正文),把消息发送出去。例如我们的短信通知是这样的(注: message.test.com是我们内部的统一通知服务):
文件名: sms
引用
#!/usr/bin/python
import sys
import requests
to = sys.argv[1]
subject = sys.argv[2]
body = sys.argv[3]
message = '%s: %s' % (subject, body)
print requests.post('http://message.test.com/sms/send', {
'request_source' : 'monitor',
'mobile' : to,
'message' : message
})
import sys
import requests
to = sys.argv[1]
subject = sys.argv[2]
body = sys.argv[3]
message = '%s: %s' % (subject, body)
print requests.post('http://message.test.com/sms/send', {
'request_source' : 'monitor',
'mobile' : to,
'message' : message
})
除此之外我们还配置了通过 email、sentry 报警的脚本。
2. 将通知脚本置于 zabbix_server.conf 配置的 AlertScriptsPath 目录下
注意:必须在这个目录下、zabbix进程有执行权限
3. 在zabbix控制台配置通知脚本
引用
Administration -> Media Types -> (右上角) Create Media Type
Name: sms
Type: Script
Script name: sms (这里写脚本的名字就行,不用全路径)
Enabled: 打勾
Save.
Name: sms
Type: Script
Script name: sms (这里写脚本的名字就行,不用全路径)
Enabled: 打勾
Save.
4. 配置用户支持的通知方法
引用
Administration -> Users -> 点击需要配置的用户(例如Admin) -> Media -> Add
Type: sms
Send to: 13800138000 (这就是脚本接受到第一个参数)
When Active: 1-7, 00:00-24:00 (7*24,运维的悲剧)
Use if severity: 根据情况勾选
Status: Enabled
Add.
Save. (别漏了点这里!)
Type: sms
Send to: 13800138000 (这就是脚本接受到第一个参数)
When Active: 1-7, 00:00-24:00 (7*24,运维的悲剧)
Use if severity: 根据情况勾选
Status: Enabled
Add.
Save. (别漏了点这里!)
4. 配置触发器
引用
Configuration -> Actions -> (右上角) create action
#Action
Name: send to sms
#Operations (以下是参考选择)
a) 点击New
b) 添加收件人:Send to Users 右边的 Add 选择 Admin
c) 选择通知方式:Send only to 选择 sms
d) 点击Add
e) 点击Save
Add和Save都得点,否则就又2了
#Action
Name: send to sms
#Operations (以下是参考选择)
a) 点击New
b) 添加收件人:Send to Users 右边的 Add 选择 Admin
c) 选择通知方式:Send only to 选择 sms
d) 点击Add
e) 点击Save
Add和Save都得点,否则就又2了
5. 触发事件测试效果
根据情况启动若干个耗cpu的进程,例如:
$ cat /dev/urandom | md5sum
Oct
16
在Windows下用惯了Secure CRT的Clone Session功能,切换到mac下面,还真有点怀念。于是搜了一下,发现达到类似的效果倒是也不难。
1. mkdir ~/.ssh/cm_socket
2. 创建 ~/.ssh/config
Host *
ControlMaster auto
ControlPath ~/.ssh/cm_socket/%r@%h:%p
3. 之后只要是相同的 user@host:port 都会共用一个tcp connection,不需要再输入密码了。
p.s. 补充说明一下,通常来说,能登录服务器也就意味着可以建立信任关系,那么clone session的意义就减少了很多,但是仍然有两个优势:
1. 类似B公司的relay机器,必须使用token认证才能登录的,信任关系不能满足需求(Google Authenticator这样的两步认证方案也类似)
2. 对于延迟比较高的机器,直接复用tcp connection,可以减少相当多的时间(tcp三次握手、ssh认证的各种交互等)。
1. mkdir ~/.ssh/cm_socket
2. 创建 ~/.ssh/config
Host *
ControlMaster auto
ControlPath ~/.ssh/cm_socket/%r@%h:%p
3. 之后只要是相同的 user@host:port 都会共用一个tcp connection,不需要再输入密码了。
p.s. 补充说明一下,通常来说,能登录服务器也就意味着可以建立信任关系,那么clone session的意义就减少了很多,但是仍然有两个优势:
1. 类似B公司的relay机器,必须使用token认证才能登录的,信任关系不能满足需求(Google Authenticator这样的两步认证方案也类似)
2. 对于延迟比较高的机器,直接复用tcp connection,可以减少相当多的时间(tcp三次握手、ssh认证的各种交互等)。
Jul
14
~ vimdiff 比对文件的时候,可以使用 "]c" 或者 "[c" 跳转到下一个/上一个不同的地方。
~ retab 将文件中的tab字符按vimrc中指定的格式转换成空格
~ 未完待续
~ retab 将文件中的tab字符按vimrc中指定的格式转换成空格
~ 未完待续
Mar
8
昨天黄老湿问了我个问题, [ -e ] 是true还是false?为什么?
==== 啦啦啦啦啦的分割线,猜猜吧 ====
这种坑题显然只能实践出真知:
果然坑了。
仔细想想,这个问题其实还是来源于实践的,比如一个很有可能会出现的写法是:
显然,在这个情况下,如果$somefile意外地是一个空串的话,bash实际上执行的就是 [ -e ] (这个可以很容易地验证),于是返回了 true。
简单过了一下源码(coreutils/src/test.c),可以看到执行流是
也就是说对于只有一个参数的情况下,test只是简单地判断这个参数是否为空(无论是不是它支持的操作符),有两个参数的情况,才会去判断是否是合法操作符,再执行相应的检测。
然后才想起来,原来我还可以看manual啊,泪流满面。。。man test,果然看到这几行:
也就是说 test STRING 等于 test -n STRING ,检查非空串,于是 [ -e ] 就等于 test -n "-e",自然就是true了。。。
对于上面提到的情况来说,解决办法是在引用变量的时候,记得加上双引号,这样test就会收到2个参数,其中第二个参数是空串,stat出错,于是就可以得到(可能原先)期望的结果了:
不过话说回来,bash脚本中引用不存在的变量这件事情本来就不应该发生,类似 rm -rf $some_path/ 这样的悲剧也不是没有发生过,但是bash又没有一个 explicit 模式,所以只能自己在使用之前检测了。
通常检测一个变量是否为空,用上面的 test -n "$VAR" 或者 test -z "$VAR" 即可(注意引号),但是如果要检测某个变量是否根本不存在,BASH却没有内建方法,只能通过这种看起来很奇怪的方式(出自stack overflow):
//本博客3月份真高产。。。
==== 啦啦啦啦啦的分割线,猜猜吧 ====
这种坑题显然只能实践出真知:
引用
$ [ -e ] && echo yes || echo no
yes
yes
果然坑了。
仔细想想,这个问题其实还是来源于实践的,比如一个很有可能会出现的写法是:
引用
[ -e $somefile ] && do_sth || do_sth_else
显然,在这个情况下,如果$somefile意外地是一个空串的话,bash实际上执行的就是 [ -e ] (这个可以很容易地验证),于是返回了 true。
简单过了一下源码(coreutils/src/test.c),可以看到执行流是
value = posixtest(argc - 1 <as> nargs);
switch(nargs)
case 1: //只有一个参数
return one_argument();
return argv[pos++][0] != '\0'; //检查不为空串
case 2: //只有俩参数
return two_arguments();
if (argv[pos] 是 - 开头 <且> 只有俩字符 <且> 是unary_operator)
return unary_operator()
switch(argv[pos][1]):
case 'e':
unary_advance() //里面pos加了2
return stat(argv[pos-1], &stat_buf) == 0;
case .. //更多参数
test_exit(value ? TEST_TRUE : TEST_FALSE);
switch(nargs)
case 1: //只有一个参数
return one_argument();
return argv[pos++][0] != '\0'; //检查不为空串
case 2: //只有俩参数
return two_arguments();
if (argv[pos] 是 - 开头 <且> 只有俩字符 <且> 是unary_operator)
return unary_operator()
switch(argv[pos][1]):
case 'e':
unary_advance() //里面pos加了2
return stat(argv[pos-1], &stat_buf) == 0;
case .. //更多参数
test_exit(value ? TEST_TRUE : TEST_FALSE);
也就是说对于只有一个参数的情况下,test只是简单地判断这个参数是否为空(无论是不是它支持的操作符),有两个参数的情况,才会去判断是否是合法操作符,再执行相应的检测。
然后才想起来,原来我还可以看manual啊,泪流满面。。。man test,果然看到这几行:
引用
-n STRING
the length of STRING is nonzero
STRING equivalent to -n STRING
the length of STRING is nonzero
STRING equivalent to -n STRING
也就是说 test STRING 等于 test -n STRING ,检查非空串,于是 [ -e ] 就等于 test -n "-e",自然就是true了。。。
对于上面提到的情况来说,解决办法是在引用变量的时候,记得加上双引号,这样test就会收到2个参数,其中第二个参数是空串,stat出错,于是就可以得到(可能原先)期望的结果了:
引用
$ [ -e "$somefile" ] && echo yes || echo no
no
no
不过话说回来,bash脚本中引用不存在的变量这件事情本来就不应该发生,类似 rm -rf $some_path/ 这样的悲剧也不是没有发生过,但是bash又没有一个 explicit 模式,所以只能自己在使用之前检测了。
通常检测一个变量是否为空,用上面的 test -n "$VAR" 或者 test -z "$VAR" 即可(注意引号),但是如果要检测某个变量是否根本不存在,BASH却没有内建方法,只能通过这种看起来很奇怪的方式(出自stack overflow):
if [ -z "${VAR+xxx}" ]; then echo VAR is not set at all; fi
//本博客3月份真高产。。。
Oct
19
经常是用vim打开了某个/etc下的文件,使用 :w 保存的时候提示 "E45: 'readonly' option is set (add ! to override)",而 :w! 则提示 "E212: Can't open file for writing"。通常的解决方案是 :q! 然后 sudo !! 再次编辑,然后保存。
虽然挺麻烦,但是一直也就将就用了。今天有人在SegmentFault.com提出了这个问题,于是仔细考虑了下,的确还是有办法实现的:
:%!sudo bash -c "cat > '%'" #为了防止文件名中的空格之类特殊字符,最好在后一个%前后加上引号
:w !sudo tee % #另一个回答给出的这个方法更简洁,出自 http://vim.wikia.com/wiki/Su-write
其实最初的想法是 :%!sudo cat > % ,但是由于权限的问题(vim打开的shell没法清空当前文件),所以还是得请shell进来掺和一脚:先用sudo给shell提权,然后shell再执行cat将stdin的内容输出到%。
p.s. 顺便给不了解 :%! 这个含义的同学普及一下, :!xxx 是执行 xxx 命令, :%!xxx 则是把当前缓冲区的所有内容当成 stdin 去执行 xxx 命令,然后将xxx的stdout再替换当前缓冲区的内容。比较常见的用法是 :%!sort 给文件所有的行排序,然后 :%!uniq 去重。另外%可以用范围来代替(同 :s 命令的范围)。
虽然挺麻烦,但是一直也就将就用了。今天有人在SegmentFault.com提出了这个问题,于是仔细考虑了下,的确还是有办法实现的:
引用
:w !sudo tee % #另一个回答给出的这个方法更简洁,出自 http://vim.wikia.com/wiki/Su-write
其实最初的想法是 :%!sudo cat > % ,但是由于权限的问题(vim打开的shell没法清空当前文件),所以还是得请shell进来掺和一脚:先用sudo给shell提权,然后shell再执行cat将stdin的内容输出到%。
p.s. 顺便给不了解 :%! 这个含义的同学普及一下, :!xxx 是执行 xxx 命令, :%!xxx 则是把当前缓冲区的所有内容当成 stdin 去执行 xxx 命令,然后将xxx的stdout再替换当前缓冲区的内容。比较常见的用法是 :%!sort 给文件所有的行排序,然后 :%!uniq 去重。另外%可以用范围来代替(同 :s 命令的范围)。
Sep
23
Aug
24
:set formatoptions+=m "允许对multi_byte字符换行(否则默认只能空格或者英文标点,详见set breakat=)
:set textwidth=80 "换行的长度
ggVG "选中全文
gq "应用到选中文本
p.s. 最后两句也可以缩写成 gggpG (少一个字符)..
:set textwidth=80 "换行的长度
ggVG "选中全文
gq "应用到选中文本
p.s. 最后两句也可以缩写成 gggpG (少一个字符)..