码农
IDE,集成式开发环境。在计算机软件世界里的的中世纪,「集成」这个词与现在的「云计算」、「大数据」、「深度学习」之类的词一样流行。
刚开始写程序的时候,我用的 IDE 是 VC++,后来到了 .net 时代,它也就进化成了 VC++.net。在我还没来得及搞明白 .net 到底是什么的时候,就自甘堕落步入了 Linux 世界。从那时起,我就一直使用终端、Emacs、gcc 之类刀耕火种式的工具写程序。
许多程序员自称码农,其实他们不是。在我心目中,他们用着功能完备、界面华丽、体积庞大的 IDE,更像是在操作 DMG 五轴联动数控机床的工人,他们穿着干净的深蓝色工装,双手干净,指甲修长,眼睛里闪跃着高科技的光芒。
农民与工人,原本就不是一个阶级。这样的农民与这样的工人,就更不是一个阶级了。在我认识的这个现实世界里,没有农民不希望自己能成为工人,没有工人希望沦落为农民。就跟城市与农村有城乡结合部一样,农民与工人也能结合,他们叫农民工,简称民工。也有一些农民与科学家结合了起来,简称民科。与军人结合一下,就叫民兵……
我是落后生产力的代言人
自甘堕落,就意味着落后。在我能掌控的这方寸之地,我以很落后的方式兼任了 C[A-Z]O。所以,我肯定是落后生产力的代言人。
这段时间的每一天,进入工作状态之后,我会打开三个终端窗口,姑且分别称它们为 X、Y、Z。它们的工作目录分别是文式编程的源文档目录、对他人开放的静态站点目录、程序源码目录。接下来,我在 X 中打开一份文式编程元文档,然后文档与代码齐飞,写作与编程一色。当觉得差不多又增加了一个小功能之后,我要把它们展示给别人看,就需要进入 Y 窗口,执行一条命令,进行文件同步与文档格式化处理。我要测试一下代码的正确性,就需要进入 Z 窗口,执行一组命令,进行文件同步、程序源码提取、编译、连接之类的处理。就这样,整整一天就在这三个终端窗口中来回切换。
再具体一些, X 与 Z 用的是我日常登录的用户身份,Y 窗口用的则是一个供其他人方便访问我机器而特设的一个用户身份。
我在 X 窗口中用 Emacs 打开一份文式编程的源文档:
$ emacs agn_sample.orz
那种感觉就像 80 年代坐办公室的人,沏了一壶茶,然后坐下来开启让自己最舒适的半瘫痪模式悠哉悠哉拿起了一张报纸……
这「报纸」看的差不多了,就放下来,对自己说,干活!
$ make
然后,就进入 Y 窗口,执行一个自己写的脚本:
$ ./sync.sh
这个脚本的内容如下:
#/bin/sh AGN_SITE=/home/garfileo/var/nikola/agn-project for i in conf.py images files mycss MathJax posts stories do rsync -avh --delete $AGN_SITE/$i ./ done rsync -avh --exclude-from="exclude.list" --delete $AGN_SITE/Meta-doc ./ source /home/garfileo/var/python/bin/activate nikola build
看不明白不要紧。无非就是一些庆贺十九大胜利闭幕,全面深化改革,合作共赢,加强环境治理力度之类的专业词汇。
这样,身边的人可以通过一个叫做 http://192.168.3.7:8080
的地址看到我更新过的文档与代码了。
文档内容有错误不太要紧,因为人人的脑子里都有一个基于进化算法、深度学习、特征识别等等先进的启发式优化算法武装了几十年的编译器。代码不能出错,机器就是机器,尽管现代人都吆喝机器学习……我得进入 Z 窗口,把代码编译好,然后在想办法测试一下。在 Z 窗口里,我要敲入:
$ make update-orez ; make ; sudo make install
剩下的事情,就都是一些琐碎的小事了,不一而足。大部分时候,我会到 /tmp 目录,随手写几个小程序测试一下。我知道怎么做单元测试,但是身为码农,是不需要这些的。你见过哪个农民去验证过自己每年播种的庄稼的正确性?
我是个很勤奋的人,像一名真正的农民那样。我在 X、Y、Z 这三亩地中来回切换的生活已经断断续续持续了一年多了。我用的这些工具,基本上都是黑乎乎的。黑乎乎的 orez,黑乎乎的 rsync,黑乎乎的 nikola,黑乎乎的 make,黑乎乎的 bash,只有 Emacs 翻着灰白的死死鱼眼。每当我开启此等自嘲模式时,就会想起年少时听过的 Beyond 的一首歌,忘掉远方是否还有出路,忘掉夜里月黑风高,踏雪过山,双脚渐老……
农业现代化,心向往之
终于有一天,我有些腻烦了在三个窗口之间换来换去,尽管这种切换我只需要 Ctrl + PageUp 与 Ctrl + PageDown 这两个组合键就可以做到,并不比 IDE 里点菜单或按钮更麻烦。在各种乎、各种错误的网站以及各种自媒体宣扬的高手在民间的段子以及一锅又一锅浓浓的鸡汤的蛊惑下,我错误地认为自己不应该继续活在自己的舒适区,应该在通往高手的方向前进,应该响应党的号召,在去产能中转型升级。
于是,在一个深秋的下午,我在一些不知道名字的树下深沉的思考。簌簌的落叶像 Matrix 里一串串的字符一样落下。打 5000 斤粮食,我真的需要耕种三亩地吗?只用一亩地行不行?为了打 5000 斤粮食,我真的需要亲力亲为,娴熟地使用或驾驭铁锹、镰刀、锄头、铧犁、平板车和牛吗?有没有「太上老君急急如律令~敕」之类的咒语可以让一切像程序一样的运转起来?
先试试整合 X 与 Y 窗口里的事。之所以要开辟 Y 窗口,是因为我要在 Y 窗口里将身份切换为一个名叫 share
的用户,然后造进入工作目录:
$ su share Password: 123 $ cd ~/agn-project
一旦切换成这个用户,我就可以像上面所说的那样,随时都可以执行一些文件的同步与文档格式化处理:
$ ./sync.sh
用 Bash 脚本将这些命令合并起来并不难,把一组命令一行一行的摞起来,扔到一个 Bash 脚本里就可以了。伟大的 Windows 系统将这种行为称为批处理。困难之处在于,在 Bash 脚本如何进行用户身份的切换?
老王
在 Bash 脚本将一个需要人参与交互的命令变成一个命令与另一个命令的交互,这与让一个程序去「点击」一个图形界面程序的菜单或按钮一样困难。此事若用我们农民的朴实的语言来讲,就是创造一个能让自己放心的「老王」的人,让他代替自己去开自家的门。
就像世间已经存在许多老王一样,我们也没必要自己去创造这个「老王」。在 Linux 的世界里,有一个叫做 expect 的程序,是用古老的 TCL 语言编写的。这个 TCL 语言,不是那个 TCL 公司发明的,它们其实没关系。但是,在「老王」这个中文词汇的撮合下,它们不得不发生了关系。
我告诉 expect,让它去按照下面的命令行事:
#!/bin/env expect set timeout 60 spawn su share expect "Password: " send "123\r" expect "$ " send "cd ~/agn-project\r" expect "$ " send "./sync.sh\r"
所谓 expect,实际上它就是一个细作,在指定的时间里认真探听终端里发生的事。我们告诉它,一旦它探听有人说 Password:
,就大声回答 123\r
。必须得有 \r
,它的意思……朴素地说,就是「完毕」。它还可以探听 $
,这是终端的命令提示符。当它探听到这个的时候,我们就让它大声说一条 Bash 命令。这些命令在上文中都已经出现了,若你还没搞清楚,那你得向老王学习。
上述的 expect 所执行的那些命令放到一个文件里,这样就有了 expect 脚本。不妨将这份脚本取名为 push,并将它放在一个名为 scripts 的目录内。若让 expect 去执行这个脚本,只需:
$ expect scripts/push
在老王的协助下,X 窗口与 Y 窗口里发生的事就可以整成一件事了,如下:
#!/bin/bash make expect scripts/push
用类似的办法,也可以继续合并 Z 窗口里的事。这个就当作课后作业吧。
这几年,这个国家的成年男性,大部分人希望自己是老王,但又在提防别的老王。这在互联网上已经是众所周知的事情了。push 脚本里有一把钥匙,它的名字叫 123
。把钥匙交给老王的时候,一定要记住,只允许他在你的监视之下使用这把钥匙:
$ chmod 700 push $ ls -l push -rwx------ 1 garfileo garfileo 150 Nov 1 15:31 push
传密码的管道
在消除 Bash 脚本中命令交互中人的存在这方面,expect 是一种通用的办法。但是,有些命令支持通过管道传入密码,例如 sudo
。对于我要解决的问题而言,expect 能做的事,用 sudo
会更简单。即
$ expect script/push
能做到的事,可以用以下这两条命令代替:
$ cd /home/share/agn-project $ echo "sudo 的密码" | sudo -S -u share ./sync.sh
其中的原理是利用 sudo 所支持的密码管道(-S
选项),用 echo
命令将密码传递给 sudo
。只不过,这里传递的是 sudo 的密码,并非 share 帐号的密码。上面的 sudo 命令的意思是,将当前用户的身份切换为超级用户,然后再以超级用户的身份冒充 share 用户。
需要注意的是,若在 Bash 脚本里使用这样的 sudo 命令,依然要记得,像防老王那样保护你的密码。
现代化农业依然是农业
最后,我将 X、Y、Z 这三个窗口里的事合并为一份名为 distribute 的 Bash 脚本:
#!/bin/bash make expect scripts/push cd ~/var/tmp/agn make update-orez && make echo "sudo 密码" | sudo -S make install
这样一来,每天我只需要在一个窗口里敲入:
$ ./distribute
就可以让铁锹、镰刀、锄头、铧犁、平板车和牛们在黑漆漆的 Bash 里形成了一条现代化的农业工作流。
这样做,改变了什么?一切都没有变。黑乎乎的工具依然是黑乎乎的,翻着死鱼眼睛的 Emacs 依然在那里翻着死鱼眼睛。那些身穿深蓝色工装操作着 DMG 五轴联动数控机床的工人师傅说,农业的产能实在是太低了,你看你整的这么繁琐,在我们这里就是摁个按钮就了结了,所以不如把你们的地让出来给我们建工厂。