码农,码农

码农

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 五轴联动数控机床的工人师傅说,农业的产能实在是太低了,你看你整的这么繁琐,在我们这里就是摁个按钮就了结了,所以不如把你们的地让出来给我们建工厂。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


用的openwrt路由器,家里宽带申请了动态公网ip,为了方便把2280端口映射到公网,发现经常被暴力破解,自己写了个临时封禁ip功能的脚本,实现5分钟内同一个ip登录密码错误10次就封禁这个ip5分钟,并且进行邮件通知使用步骤openwrt为19.07.03版本,其他版本没有测试过安装bashmsmtpopkg
#!/bin/bashcommand1&command2&wait从Shell脚本并行运行多个程序–杨河老李(kviccn.github.io)
1.先查出MAMP下面集成的PHP版本cd/Applications/MAMP/bin/phpls-ls 2.编辑修改.bash_profile文件(没有.bash_profile文件的情况下回自动创建)sudovim~/.bash_profile在文件的最后输入以下信息,然后保存退出exportPATH="/Applications/MAMP/bin/php/php7.2.20/b
1、先输入locale-a,查看一下现在已安装的语言2、若不存在如zh_CN之类的语言包,进行中文语言包装:apt-getinstalllanguage-pack-zh-hans3、安装好后我们可以进行临时修改:然后添加中文支持: locale-genzh_CN.UTF-8临时修改> export LC_ALL='zh_CN.utf8'> locale永久
BashPerlTclsyntaxdiff1.进制数表示Languagebinaryoctalhexadecimalbash2#[0~1]0[0~7]0x[0~f]or0X[0~f]perl0b[0~1]0[0~7]0x[0~f]tcl0b[0~1]0o[0~7]0x[0~f]bashdifferentbaserepresntationreference2.StringlengthLanguageStr
正常安装了k8s后,使用kubect工具后接的命令不能直接tab补全命令补全方法:yum-yinstallbash-completionsource/usr/share/bash-completion/bash_completionsource<(kubectlcompletionbash)echo"source<(kubectlcompletionbash)">>~/.bashrc 
参考这里启动jar包shell脚本修改过来的#!/bin/bash#默认应用名称defaultAppName='./gadmin'appName=''if[[$1&&$1!=0]]thenappName=$1elseappName=$defaultAppNamefiecho">>>>>>本次重启的应用:$appName<
#一个数字的行#!/bin/bashwhilereadlinedon=`echo$line|sed's/[^0-9]//g'|wc-L`if[$n-eq1]thenecho$linefidone<1.txt#日志切割归档#!/bin/bashcd/data/logslog=1.logmv_log(){[-f$1]&&mv$1$2
#文件增加内容#!/bin/bashn=0cat1.txt|whilereadlinedon=[$n+1]if[$n-eq5]thenecho$lineecho-e"#Thisisatestfile.\n#Testinsertlineintothisfile."elseecho$linefidone#备份/etc目录#
# su - oraclesu: /usr/bin/ksh: No such file or directory根据报错信息:显示无法找到文件 /usr/bin/ksh果然没有该文件,但是发现存在文件/bin/ksh,于是创建了一个软连接,可以规避问题,可以成功切换到用户下,但无法执行系统自带命令。$. .bash_profile-ksh: .: .b
history显示历史指令记录内容,下达历史纪录中的指令主要的使用方法如果你想禁用history,可以将HISTSIZE设置为0:#exportHISTSIZE=0使用HISTIGNORE忽略历史中的特定命令下面的例子,将忽略pwd、ls、ls-ltr等命令:#exportHISTIGNORE=”pwd:ls:ls-ltr:”使用HIS
一.命令历史  1.history环境变量:    HISTSIZE:输出的命令历史条数,如history的记录数    HISTFILESIZE:~/.bash_history保存的命令历史记录数    HISTFILLE:历史记录的文件路径    HISTCONTROL:     ignorespace:忽略以空格开头的命令
之前在网上看到很多师傅们总结的linux反弹shell的一些方法,为了更熟练的去运用这些技术,于是自己花精力查了很多资料去理解这些命令的含义,将研究的成果记录在这里,所谓的反弹shell,指的是我们在自己的机器上开启监听,然后在被攻击者的机器上发送连接请求去连接我们的机器,将被攻击者的she
BashOne-LinersExplained,PartI:Workingwithfileshttps://catonmat.net/bash-one-liners-explained-part-oneBashOne-LinersExplained,PartII:Workingwithstringshttps://catonmat.net/bash-one-liners-explained-part-twoBashOne-LinersExplained,PartII
Shell中变量的作用域:在当前Shell会话中使用,全局变量。在函数内部使用,局部变量。可以在其他Shell会话中使用,环境变量。局部变量:默认情况下函数内的变量也是全局变量#!/bin/bashfunctionfunc(){a=99}funcecho$a输出>>99为了让全局变量变成局部变量
1、多命令顺序执行;  命令1;命令2  多个命令顺序执行,命令之间没有任何逻辑联系&&  命令1&&命令2  逻辑与,当命令1正确执行,才会执行命令2||  命令1||命令2  逻辑或,当命令1执行不正确,才会执行命令2例如:ls;date;cd/home/lsx;pwd;who ddif=输入文件of=输
原博文使用Linux或者unix系统的同学可能都对#!这个符号并不陌生,但是你真的了解它吗?首先,这个符号(#!)的名称,叫做"Shebang"或者"Sha-bang"。Linux执行文件时发现这个格式,会把!后的内容提取出来拼接在脚本文件或路径之前,当作实际执行的命令。 Shebang这个符号通常在Unix系统的脚本
1、历史命令history[选项][历史命令保存文件]选项:-c:  清空历史命令-w:  把缓存中的历史命令写入历史命令保存文件 ~/.bash_historyvim/etc/profile中的Histsize可改存储历史命令数量历史命令的调用使用上、下箭头调用以前的历史命令使用“!n”重复执行第n条历史
目录1.Shell脚本规范2.Shell脚本执行3.Shell脚本变量3.1环境变量3.1.1自定义环境变量3.1.2显示与取消环境变量3.1.3环境变量初始化与对应文件的生效顺序3.2普通变量3.2.1定义本地变量3.2.2shell调用变量3.2.3grep调用变量3.2.4awk调用变量3.3
   http://www.voidcn.com/blog/wszzdanm/article/p-6145895.html命令功能:显示登录用户的信息命令格式:常用选项:举例:w显示已经登录的用户及正在进行的操作[root@localhost~]#w 11:22:01up4days,21:22, 3users, loadaverage:0.00,0.00,0.00USER