Skip navigation.

生活周遭

In My Circle

Posts tagged with "tips"

Tips: find到带空格文件名用xargs处理的技巧

, ,

find和xargs是最好的组合,可以说是linux shell下的瑞士军刀,用xargs配合find,比直接用find的-exec参数,速度更快,用法也更直观。
基本的用法比如:
find ./ -name '*.bak' | xargs rm -rf

一般情况,上面这个命令运行的很好,但是如果找到的文件名代空格,上面的命令运行就可能会出问题了。

find有一个参数-print0,于默认的-print相比,输出的序列不是以空格分隔,而是以null字符分隔。而xargs也有一个参数-0,可以接受以null而非空格间隔的输入流。所以说xargs简直就是为find而生的。上面的问题就很好解决了:
find ./ -name '*.bak' -print0 | xargs -0 rm -rf


用p4命令行作打包修改中的changelist

发现这种heavy GUI的工具,非常不灵活,非常难用,能做什么都是定好的,想要做点没有预订好的事情根本就是不可能的。Perforce就是,非常怀念cvs/svn。
想要把一个正在修改的changelist给同事,发现p4的GUI根本不能做patch,命令行好像也不行。想想,做出个diff格式的patch,同事也未必能用(windows世界...)。于是,饶了个大弯路,写了个长命令,用于打包本地changelist的文件:
p4 change -o  14563 | grep --color="never" -o "//depot/[^ ]*"  | cut -c 40- | xargs tar rvf patch.tar

最后之所以用tar rvf而不是jcvf,是怕xargs接到的文件列表太长,分几次传给tar。最后的tar,你要bzip2还是gzip就随意了。

Tips: grep, output only matched patterns

, ,

"sed的in-place edit选项,和RTFM"中,说到过:

...关于 Search and Replace 和 Regular Expression,还有一个问题困扰我,在这儿记下来。 就是将文件中符合某个pattern的字符串打印出来。注意,只是符合这个pattern的字符串本身,而不是所在行。直接一看,这怎么都是grep的工作嘛,可以在对grep狠狠的RTFM以后,还是未果...


GNU grep's new features上看到

If you haven't been paying attention to GNU grep recently, you should be happily surprised by some of the new features and options that have come about with the 2.5 series. They bring it functionality you can't get anywhere else -- including the ability to output only matched patterns (not lines), color output, and new file and directory options.


于是特地又看了一下grep的man page,我手边的是公司里cygwin下的grep-2.5.1a,果然有这么一个参数:
  -o, --only-matching       show only the part of a line matching PATTERN

试了一下,真是好用。看来是2.5系列新加的功能。(不过现在又不免想,是不是早在发sed的in-place edit选项,和RTFM,grep就已经有-o可用了?汗~……)

Tips:autossh

, , ,

SSH的特性就是安全,如果一个连接长期闲置,那么就可能被利用,所以SSH服务端一般都会有一个超过Idle时间踢出的设置。不过像我们经常会用SSH登陆到远程服务器上长时间的工作的,这个特性就非常不方便了。于是autossh,就是这么一个牺牲安全性,换取便利性的工具。

autossh通过建立另一个SSH连接来监视工作SSH连接,当工作连接断开的时候,能够自动发起重连。不过你得设置ssh-agent,否则,重连的时候还是会提示你输入密码的,这样就失去意义了。

不过,就算是重连,你正在做的工作也会因为失去连接登出而都被杀死的。这时候就该GNU screen登场了。在你ssh到远程服务器的时候,启动一个screen Session,screen可以让你在ssh失去连接的时候自动detach,然后重连上来的时候,只要用screen -D -R取回screen Session就可以了。而且,autossh自带了一个非常好用的script rscreen,已经完完整整的帮忙做好了这件事情,只要直接拿过来用就可以了。

至于安装嘛,对于Debian,照例只要apt就可以了,下面贴一下我的对rscreen的小小修改,去掉了不需要的键设置,使用remoteSSH做为screen Session的名字以区别其他的screen Session,接收全部的ssh参数:

 
--- /usr/share/doc/autossh-1.3/examples/rscreen 2005-03-23 10:05:20.001000000 +0800 
+++ /usr/local/bin/rscreen  2006-05-16 11:41:23.705698100 +0800 
@@ -23,4 +23,4 @@ 
 #AUTOSSH_PATH=/usr/local/bin/ssh
 export AUTOSSH_POLL AUTOSSH_LOGFILE AUTOSSH_DEBUG AUTOSSH_PATH AUTOSSH_GATETIME AUTOSSH_PORT

