Jan
7
使用Excel的过程中经常需要调整行的高度,由于各行的高度不同,统一设定高度往往不适用,而手动逐行调整比较麻烦。有一个常见的小技巧是先按Ctrl+A全选,然后再双击左侧数字标题栏的任意分割线,Excel会自动调整行高。
但是对于精神处女座的我来说,行与行之间没有间隔,所有字密密麻麻挤在一起有点受不了;但是excel又不像css里面可以一句话统一给单元格设置padding或margin(就没有这个属性)。
所幸还有很多其他精神处女座的同学,他们给出的方案 是用宏:
将这段代码保存为一个宏(可以设置一个快捷键,例如 Ctrl + Shift + L),选中某些行,再执行这个宏,就解决问题了。
但是对于精神处女座的我来说,行与行之间没有间隔,所有字密密麻麻挤在一起有点受不了;但是excel又不像css里面可以一句话统一给单元格设置padding或margin(就没有这个属性)。
所幸还有很多其他精神处女座的同学,他们给出的方案 是用宏:
Sub AutoFitPlus()
Dim rng As Range
rowCount = 0
Selection.EntireRow.AutoFit
For Each rng In Selection.Rows
rng.RowHeight = rng.RowHeight + 10
rowCount = rowCount + 1
If rowCount > 100 Then Break
Next rng
End Sub
Dim rng As Range
rowCount = 0
Selection.EntireRow.AutoFit
For Each rng In Selection.Rows
rng.RowHeight = rng.RowHeight + 10
rowCount = rowCount + 1
If rowCount > 100 Then Break
Next rng
End Sub
将这段代码保存为一个宏(可以设置一个快捷键,例如 Ctrl + Shift + L),选中某些行,再执行这个宏,就解决问题了。
Sep
6
excel很强大,但也有非常蠢的地方:比如今天遇到的,导出文档的日期列是“文本”格式,这时候用数据透视表,excel不能识别这是日期,于是无法根据月或者年对数据进行聚合。
即使选中整列,然后将格式全都修改为日期也不行。
即使再弄一列格式为日期的,然后用黏贴数值也不行。
按照过去的经验,只有逐个格子双击,然后回车,才能把格式应用到数据上,真是蠢到爆炸。
今天觉得实在不能忍了,放狗搜了下“excel apply format instead of double click on each column”,总算找到一个解决方案:
1. 选中该列
2. 在“数据”Tab里点击“分列”(按格式将单列文本拆分成多列,英文版是 Text To Columns)
3. 点击完成
搞定
即使选中整列,然后将格式全都修改为日期也不行。
即使再弄一列格式为日期的,然后用黏贴数值也不行。
按照过去的经验,只有逐个格子双击,然后回车,才能把格式应用到数据上,真是蠢到爆炸。
今天觉得实在不能忍了,放狗搜了下“excel apply format instead of double click on each column”,总算找到一个解决方案:
1. 选中该列
2. 在“数据”Tab里点击“分列”(按格式将单列文本拆分成多列,英文版是 Text To Columns)
3. 点击完成
搞定
May
25
$ vi /config/environments/production.rb
注释掉 “config.action_mailer.delivery_method = :sendmail”,
并在下面添加
config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.smtp_settings = {
:address => "smtp.exmail.qq.com",
:port => 465,
:domain => 'yourdomain.com',
:user_name => '发信帐号',
:password => '密码',
:authentication => 'login',
:enable_starttls_auto => true,
:tls => true,
:email_from => '发信帐号'
}
注释掉 “config.action_mailer.delivery_method = :sendmail”,
并在下面添加
引用
config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.smtp_settings = {
:address => "smtp.exmail.qq.com",
:port => 465,
:domain => 'yourdomain.com',
:user_name => '发信帐号',
:password => '密码',
:authentication => 'login',
:enable_starttls_auto => true,
:tls => true,
:email_from => '发信帐号'
}
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月份真高产。。。





