软件真的好难做啊(转载)

2014年9月03日 00:02


转自http://coolshell.cn/articles/4811.html

软件真的好难做啊

2011年6月10日 陈皓 发表评论 阅读评论 3 次点击    
 

还记得以前本站的那一篇“编程好难啊”吗,那是一篇众程序员调侃程序新手的文章,有恶搞的成分在里面。今天要和大家说的这个事没有一些恶搞和调侃的意思,是比较严肃的话题,你一定可以从中收获一些东西。这个话题来自StackOverflow上的一个问题——Cycle in Family Tree Software,这个程序员问了下面这个问题:

我是一个写家族族谱软件的程序员(我用的是C++和Qt),这个软件基本上没有什么问题,真到有一天有个用户报告了一个bug。这个问题是这样的——我这个用户和他女儿生了两个孩子

于是,我程序员的一些断言和硬性条件导致程序报错,因为我的程序在处理这个关系的时候,其发现X即是Y的爸爸,又是Y的爷爷,所以只能报错。

请问,在不需要移除我的断言和数据验证的情况下,我怎么才能解决这个问题

看到这里,请重点阅读一下下面的两点:

  • 如果你看到这里开始兴奋了,请你为你阴暗的心理去面壁反省10分钟,因为这是一个很技术的问题。
  • 如果你开始陷入了深深的思考如何解决这个问题,那么你绝对是一个合格的程序员,因为你已陷入技术已经很深了,有点呆了。

我在前面说过,“这个是一个严肃的话题,你可以从中收获一些东西”,当然,我并不希望你来收获乱伦的知识和心得,酷壳是一个技术博客,应该是收获技术方面的东西。

 

从技术的角度上来说,这是我们经常在设计软件时犯的错误——

1)作了错误的假设(Assumption)

Assumption是软件设计的重大天敌,Assumption的动词Assume意为Ass u me – Ass you and me 。你的假设做得越多,你的设计就越不靠谱。这里的假设是——我们以为family tree是一个tree,其实并不是tree。Assumption是魔鬼

还有一些经典的Assumption如下所示

  • 最著名的就是那个y2k臭虫。
  • 不要以为没有2月30日,在瑞典1712年有2月30日
  • 一分钟有60秒?闰秒呢?
  • 双胞胎的生日是同一天吗?
  • 双胞胎的父亲是同一个?
  • 性别只有男和女?
  • 婚姻只能是异性? 关于这一点,推荐一篇强文——Gay marriage: the database engineering perspective (同性婚姻:数据库工程)

2)没有认真分析用户案例(Use Case)