-autossh -M 20004 -t $1 "screen -e^Zz -D -R" 
+autossh -M 20004 -t $* "screen -D -R remoteSSH" 

Tips: 图片格式的批量转换

, ,

手上有一堆很大的tif图片,想要批量转成尺寸小一点的jpg图片。对于图片处理,特别是批量的时候,命令行工具imagemagick可以说是最好不过的工具了。
一般对于处理转换图片,imagemagick提供了convert和mogrify两个工具,convert一般用于处理完后输出到另一个文件,而mogrify一般用于修改源文件,但是如果指明不同的格式,mogrify也会保存到另一个不同扩展名的文件中去。这里我要用到的就是magrify。
命令很简单:
ls *tif | xargs -n1 mogrify -format jpg -resize ">1024x1024"

xargs的强大,这里就不说了。这里主要涉及mogrify的两个参数,-fromat和-resize。-format指明格式,这里是jpg。-resize就是要修改尺寸,这里用的是">1024x1024",意思是输出图片不能大于1024x1024,这也是一个很方便的用法,这样,输出的图片最长的一边都不会超过1024,大小都比较统一。如果只是指明 -resize 1024 的话,只能保证横向宽度为1024,如果是纵向较长的竖图片,可能就会变成1024x1540之类的尺寸,大小就不统一了。

imagemagick非常强大,并且具备命令行工具特有的方便和适于脚本的特性,非常适合于批量处理。除了上述的例子,我原先还用imagemagick写过一个批量添加png图片透明层的简单脚本,不过不知道扔哪儿了,回头找找再帖上来。

Tips: procmailrc规则中的中文处理

, ,

procmail有很方便的基于正则表达式的规则,非常强大。 处理英文字段自然OK,可是处理中文字段呢?直接打中文恐怕是肯定不可以了。比如分类Subject段包含“中国”的规则,如果写成:
* ^Subject.*中国
那就找不到了。因为procmail直接处理邮件文本,而邮件文本都是编码过的,Subject段是肯定不会直接出现“中国”字样。 一般邮件内容的编码常用的有两种,QuotedPrintable和Base64,下面分开说。
QuotePrintable
用文本编辑器直接打开mbox文件,在Subject段看到
=?utf-8?Q?Goowy=e9=82=ae=e4=bb=b6=e6=9c=8d=e5=8a=a1=e7=9a
=84flash=e7=95=8c=e9=9d=a2_=5bFlickr=5d?=
这样都是=间隔的,就是QuotePrintable编码了,其中头部=?utf-8?Q?中的Q也指出了这儿用的是QuotePrintable编码,utf-8不用解释,就是文本是utf-8编码的。以上的Subject段解码后是:
Goowy邮件服务的flash界面_[Flickr]
对于QuotePrintable的Procmail规则就比较简单,直接根据关键字的编码,加入=号间隔就可以了。比如我们查找关键字“服务”,对应的utf-8序列是
0xe69c8d 0xe58aa1
,一般中文自的utf8编码都会是3个字节,那么对应的就是
=e6=9c=8d=e5=8a=a1
,规则可以这么写:
* ^Subject.*=e6=9c=8d=e5=8a=a1
对于GB系列编码也是一样,只是每个汉字就是两个字节,而不是三个了。
Base64
Base64的嘛,hoho,再研究研究~ 等下回吧~

Tips: ssh记住密码,自动登录

, ,

ssh登录,每次都要敲密码,敲多了自然是烦。而且ssh的安全性,使它不能在任何配置文件中或者命令行参数中直接指出密码,所以只能不厌其烦的每次等待登录框出现,然后敲入密码。特别是使用ssh认证的cvs,svn之类的,更是影响工作情绪。ssh-agent就是用于解决这个问题的:
1. Creating authentication key
用ssh-keygen生成公/私钥对:
  beowulf% ssh-keygen -t rsa
  Generating public/private rsa key pair.
  Enter file in which to save the key (/u/kim/.ssh/id_rsa): [RETURN]
  Enter passphrase (empty for no passphrase): litt1e 1amp jumb3d
  Enter same passphrase again: litt1e 1amp jumb3d
  Your identification has been saved in /u/kim/.ssh/id_rsa.
  Your public key has been saved in /u/kim/.ssh/id_rsa.pub.
  The key fingerprint is:
  b7:18:ad:3b:0b:50:5c:e1:da:2d:6f:5b:65:82:94:c5 kim@beowulf.gw.com
