馮老師踩坑記——測試和正式環境掐架篇(一)

快樂的皮拉夫發表於2023-11-20

關於馮老師

  • 大名:馮老師
  • 小名:真男人
  • 英文名字:TrueMan
  • 年齡:未知
  • 座右銘:就這???

在我們公司,一提起馮老師,那可謂無人不知,無人不曉。

訂單申請不了售後了,怎麼辦呢?—— 找馮老師。

倉庫稽核按鈕不見了,怎麼辦呢?—— 找馮老師。

衛生間馬桶堵了,怎麼辦呢—— 找馮老師。

可以說,在我們公司,找馮老師就是「政治正確」。找馮老師,比 ChatGPT 還好使。

不過,即使聰慧如馮老師,也會有踩坑的時候。本系列文章,我們就來細數馮老師踩過的那些「坑」。

馮老師的困惑

週一下班後,我已經收拾好東西準備下班了,馮老師略顯踟躕地走過來,用戲謔的語氣對我說:「來來來,架構師,考你個問題,看看你水平怎麼樣」。

聽到這裡,我大抵猜到馮老師又遇到問題了—— 他平時都是喊我小喬的。

我放下書包,剛準備去他那裡,又突然想到了什麼,忙收住腳步。我開啟了我的記賬本:

附錄(PB 兌換規則及收費標準):

PiujdKPUye.png!large

1cyVWmQ00q.png!large

「馮老師,你還欠我 4PB 呢。」

「先記賬上就行。」

「好的。按技術服務標準收費,現在是六點零一分,算你六點鐘吧。」

馮老師似乎並不關心收費問題,畢竟對於吃慣了四個菜的人來說,這些都是毛毛雨。

「你來看,我給你描述一下問題。」

「同樣的程式碼,我程式碼在本地和測試環境都正常,但是上線以後,報了一個常量未定義的錯誤,這可能是什麼問題呢?」

我思考片刻,快速捕捉馮老師言語中的重要資訊:

  • 直接報錯:常量未定義;
  • 本地和測試環境正常,正式環境報錯;
  • 正式環境和測試環境程式碼一致。

神探皮拉夫登場

帶著這些所謂的「結論」,我開始了「破案」過程。

我需要做的就是,從上述「線索」出發,一一排查每一條「線索」的真實性。沒錯,在真相大白之前,我只相信我眼睛看到的東西,其他聽到的「證據」在沒有得到證實之前,我都稱之為「線索」。

關於同樣的程式碼在不同環境下表現不同,無外乎以下兩種情況:

  • 程式碼問題;
  • 環境問題。

環境包括程式碼執行的編譯環境,資料庫環境等外部條件。這裡經過排查,測試和正式環境都是一致的。而且報錯提示是常量未定義的問題,並非環境問題導致。所以,環境問題的嫌疑基本可以排除。

接下來,我們把重點放在程式碼差異的排查上。

由於程式碼都是經過 jenkins 自動部署釋出的,經過對比核心程式碼以後,發現經過釋出的程式碼和測試環境並無差異。除了自動部署的程式碼,還有一部分程式碼是不走釋出的,因為這部分程式碼屬於各環境的環境變數及配置資訊,所以這部分程式碼需要手動維護更新。

接下來,就是排查這部分程式碼的問題了。

可是,馮老師信誓旦旦地告訴我:「環境變數也是一樣的,我都檢查過了,不用看。」

環境沒有問題,程式碼也沒有問題 —— 常量不存在?一定是見鬼了。

「你確定常量都是一樣的嗎?」

「你還不相信我。。。來,你來看。」

馮老師開啟線上和測試環境的變數給我看(常量定義在了入口檔案index.php中,框架用的ThinkPHP 5.0):

正式環境 index.php

define('BIG_KENG', 'IF YOU JUMP, YOU ARE DEAD.');
//========== tms 電子面單 ==========
define('TMS_HOST', 'http://tms.aaa.com');

測試環境 index.php

//========== tms 電子面單 ==========
define('TMS_HOST', 'http://tms-test.aaa.com');

看著確實沒什麼區別。「這個 BIG_KENG 是個什麼東東?」,我隨口一問。

「那個不用管,別人定義的,和這裡沒有關係。」

「哦。」

「常量未定義還有可能是定義常量的檔案出現了語法問題,其他常量能用麼?」

「能用。」馮老師信誓旦旦地對我說。

「列印一個我瞧瞧。」

「還不相信我。。。這就給你看。」馮老師很不情願地給我列印了一個其他定義的常量 —— 確實可以正常輸出。

「那真的是見鬼了。。。」

往往到了這種兜兜轉轉又回到起點的時候,我都會想起福爾摩斯對華生說的那句話 —— 排除其他一切可能,最後剩下來的,就算再不可思議,也必定是真相。

我決定再把目光回到index.php這個「重大嫌疑人」身上。

