问:池老师,我是个不爱互动的人,但是您所有的文章我都看了,非常感谢您的引导,我入手了人生第一台 MBP。现在问题来了,但是找不到更合适的人解答,只能求助于您了,如果您有时间的话。问题是这样的:我有个32bit unix file(开启一个服务进程),在 Mac 上执行时错误提示是:exec format error,但是在 Linux 服务器却可以执行,为何?Mac 上有可以运行的方案吗?期待您的回复,不胜感激。
答:Linux 和 OS X 是不同的操作系统,可以尝试在 OS X 里重新编译这个文件。
问:非常感谢!如果没有文件源码是不是就只能认命了?
答:可以在 Mac 上装 Docker,然后对服务进行端口映射就可以了。
答:茅塞顿开。谢池老师。
以上是我和一位读者的对话,这位小伙子在拿到答案之后像一缕烟尘一样消失无踪,之后再也没有出现过。
在微信上加了很多 MacTalk 的读者之后,经常会收到一些奇奇怪怪的问题,关于职场、关于选择、关于朋友、关于 Mac、关于技术等等,不一而足。但是我能回答的却很少。问题不好没法回答,问题太复杂没法回答,问题领域超出我的认知也没法回答,耗时太长的问题我也没 时间回答,实在是惭愧的紧。好在偶尔也能够帮助一些小伙伴解决一些实际问题,心理上略感安慰,比如上面这个问题。
把这段程序员之间的对话翻译一下,大致是这么个故事:
一 位读者有一个32位的 Unix 可执行文件,可以在某种版本的 Linux 服务器上正常运行,运行这个文件作用就是起个进程,开端口,然后与其他程序进行交互。但是这个文件拿到 Mac 上完全没办法运行。就在他趴在 Mac 上愁肠百结万念俱灰的时候,突然想到了「池老师」。不就是这个老家伙把 Mac 夸的像一朵玫瑰一样,让每个程序员都去采摘么?现在扎手了,你不管谁管?于是他给我发来消息,意思就是管也得管,不管也得管,您看着办。
我拿到问题一看,不难。Linux 和 OS X 虽然师出同门,都是从老前辈 Unix 那儿毕业的,但是后来毕竟各练各的,在 Linux 编译好的程序不可能在 OS X 上用,但是在 OS X 上重新编译一下可能就没事了。我把这个想法告诉了这位程序员,得到的反馈是:对不起哥,没有源代码!
我被这个冷酷的回复震惊了,立刻意识到 刚才的想法并不是最优解决方案,因为在重新编译的过程中,各种包的依赖关系和编译错误足以让你焦头烂额,我随即提供了 B 计划:在 OS X 上安装 Docker,轻量级的容器 Docker 可以运行各种版本的 Linux,把文件扔到 Docker 里,然后通过主机和 Docker 之间的端口映射即可轻松解决这一问题。
虽然这里面会涉及很多技术细节,但是方向是没有问题的,所以这位程序员立刻表示「茅塞顿开」,然后「biu 」的一声就在屏幕对面消失了,没有留给我说「不客气」的机会。
这个问题装个 Linux 虚拟机也可以解决,但是虚拟机过于耗费资源,而且不如 Docker 灵活,所以不是最佳解决方案。Docker 是。
做为一个程序员,我们除了要掌握多门程序语言和多种数据库,了解前端技术、后端技术,通晓网络七层架构,知道 TCP/IP三次握手和四次挥手,编写漂亮的代码,设计优美的架构……之外,我们还要解决研发、程序运行和产品上线过程中遇到的各种问题,而且被要求以最 小的代价来解决问题……我们容易吗?
除了编程技巧和程序设计能力,解决问题的稳准狠是衡量一个程序员是否优秀的重要因素之一,也是资深技术 人员真正的价值所在。在科技浪潮澎湃、技术信息扑面而来的今天,一位刚毕业的大学生如果足够勤奋,他可以在两三个月之内掌握一门编程语言,并编写出像模像 样的软件,他们的学习速度甚至超过了我们这些老程序员,但是解决问题的能力是无法速成的,只能依靠时间、经验和惨痛的教训历练而成。有时候还需要灵感和运 气。
很多军迷读了大量的军事著作和历史小说,常常羡慕那些名将的风采,并浩叹自己「生不逢时」。但是名将不是那么容易炼成的。历史上叱诧风 云的名将凤毛麟角,他们亲自持刀上阵追击敌人,见识战场的惨烈,目睹敌人的尸体,看到战友被杀,知道被刀看中会流血死去,他们冷酷无情,坚如磐石,在全军 即将崩溃的时候发现敌人的弱点并进行攻击,在瞬息万变的战场进行决断,在多次失败后从无数士兵的尸体里站起来重新出发去挑战那个战胜你的对手,在所有人对 你说「指导员,我们上吧」的时候,坚定的说出那三个字:再等等!
如果你做不到这些,那还是做个最终会被张飞枪挑的小兵吧。
优秀的程序员同样如此,菜鸟常常羡慕高手在谈笑之间让难题灰飞烟灭,而自己却苦苦思索而不得入门之法,殊不知这些高手同样经历了名将的那些腥风血雨。他们在 清晨的微光里编写代码,在轰鸣的机房中调试程序,他们彻夜不眠就是为了解决一个 bug,他们要承受数据丢失或上线失败的痛苦,默默吞下眼泪,准备下一次的战斗。不停的学习、实践和思索,成千上万个小时之后,高手史成。
同样的问题,高手的解决思路和小球是截然不同的。一般来说,只要不是世界难题,给足时间、空间和人力,都能解决。如果你遇到问题告诉上级,这个问题交给我 了,两年之内搞的妥妥哒,那就不要怪项目组组团把你打出翔来,因为大家要的是分分钟解决,不是两年。在这个唯快不破的年代,我们没有这么多的时间,所以要 通过逆向思维、经验教训、辗转腾挪、借力打力等方式以最小的代价快速解决问题。这才是老程序员的价值。
再举个例子,一个运行良好的线上应用在你修改 bug 增加功能之后重新上线出现了一些莫名其妙的问题,比如占用资源增加或运行一段时间宕机等等,怎么解决?
常规的做法就是通过阅读日志、模拟线上环境和调试程序来定位错误。容易的 bug 用这些方式基本就能搞定了,但是更隐蔽的 bug 会耗费大量的时间和人力。更好的方式是什么?
首先,排查是程序问题还是环境问题,把线上程序恢复到运行正常时的老版本,如果出现了同样的问题,那就是生产环境发生了改变。如果运行正常,要么是你修改老 bug 时引入了新 bug,要么是新增加的代码出现了问题。
其次,阅读产品的 changelog,根据代码提交的时间线构建系统,通过二分法排查,定位是哪部分代码引起的问题。
最后,排除了所有的不可能,剩下的无论看起来如何不可能,就是它干的。
以上只是一个简单的例子,实际的情况可能比这个例子复杂一百倍,需要我们综合使用各种方式进行交叉比对和错误排查才能解决。这仅仅是遇到问题解决问题,更多的时候是需要你提出问题,并解决问题,那是更高的境界。
很多人学了那么多编程语言,写了十几年程序,最终依然无法做到以最小的代价解决问题,不禁让人扼腕叹息。
程序员真正的价值是什么?以最小的代价解决问题!知行合一,方可无敌于天下。