记住你的passphrase(这里是little lamp jump3d)。其中~/.ssh/id_rsa.pub为公钥文件
2. Authorizing access
将公钥上传成目标机的~/.ssh/authorized_keys (ftp,scp都可以)
  beowulf% cd ~/.ssh
  beowulf% cp id_rsa.pub authorized_keys
  beowulf% scp -p ~/.ssh/authorized_keys kim@hrothgar:.ssh/
  kim@hrothgar’s password: YourPasswordHere
  authorized_keys               100% 1839     1.2MB/s   00:00 
其中需要输入目标机上你的用户密码(在此为hrothgar上的kim用户)。 这时,你使用ssh登录时,将会通过你identification的passphrase来登录了。
  beowulf% ssh hrothgar
  Enter passphrase for key '/u/kim/.ssh/id_rsa': litt1e 1amp jumb3d
  kim@hrothgar% 
3. Keeping authentication keys in memory
通过ssh-agent来记住认证,添加的方式见下一节。一般的做法是通过ssh-agent来启动一个shell,在该shell中使用:
  beowulf% ssh-agent $SHELL
  beowulf% 
我用的是Debian,在/etc/X11/Xsession.d/下面就又一个90xfree86-common_ssh-agent用于使用ssh-agent来启动X,这样,一进入X,ssh-agent就是可用的。如果你的系统里没有这样的设置,简单的做法就是用"ssh-agent startx"来启动X,如果你用的是xdm,gdm之类的,修改你的~/.xsession文件
4. Managing keys in memory
通过ssh-add添加keys。
  beowulf% ssh-add
  Enter passphrase for /u/kim/.ssh/id_rsa: litt1e 1amp jumb3d
  Identity added: /u/kim/.ssh/id_rsa (/u/kim/.ssh/id_rsa) 
然后,你就可以通过
  beowulf% ssh hrothgar
  kim@hrothgar% 
ssh登录而不需要密码了。

sed的in-place edit选项,和RTFM

, , ,

Debian Administration上看到Search and replace across many files with a perl one-liner这篇文章。多文件的Search and Replace的Linux风格处理方式,也是我一直思考的,这篇文章提供的是一个perl的解决方案。而对于这种问题,最直接想到的解决方案应该是sed吧?而且对于Perl,我到现在还是个门外汉。

不过一直以为sed不能直接对源文件修改,必须重定向到新文件,所以觉得在批量处理中很麻烦,因为每次都必须指定新文件名,然后在覆盖回源文件。为此还傻傻的专门写过一个runsed的shell脚本用于处理重定向到中间文件再覆盖回源文件的工作,让sed可以直接修改源文件,适用于批量处理。还沾沾自喜,以为找到了最终的解决方案。

在上面这篇文章中,比较关键的是用到了perl的 -i 参数edit the files in-place,直接修改源文件。这时候我想,sed也是应该有这么一个in-place edit的选项的,只是我以前没有找到罢了。于是man sed,然后在man page的32行就看到了

-i[SUFFIX], --in-place[=SUFFIX]
                edit files in place (makes backup if extension supplied)
这个参数。这时候才觉得自己好傻,没有好好的RTFM,而且还好好的自作聪明了一把。 sed的这个 -i[SUFFIX], –in-place[=SUFFIX] 参数功能还真的很强,除了能够直接修改源文件,还能自动备份源文件,指出备份文件的suffix,真是非常方便。(居家旅游,杀人灭口,必备良药?XD)又可以快乐的sed生活了。

现在,关于 Search and Replace 和 Regular Expression,还有一个问题困扰我,在这儿记下来。 就是将文件中符合某个pattern的字符串打印出来。注意,只是符合这个pattern的字符串本身,而不是所在行。直接一看,这怎么都是grep的工作嘛,可以在对grep狠狠的RTFM以后,还是未果。真是奇怪,总觉得打印搜索到的pattern本身,比打印行要容易的多嘛,怎么会这么难找?Python脚本自然可以很容易就实现,但是总觉得已有的shell工具肯定是有这样的功能了,只是我没找到罢了。希望有达人指点。(不要告诉我grep后sed哦~)

December 2009
S M T W T F S
November 2009January 2010
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31