果不其然,真相還就真被我給發現了。

揭秘時刻

當我一拍桌子的時候,馮老師頓時慌了神,怔了一下,臉上隨即露出了不可思議又略帶嫉妒的笑——「快說,怎麼回事?」

每當這個時候,我感覺如果不是噸位大一些的話,我都能飄起來。沒有什麼事是比在馮老師面前炫耀戰果更有成就感的了。

馮老師目不轉睛地盯著電腦螢幕,我甚至能聽到他緊張的心跳。

我把滑鼠選中了以下這行程式碼:

define('BIG_KENG', 'IF YOU JUMP, YOU ARE DEAD.');

「這是誰寫的程式碼?Tell me。」

馮老師似乎對我這突如其來又貌似八竿子打不著的問題有些不耐煩:「別人寫的啊,人家寫的也沒問題啊,格式都對啊。」

「你列印下試試,看看能正常列印麼。」

馮老師似乎對這看上去 100% 無疑義的問題不屑一顧:「這還用列印麼,肯定沒問題啊,這都是線上正常在跑的,你到底行不行啊。」

「先列印下看看吧,馮老師。萬一不行呢?」我耐心勸導著馮老師。

馮老師心中雖然不情願,但還是照我說的做了。

「擦嘞!!!什麼情況」馮老師一臉的不可思議,兩隻眼睛瞪的像銅鈴一樣,幾乎要迸出來了。

「不可能吧,看不出來哪有問題啊?」馮老師似乎還是沒有發現端倪,儘管真相就在他目之所及的程式碼上方。

我沒有說話,只是用滑鼠把下面的程式碼給圈了出來:

// 載入框架引導檔案
require __DIR__ . '/../thinkphp/start.php';
define('BIG_KENG', 'IF YOU JUMP, YOU ARE DEAD.');
//========== tms 電子面單 ==========
define('TMS_HOST', 'http://tms.aaa.com');

馮老師看了半晌,還是沒看出問題來:「沒看出有啥不妥的啊?BIG_KENG 定義的沒啥問題啊。」

見馮老師還是沒 Get 到我的點,我讓他關注下面這行程式碼:

// 載入框架引導檔案
require __DIR__ . '/../thinkphp/start.php';

「我想讓你看的是它,馮老師。」

start.php怎麼了,不要告訴我你不知道它是啟動檔案?」

我嘆了口氣:「你去開啟這個start.php,看看它到底幹了些啥。」

馮老師照我說的開啟了start.php

namespace think;

// ThinkPHP 引導檔案
// 1. 載入基礎檔案
require __DIR__ . '/base.php';

// 2. 執行應用
App::run()->send();

檔案內容不多,只有三行程式碼。這次不等馮老師張口,我便提前給他科普了:「start.php是啟動檔案,包含了啟動應用的操作。而你的常量定義在了啟動檔案後面,當然就不起作用了。」

「那測試環境為啥……」

//========== tms 電子面單 ==========
define('TMS_HOST', 'http://tms-test.aaa.com');
// 載入框架引導檔案
require __DIR__ . '/../thinkphp/start.php';

「靠!!!」

馮老師沉思了大概有半秒鐘,瞬間又換了一副小人得志的嘴臉:「行了,行了,我以為多大問題,就這???」。

我微微一笑,因為我已經習慣了這樣的馮老師。

「你們是真的坑,這不能用的程式碼也往線上發,這不坑人麼。」馮老師還在發著小牢騷。

「人家都掛了牌子了啊,你自己不看就往下跳,這賴誰。」

「哪寫了?」

「BIG_KENG。。。這還不夠明顯???」

馮老師起身,搖著頭,撅著嘴,念念叨叨地揚長而去,只留給我一個不屈的背影。

我看了一眼手機,此時剛好六點十五分。於是我在記賬本上又記下了一筆 —— 替馮老師處理線上環境變數問題,耗時二十分鐘,收費 4PB。

總結大會

十分鐘前,一切看著不可思議。

十分鐘後,一切看著又不過爾爾。

很多時候,不是我們的眼神不夠犀利,而是在面對近在咫尺的問題前,我們總是習慣性地自我肯定及否定 —— 我們遲遲走不出圈子,不是因為邁不開腳,而是因為我們從來不覺得自己就站在圈子裡。

就像馮老師遇到的這個問題一樣,明明別人已經標了「BIG_KENG」了,馮老師卻偏偏還要跟著 JUMP。明明已經在「坑」裡了,卻還信誓旦旦地說:這怎麼可能會是個「坑」呢?

就像至尊寶,戴上金箍只需要一秒,而摘下來,卻要一萬年。

NuTGpfkzNq.jpg!large

本作品採用《CC 協議》,轉載必須註明作者和本文連結
你應該瞭解真相,真相會讓你自由。

相關文章