在设计软件时,我们需要考虑各种各样的用户案例,比如如下的东西:

  • 私生子的问题
  • 一夫多妻或一妻多夫,同父异母,同母异父
  • 就算一夫多妻制违反法律,也会有离异再婚的情况
  • 同性恋的问题,虽然不能繁衍,但可以领养。
  • 换妻活动
  • 各种乱伦关系——这种东西那个民族都不少,尤其是古时候,比如:
    • 先后嫁了两个人其是父子关系(昭君)
    • 达尔文同学和他的表妹,爱因斯坦的二婚是和他的表姐,埃及艳后嫁了她的弟弟,……
    • 顺治同学娶了四个老婆,这四个人还是一家人:姑姑,侄女,妹妹,女儿。(参看这里
    • 刘邦同学的母后干出来的事,相当变态(参看这里
    • 中国古代的“扒灰老” (类似于楼主那个问题的Use Case)

不想再列下去了,人类真TMD恶心,有点要吐了

——————————为了缓解一下恶心的气氛,请允许我插入一个搞笑短文——————————

一位自杀者在他的遗书里讲述了他自杀的原因,听起来实在让人头痛。遗书这样写道:“我和一个寡妇结了婚,她有一个已成年的女儿,我父亲跟我妻子带过来的女 儿结了婚。所以我父亲就成了我的女婿,女儿就成了我的后母,我管父亲叫爸爸,而我父亲也管我叫爸爸;我女儿管我叫爸爸,但我却管她叫妈妈;我还得管我妻子 叫姥姥,因为她是我后母的母亲。不久我女儿,也就是我后母生了一个儿子,他是我同父异母的弟弟,他也得管我叫姥爷,因为他也是我的外孙。后来我妻子,也就 是我姥姥生了一个儿子,他是我后母的弟弟,我是他的外甥,所以儿子管我叫爸爸,我管儿子叫舅舅。另外我是我妻子,也就是我姥姥的外孙,同时也是我姥姥的丈 夫,所已我也是我的外祖父。又因为我妻子是我的外祖母,我的儿子,也就是我的舅舅是我的弟弟和我女儿的弟弟,所以我……我的天哪,这么复杂的关系实在让我 伤透了脑筋,我只有一死才能得以解脱……”

————————————————————————插入完毕————————————————————

看完上面这个短文,不知道你是否和我一样,觉得这么一个简单的程序将是如此难做啊。另外,我决定在下一次的面试中让应聘者来设计Family Tree的程序

我又说多了,现在还是让我们回到技术上来。除了上面那几个观点,我在回复中还看到了如入一些有意思的回复:

  • “我的软件没有bug,是你的生活有bug”——让我想到了程序员惯用的借口
  • “算法中不应该加太多的限制,限制多了反而让算法不灵活。”
  • “移除断言,并不代表就不出错,对于这种rare case,我们最好给一个Warning提醒用户,让用户确认确实是这样的。”
  • “关于解决这个问题,移除那个断言,如果显示上会有问题的话,那就复制一下有不同关系的人就可以了”
  • “你真的应该想想你的软件的价值是什么?市场在哪里?你真的要照顾这样的用户吗?”

挺好的,相信你对软件开发又学到了一些东西。

倍受打击

2014年9月03日 00:02

tubo posted @ 2011年6月15日 19:39 in 未分类 , 0 阅读

倍受打击

看看人家的 Blog , 想想人家从中体现的水平,再看看自己的。

受打击呀。

不过, 知耻而后勇,以后还要继续努力,拓展知识面。

不过,我更想探索,怎样把上学期间学到的各种算法和公式慢慢的用程序表现出来?

伟大的数学。

彷徨着彷徨,迷惘着迷惘

2014年9月03日 00:02

现在的状态。

不要在功能上竞争(转载)

2014年9月03日 00:02

作者: 阮一峰

日期: 2011年7月14日

苹果公司的电子产品,最大的特点就是它的易用性(usability)----简单,美观,容易上手。

它们通常不是功能最强大的,但往往是最好用的。下图的左边是Mac,右边是PC,你觉得看上去哪个更好用?

不要在功能上竞争(转载) - vic_kk - Live and Learn

很多产品经理都想模仿这些特点。但是,一个难题就会随之而来:

很难让一件产品保持简单,同时还具备大量的新功能。

如果你不断为产品添加新功能,在变得强大的同时,它还会变得越来越复杂,增加了用户的使用难度;如果你大力简化产品,在功能上比较单一,那么怎样与竞争对手抗衡呢?

每个产品经理都会面对这个难题。对于新产品,这个问题尤其重要。因为新产品通常很难打开市场,最容易想到的解决办法就是为它不断增加功能,直到引起市场注意为止。但是,这样做是否正确呢?

不要在功能上竞争(转载) - vic_kk - Live and Learn

我对这个问题,一直很困惑,不知道开发新产品的时候,哪一个取向优先,多功能还是易用性?

昨天,我读到了硅谷产品经理Andrew Chen的文章,顿时醍醐灌顶,一下子就找到了答案。

他说,正确的做法,就是不要在功能上竞争。如果你的产品的核心概念行不通,那就重新定位这个产品,而不是为它添加新功能。你必须牢记在心,创造一个有竞争力的新产品,不要着眼于它的功能比别人多,而要着眼于它有一个截然不同的市场定位。

如果市场上都是复杂的企业级工具,那就开发一个针对个人用户的简化版;如果市场上都是很正式的高端葡萄酒,那就开发一种便宜的、针对年轻人的、更休闲的酒精饮料;如果市场上都是提供长篇Blog服务的网站,那就开发一个很简单的、每次只能写140个字的网站;如果市场上都是技术性的、廉价的电子设备,那就开发人性化的、高价的电子设备。

不要在功能上竞争(转载) - vic_kk - Live and Learn

总之,你要做的不是添加功能,而是做一个市场定位不同的产品。

这主要有两个原因:

首先,你不太可能通过一个更多功能的新产品,战胜现有厂商。因为你开发出全面胜过别人的产品,需要很多时间;而且,等你开发出新功能,别人可能又做出了改进,或者拷贝了你的新功能。

其次,比起新功能,消费者更容易为一个特殊定位的产品掏钱。

所以,更好的策略是,开发一个简化的产品,突出某种不同的市场定位,争夺现有厂商的低端用户。这样的话,你不用开发一个全功能的产品,节省了时间,而且由于设计目标不同,更容易做出颠覆式创新(disruptive innovation)。

下面是开发新产品时,几点可行的做法:

  (1)你不是做一个比竞争对手"更好"的产品,而是做一个"不同"的产品。

  (2)你只提供部分功能,但是很好地满足了用户的需求。

  (3)如果新产品的市场反响不好,增加新功能并不能解决问题。你应该重新定位你的产品,想想它能向消费者提供哪些不同的价值。

  (4)在产品设计和推广的每一个环节,都突出它的不同定位。

不要在功能上竞争(转载) - vic_kk - Live and Learn

(完)

文档信息



http://shhuanyayq.blog.163.com/blog/static/9754761420099771617709/


前几天为了和一个名师联系,但是由于台湾的yahoo博客被封了,于是就下了一个tor穿墙。用的正欢,昨天开始,tor就连不上了。现在的GFW还是很厉害的,封的很死,加上现在IP代理发布站都被和谐掉,几个翻墙浏览器也被喀嚓。心里咯噔一下,难道这下没辙了。

网上搜了一下,还是有人有办法的。

tor提供一个网桥中继功能。

可以通过访问 https://bridges.torproject.org/来获取网桥地址。

也可以给 bridges@torproject.org 发邮件,邮件正文为 “getbridges”,立即会收到自动回信。

得到如下信息

Here are your bridge relays:

bridge 67.166.252.156:9001 50190e89af98e18a79828006680748

af5c946a84
bridge 75.190.175.8:443ea20adbc86c91ae4e067289bb5a649ccac297596
bridge 218.189.200.130:4439c88ed76dfb3d42ce98047219e190aad4c970d8a4

然后按图设置,后面的key不需要填写。只要IP和端口即可。
连不上tor的解决方法(综合) - 自由职业者 - 自由职业者的博客

这样设置好,就可以翻墙了。如果地址被封,就再去获取网桥地址了。


Tor被封的解决方法 / 搞笑

2009-09-26 10:47 |阅读(1979) | 标签:科技新知| 字号:  

原载:http://www.my1510.cn/article.php?id=31f729a4cadb7caf

 

今天上网用Tor,发现无法连接。心想难道我疑惑的问题,GFW没两天就给出答案啦——前两天在想,依据技术圈最近流传的宏文《GFW的前世今生》,Tor是很容易封的,客户端启动连接Tor网络的阶段尤其脆弱,为什么大庆当前,GFW还没动静呢?

既然来了,咱们就得想办法,网上搜索加上不断的测试,得到一些经验,供大家参考。

方法一:是设置用网桥,很多网页上有介绍(http://tor.zuo.la/bridges.html.zh-cn),具体方法就不多说了。只说我用的过程,用了十个左右的网桥地址,都是从官方最新获取的,结果每次启动后三十多分钟bootstrapping依然停留在 5%,简单说就是设置网桥没效果。在自己摸索出方法二之后,去Twitter上搜索了一下,发现了某同学说的设置网桥不成功的原因——就是填写网桥配置时 只能写IP地址和端口,后面的Key一定不要写。笔者经过后经过多次正反试验确认了这一点,只要设置时填写网桥的格式正确,就可以连上Tor网络

方法二:是设置代理,首先通过普通网络搜索或者代理网站获得一个可用的HTTP代理,最好是海外的。验证可用后,在Vidalia中设置使用代理访问互联 网。一旦成功连接上Tor网络后,可以在设置中把代理去掉,再次重新启动Tor,这样没有经过代理,访问速度会快一点。以后使用Tor也应该是正常的。

至于其中的原因,我初步猜想:GFW采用了类似IP层特征码识别的检测方法,来阻断Tor客户端连接Tor网络。我们在设置中加上代理,就改变了发送到网络上的数据包及其特征码,因而能躲过了GFW的检测,也就避免了其对Tor连接的攻击。至于连上Tor网络之后就无需再用代理,应该是因为连上一次Tor 网络后,Tor软件就在本地存放了一些Tor网络的节点信息,可供下次连接使用。

经过分析对比,目前笔者已经找到了Tor节点信息的文件位置是“C:\Documents and Settings\Administrator\ApplicationData\Tor\”(其中C是系统盘,Administrator是用户名,具体到个人的机器会有不同),共有三个文件保存节点相关信息,cached-certscached-consensuscached-descriptors,保存这三个文件以备不时之需,应该也是有作用的。

 

Tor有关Bridge relays的建议与配置方案

04 5th, 2008 by MikeZhang

原载:http://logmike.com/?p=232

 

今天偶然间看到网上Andrew的一文大声疾呼:请中国的Tor中继服务提供者仅把自己设置为”中间人””后,深有感触。虽然实际使用中我并没有发现国内torrelay服务器被出用最终出口的情况,但只要是公开的relay服务器肯定有可能被利用来做最终出 口。如果最终出口在大--网络中的话,的确就失去意义了。虽然可能不会被找到访问者,但多少也有可能为torrelay服务运行者带来多多少少地麻 烦。所以在大--网络中设置仅以Bridgerelays模式运行torrelay看来是十分有必要的。

Win版的Tor设置Bridge relays方式为:
设定->中继->Tor 网络中继->服务策略->清除所有的选择(也就是一个也别选中)->保存

Linux版的Tor设置Bridge relays的方式稍复杂点,我试了一下,具体设置如下:
# vi /usr/local/etc/tor/torrc

在原来的ORPort设置的最后面,把此设置打开:
ExitPolicy reject *:*
即不允许原来的tor relay任何服务作出口,由于我还要运行着tor的匿名网站,故此断的relay其它设置还要保留着。

然后在此配置文件的最后面,把BridgeRelay的相关配置的前三行enable
ORPort 443
BridgeRelay 1
RelayBandwidthRate 500KBytes
#ExitPolicy reject *:*

保存后重启tor的服务即可。

如果你把debuglog打开,应该可以看到都是一些类似如下的日志记录:
Apr 05 11:44:23.939 [debug] directory_handle_command_get():rewritten url as‘/tor/server/d/0E1353F11009ECEA964B01930………………………………..(
太长了,中间省略)………………….z’.
Apr 05 11:44:23.939 [debug] conn_write_callback(): socket 19 wantsto write.
Apr 05 11:44:23.939 [debug] connection_dir_finished_flushing():Finished writing server response. Closing.
Apr 05 11:44:23.939 [debug] conn_close_if_marked(): Cleaning upconnection (fd 19).
Apr 05 11:44:23.939 [debug] connection_remove(): removing socket 19(type Directory), n_conns now 12
Apr 05 11:44:23.939 [debug] _connection_free(): closing fd19.
Apr 05 11:44:24.034 [debug] conn_read_callback(): socket 8 wants toread.
Apr 05 11:44:24.034 [debug] connection_handle_listener_read():Connection accepted on socket 19 (child of fd 8).
Apr 05 11:44:24.034 [debug] connection_add(): new conn typeDirectory, socket 19, n_conns 12.
Apr 05 11:44:24.166 [debug] conn_read_callback(): socket 19 wantsto read.
Apr 05 11:44:24.166 [debug] read_to_chunk(): Read 1448 bytes. 1448on inbuf.
Apr 05 11:44:24.166 [debug] fetch_from_buf_http(): headers not allhere yet.
Apr 05 11:44:24.166 [debug] directory_handle_command(): command notall here yet.
Apr 05 11:44:24.181 [debug] global_read_bucket now 10485760.
Apr 05 11:44:24.181 [debug] global_write_bucket now 10485760.
Apr 05 11:44:24.181 [debug] global_relayed_read_bucket now2048000.
Apr 05 11:44:24.181 [debug] global_relayed_write_bucket now2048000.
Apr 05 11:44:24.181 [debug] or_conn->read_bucket now10485760.
Apr 05 11:44:24.181 [debug] or_conn->read_bucket now10485760.
Apr 05 11:44:24.181 [debug] circuit_is_acceptable(): Skippingone-hop circuit.
Apr 05 11:44:24.181 [debug] circuit_is_acceptable(): Skippingone-hop circuit.
Apr 05 11:44:24.181 [debug] circuit_get_open_circ_or_launch(): oneon the way!
Apr 05 11:44:24.378 [debug] conn_read_callback(): socket 20 wantsto read.
Apr 05 11:44:24.378 [debug] connection_read_to_buf(): 20: starting,inbuf_datalen 0 (0 pending in tls object). at_most 16384.
Apr 05 11:44:24.379 [debug] connection_read_to_buf(): After TLSread of 1024: 1098 read, 0 written
Apr 05 11:44:24.379 [debug]connection_or_process_cells_from_inbuf(): 20: starting,inbuf_datalen 1024 (0 pending in tls object).

这些log和之前非仅仅是bridgerelays的模式的日志是完全不一样的。

同时在我把torrelay设置成bridgerelays运行后,再检测原来设置在此之上的“http://o2ykh5czcfujbqty.onion/”tor匿名网站也是正常的。

这样就一切ok设置好了。

关于Bridgerelays在配置文件里有如下一段说明:
## Bridge relays (or “bridges” ) are Tor relays that aren’t listedin the
## main directory. Since there is no complete public list of them,even if an
## ISP is filtering connections to all the known Tor relays, theyprobably
## won’t be able to block all the bridges. Unlike running an exitrelay,
## running a bridge relay just passes data to and from the Tornetwork –
## so it shouldn’t expose the operator to abusecomplaints.

主要意思就是说以Bridgerelays模式运行后,你的torrelay服务器就不会在公开的relay目录里显示出来了,这样可以防止被当地ISP根据公开的relay目录来block,当然你也只能作一个幕后英雄了。:-)不过此种情况实在太适合我们目前的情况了,我把我的tor relay服务器调整成这种模式后,所以我也宁可当一个幕后英雄。

非常感谢Andrew在其blog上的文章给我的启发。

 


/etc/hosts 备份

2014年9月03日 00:01

# /etc/hosts: Local Host Database
#
# This file describes a number of aliases-to-address mappings for the for
# local hosts that share this file.
#
# In the presence of the domain name service or NIS, this file may not be
# consulted at all; see /etc/host.conf for the resolution order.
#

# IPv4 and IPv6 localhost aliases
127.0.0.1 localhost
::1 localhost

#
# Imaginary network.
#10.0.0.2 myname
#10.0.0.3 myfriend
#
# According to RFC 1918, you can use the following IP networks for private
# nets which will never be connected to the Internet:
#
# 10.0.0.0 - 10.255.255.255
# 172.16.0.0 - 172.31.255.255
# 192.168.0.0 - 192.168.255.255
#
# In case you want to be able to connect directly to the Internet (i.e. not
# behind a NAT, ADSL router, etc...), you need real official assigned
# numbers. Do not try to invent your own network numbers but instead get one
# from your network provider (if any) or from your regional registry (ARIN,
# APNIC, LACNIC, RIPE NCC, or AfriNIC.)
#
203.208.46.30 www.google.com
203.208.46.30 picasaweb.google.com

203.208.46.30 lh1.ggpht.com
203.208.46.30 lh2.ggpht.com
203.208.46.30 lh3.ggpht.com
203.208.46.30 lh4.ggpht.com
203.208.46.30 lh5.ggpht.com
203.208.46.30 lh6.ggpht.com
203.208.46.30 lh6.googleusercontent.com
203.208.46.30 lh5.googleusercontent.com
203.208.46.30 lh4.googleusercontent.com
203.208.46.30 lh3.googleusercontent.com
203.208.46.30 lh2.googleusercontent.com
203.208.46.30 lh1.googleusercontent.com
203.208.46.30 images1-focus-opensocial.googleusercontent.com
203.208.46.30 images2-focus-opensocial.googleusercontent.com
203.208.46.30 images3-focus-opensocial.googleusercontent.com
203.208.46.30 images4-focus-opensocial.googleusercontent.com
203.208.46.30 images5-focus-opensocial.googleusercontent.com
203.208.46.30 images6-focus-opensocial.googleusercontent.com
203.208.46.30 s6.googleusercontent.com
203.208.46.30 s5.googleusercontent.com
203.208.46.30 s4.googleusercontent.com
203.208.46.30 s3.googleusercontent.com
203.208.46.30 s2.googleusercontent.com
203.208.46.30 s1.googleusercontent.com

203.208.46.30 plus.google.com
203.208.46.30 talkgadget.google.com
203.208.46.30 ditu.google.com
203.208.46.30 maps-api-ssl.google.com
203.208.46.30 mail.google.com
203.208.46.30 docs.google.com
203.208.46.30 scholar.l.google.com
203.208.46.30 news.google.com
203.208.46.30 video.google.com
203.208.46.29 translate.google.com

203.208.46.30 profiles.google.com

autocomplete-mode + flyspell-mode

2014年9月03日 00:01

简介:
A known bug in Autocomplete-mode
转载请注明出处


今天发现,在 enable 了 flyspell-mode 以后,autocomplete 不能正常工作了, 查了一下,发现是 autocomplete 的一个 known issue.
下面的内容摘自: , 描述了这一问题,并给出了解决方法:

11.1. Auto completion will not be started in a buffer flyspell-mode enabled

A way of delaying processes of flyspell-mode disables auto completion. You can avoid this problem by M-x ac-flyspell-workaround. You can write the following code into your ~/.emacs.

(ac-flyspell-workaround) 


Author:yangyingchao, 2011-07-26

简介:
Solution of how to disable Cache in Chromimum browser.
转载请注明出处


There's an option which does not appear in chromium's manual page --- "-disk-cache-dir".
This option specifies where the disk cache should be stored.
Hence, under Linux, we can set the disk-cache-dir to /dev/null. In that way, the cache will be disabled, and all contents will be read from the Internet directly.

Here is what the modified chromium-browser-chromium.desktop looks like:

[Desktop  Entry] 
Name=Chromium Type=Application 
Comment=Open-source version of Google Chrome web  browser 
Exec=chromium-browser %U --disk-cache-dir=/dev/null 2>/dev/null 
TryExec=chromium-browser 
Icon=chromium-browser
Categories=Network;WebBrowser; 
MimeType=text/html;text/xml;application/xhtml+xml;x-scheme-handler/http;x-scheme-handler/https;   



Why I need to disable file cache?
Well, on my machine, when chromium browser starts up, it keeps reading cache and take a long time to show the homepage.
So I decided to disable it.



Author:yangyingchao, 2011-07-30

stardict 字典下载

2014年9月03日 00:01

刚刚发现, sourceforge  上的字典都被 Remove 了,找了一下,发现这里还有一些存货,不容易……

http://debian.ustc.edu.cn/debian-uo/dists/sid/ustc/pool/stardict/


简介: 转载的文章,里面介绍的技巧用的好的话可以提高工作效率,而且有几条很实用,比如 record screen, ssh-copy-id 等等。
转载请注明出处


#1. Run the last command as root

$ sudo !!

We all know what the sudo command does - it runs the command as another user, in this case, it runs the command as superuser because no other user was specified. But what's really interesting is the bang-bang !! part of the command. It's called the event designator. An event designator references a command in shell's history. In this case the event designator references the previous command. Writing !! is the same as writing !-1. The -1 refers to the last command. You can generalize it, and write !-n to refer to the n-th previous command. To view all your previous commands, type history.

This one-liner is actually really bash-specific, as event designators are a feature of bash.

I wrote about event designators in much more detail in my article "The Definitive Guide to Bash Command Line History." The article also comes with a printable cheat sheet for working with the history.

#2. Serve the current directory at http://localhost:8000/

$ python -m SimpleHTTPServer

This one-liner starts a dedicated server hosting (web server) on port 8000 with the contents of current directory on all the interfaces (address 0.0.0.0), not just localhost. If you have "index.html" or "index.htm" files, it will serve those, otherwise it will list the contents of the currently working directory.

It works because python comes with a standard module called SimpleHTTPServer. The -m argument makes python to search for a module named SimpleHTTPServer.py in all the possible system locations (listed in sys.path and $PYTHONPATH shell variable). Once found, it executes it as a script. If you look at the source code of this module, you'll find that this module tests if it's run as a script if __name__ == '__main__', and if it is, it runs the test() method that makes it run a web server in the current directory.

To use a different port, specify it as the next argument:

$ python -m SimpleHTTPServer 8080

This command runs a HTTP server on all local interfaces on port 8080.

If you're looking for hosting your website, check out webhosting.

#3. Save a file you edited in vim without the needed permissions

:w !sudo tee %

This happens to me way too often. I open a system config file in vim and edit it just to find out that I don't have permissions to save it. This one-liner saves the day. Instead of writing the while to a temporary file :w /tmp/foobar and then moving the temporary file to the right destination mv /tmp/foobar /etc/service.conf, you now just type the one-liner above in vim and it will save the file.

Here is how it works, if you look at the vim documentation (by typing :he :w in vim), you'll find the reference to the command :w !{cmd} that says that vim runs {cmd} and passes it the contents of the file as standard input. In this one-liner the {cmd} part is the sudo tee % command. It runs tee % as superuser. But wait, what is %? Well, it's a read-only register in vim that contains the filename of the current file! Therefore the command that vim executes becomes tee current_filename, with the current directory being whatever the current_file is in. Now what does tee do? The tee command takes standard input and write it to a file! Rephrasing, it takes the contents of the file edited in vim, and writes it to the file (while being root)! All done!

Blue host and Hostgator are considered best web host in hosting industry.

#4. Change to the previous working directory

$ cd -

Everyone knows this, right? The dash "-" is short for "previous working directory." The previous working directory is defined by $OLDPWD shell variable. After you use the cd command, it sets the $OLDPWD environment variable, and then, if you type the short version cd -, it effectively becomes cd $OLDPWD and changes to the previous directory.

To change to a directory named "-", you have to either cd to the parent directory and then do cd ./- or do cd /full/path/to/-.

#5. Run the previous shell command but replace string "foo" with "bar"

$ ^foo^bar^

This is another event designator. This one is for quick substitution. It replaces foo with bar and repeats the last command. It's actually a shortcut for !!:s/foo/bar/. This one-liner applies the s modifier to the !! event designator. As we learned from one-liner #1, the !! event designator stands for the previous command. Now the s modifier stands for substitute (greetings to sed) and it substitutes the first word with the second word.

Note that this one-liner replaces just the first word in the previous command. To replace all words, add the g modifer (g for global):

$ !!:gs/foo/bar

This one-liner is also bash-specific, as event designators are a feature of bash.

Again, see my article "The Definitive Guide to Bash Command Line History." I explain all this stuff in great detail.

#6. Quickly backup or copy a file

$ cp filename{,.bak}

This one-liner copies the file named filename to a file named filename.bak. Here is how it works. It uses brace expansion to construct a list of arguments for the cp command. Brace expansion is a mechanism by which arbitrary strings may be generated. In this one-liner filename{,.bak} gets brace expanded to filename filename.bak and puts in place of the brace expression. The command becomes cp filename filename.bak and file gets copied.

Talking more about brace expansion, you can do all kinds of combinatorics with it. Here is a fun application:

$ echo {a,b,c}{a,b,c}{a,b,c}

It generates all the possible strings 3-letter from the set {a, b, c}:

aaa aab aac aba abb abc aca acb acc baa bab bac bba bbb bbc bca bcb bcc caa cab cac cba cbb cbc cca ccb ccc 

And here is how to generate all the possible 2-letter strings from the set of {a, b, c}:

$ echo {a,b,c}{a,b,c} 

It produces:

aa ab ac ba bb bc ca cb cc 

If you liked this, you may also like my article where I defined a bunch of set operations (such as intersection, union, symmetry, powerset, etc) by using just shell commands. The article is called "Set Operations in the Unix Shell." (And since I have sets in the shell, I will soon write articles on on "Combinatorics in the Shell" and "Algebra in the Shell". Fun topics to explore. Perhaps even "Topology in the Shell" :))

#7. mtr - traceroute and ping combined

$ mtr google.com

MTR, bettern known as "Matt's Traceroute" combines both traceroute and ping command. After each successful hop, it sends a ping request to the found machine, this way it produces output of both traceroute and ping to better understand the quality of link. If it finds out a packet took an alternative route, it displays it, and by default it keeps updating the statistics so you knew what was going on in real time.

#8. Find the last command that begins with "whatever," but avoid running it

$ !whatever:p

Another use of event designators. The !whatever designator searches the shell history for the most recently executed command that starts with whatever. But instead of executing it, it prints it. The :p modifier makes it print instead of executing.

This one-liner is bash-specific, as event designators are a feature of bash.

Once again, see my article "The Definitive Guide to Bash Command Line History." I explain all this stuff in great detail.

#9. Copy your public-key to remote-machine for public-key authentication

$ ssh-copy-id remote-machine

This one-liner copies your public-key, that you generated with ssh-keygen (either SSHv1 file identity.pub or SSHv2 file id_rsa.pub) to the remote-machine and places it in ~/.ssh/authorized_keys file. This ensures that the next time you try to log into that machine, public-key authentication (commonly referred to as "passwordless authentication.") will be used instead of the regular password authentication.

If you wished to do it yourself, you'd have to take the following steps:

your-machine$ scp ~/.ssh/identity.pub remote-machine: your-machine$ ssh remote-machine remote-machine$ cat identity.pub >> ~/.ssh/authorized_keys 

This one-liner saves a great deal of typing. Actually I just found out that there was a shorter way to do it:

your-machine$ ssh remote-machine 'cat >> .ssh/authorized_keys' < .ssh/identity.pub 

#10. Capture video of a linux desktop

$ ffmpeg -f x11grab -s wxga -r 25 -i :0.0 -sameq /tmp/out.mpg

A pure coincidence, I have done so much video processing with ffmpeg that I know what most of this command does without looking much in the manual.

The ffmpeg generally can be descibed as a command that takes a bunch of options and the last option is the output file. In this case the options are -f x11grab -s wxga -r 25 -i :0.0 -sameq and the output file is /tmp/out.mpg.

Here is what the options mean:

  • -f x11grab makes ffmpeg to set the input video format as x11grab. The X11 framebuffer has a specific format it presents data in and it makes ffmpeg to decode it correctly.
  • -s wxga makes ffmpeg to set the size of the video to wxga which is shortcut for 1366x768. This is a strange resolution to use, I'd just write -s 800x600.
  • -r 25 sets the framerate of the video to 25fps.
  • -i :0.0 sets the video input file to X11 display 0.0 at localhost.
  • -sameq preserves the quality of input stream. It's best to preserve the quality and post-process it later.

You can also specify ffmpeg to grab display from another x-server by changing the -i :0.0 to -i host:0.0.

If you're interested in ffmpeg, here are my other articles on ffmpeg that I wrote while ago:

PS. This article was so fun to write, that I decided to write several more parts. Tune in the next time for "The Next Top Ten One-Liners from CommandLineFu Explained" :)

Have fun. See ya!


http://www.catonmat.net/blog/top-ten-one-liners-from-commandlinefu-explained/