現(xiàn)DDNS動(dòng)態(tài)解析:公網(wǎng)IP變化自動(dòng)更新教程)
家里的寬帶每隔一段時(shí)間公網(wǎng)IP就會(huì)變尤其是不滿運(yùn)營商最長在線時(shí)長之后強(qiáng)制斷線重?fù)艿哪欠N老域名解析記錄一直是舊IP訪問家里NAS或者是遠(yuǎn)程桌面全都得靠臨時(shí)記IP來連煩得不行。后來我把域名托管到了阿里云云解析直接用了阿里云官方出的alidns命令行工具來做動(dòng)態(tài)解析配合一個(gè)小腳本把檢測(cè)IP、比對(duì)緩存、調(diào)API更新記錄這幾件事串起來徹底不用再手動(dòng)改解析了。這篇文章就記錄我這次完整折騰的過程工具選型怎么想、AccessKey權(quán)限怎么收縮、腳本怎么寫、定時(shí)任務(wù)怎么掛以及實(shí)際跑起來踩過的坑。內(nèi)容適合家里有動(dòng)態(tài)公網(wǎng)IP、手上域名在阿里云云解析的用戶也適合剛接觸alidns想快速落地的開發(fā)者。1. 項(xiàng)目思路拆解動(dòng)態(tài)IP自動(dòng)更新的完整鏈路1.1 痛點(diǎn)本質(zhì)解析記錄和出口IP之間的“失聯(lián)”沒有固定公網(wǎng)IP的家庭寬帶IP變化是有周期的。運(yùn)營商會(huì)重啟你的撥號(hào)連接可能是48小時(shí)可能是72小時(shí)也可能是隨機(jī)的時(shí)間點(diǎn)。每次重?fù)苣玫降男翴P都和上一輪不一樣而DNS解析記錄里寫死的還是上一次的那個(gè)A記錄值。結(jié)果就是域名明明解析正常但訪問指向的IP已經(jīng)不再是你的設(shè)備了。這個(gè)問題的本質(zhì)是DNS記錄需要跟隨出口IP的變化同步刷新。手動(dòng)做這件事要兩步先查當(dāng)前公網(wǎng)IP再去控制臺(tái)改解析記錄。一次還行長期下來就是純粹的重復(fù)勞動(dòng)而且白天人不在家、夜里突然斷線重?fù)芨緛聿患笆謩?dòng)改。所以我們需要的是一個(gè)能自動(dòng)完成“檢測(cè)到IP變化 → 更新云解析記錄”的本地腳本或者服務(wù)。1.2 為什么選擇阿里云官方alidns而不是自研腳本方案其實(shí)可以從兩個(gè)維度看調(diào)用API的路徑、觸發(fā)更新的方式。調(diào)用API這一步第一反應(yīng)是直接用阿里云云解析的OpenAPI來做寫一個(gè)Python腳本調(diào)用SDK更新對(duì)應(yīng)記錄。這個(gè)思路沒有問題但實(shí)際上做的時(shí)候會(huì)發(fā)現(xiàn)很多邊緣細(xì)節(jié)要處理記錄不存在時(shí)先創(chuàng)建記錄存在時(shí)才能更新不同記錄類型要分別處理SDK初始化參數(shù)要填對(duì)區(qū)域等等。alidns這個(gè)官方命令行工具把這些底層邏輯都封裝好了一條命令就能完成解析記錄的增刪改查天然比“自己從零寫SDK調(diào)用”省事。觸發(fā)更新這一步我見到的方案也很多有人在路由器上掛插件有人在軟路由里跑容器還有人直接寫cron定時(shí)任務(wù)。我選擇最簡(jiǎn)單、依賴最少的一條路alidns命令行工具加本地bash腳本再掛系統(tǒng)cron。不需要常駐進(jìn)程不需要額外容器環(huán)境腳本五分鐘或者十分鐘跑一次足夠應(yīng)對(duì)IP變化了。結(jié)論很直接用官方工具alidns承擔(dān)API調(diào)用細(xì)節(jié)用腳本做輪詢比對(duì)用cron做定時(shí)觸發(fā)。這套組合邏輯清晰、故障點(diǎn)少、出問題也好排查。2. 核心細(xì)節(jié)解析alidns工具的工作機(jī)制與關(guān)鍵配置2.1 alidns是什么以及它怎么工作alidns是阿里云云解析配套的命令行工具。它底層調(diào)用的就是云解析DNS的OpenAPI你給它的參數(shù)最終會(huì)轉(zhuǎn)換成對(duì)接口的請(qǐng)求。比如更新一條A記錄它內(nèi)部會(huì)先查域名下的記錄列表找到匹配record參數(shù)的記錄ID再調(diào)用更新接口把value改成新的IP。因?yàn)樗旧砘诎⒗镌乒俜降腟DK封裝所以你不需要關(guān)心簽名算法、請(qǐng)求串格式、錯(cuò)誤重試這些問題。工具支持的操作大致包括add新增解析、update更新解析、delete刪除解析、describe查詢解析。日常動(dòng)態(tài)DNS場(chǎng)景最常用的就是describe和update。工具的運(yùn)行環(huán)境要求很普通Python 3.6 以上就可以通過pip安裝后直接命令行調(diào)用。我實(shí)際用下來它就是一條命令的事情例如alidns --record home.example.com --method update --value 你的新IP執(zhí)行完它會(huì)在終端里輸出解析記錄ID、當(dāng)前記錄值這些關(guān)鍵信息返回結(jié)果清晰可控。2.2 安裝與環(huán)境準(zhǔn)備過程裝工具這塊沒什么玄學(xué)直接pip安裝pip3 install alidns裝完之后檢查一下命令是否可用alidns --help當(dāng)終端能正常輸出參數(shù)幫助信息工具就算裝好了。這里提醒一句如果機(jī)器上有多個(gè)Python版本pip3對(duì)應(yīng)的Python版本最好和alidns要求的版本一致否則會(huì)出現(xiàn)“裝成功但命令找不到”的經(jīng)典問題。另外一個(gè)不太顯眼的細(xì)節(jié)是alidns支持通過--config指定一個(gè)配置文件這樣每次執(zhí)行不用把AccessKey信息寫在命令行里既安全又省事。我建議在正式用之前就把配置文件的目錄規(guī)劃好比如放在當(dāng)前用戶目錄下的隱藏文件夾里權(quán)限收緊到只有自己可讀寫。2.3 AccessKey的創(chuàng)建原則絕不用主賬號(hào)調(diào)任何云API都需要鑒權(quán)alidns也是一樣。它通過AccessKey ID和AccessKey Secret來確定你的身份和權(quán)限。這里有一條非常硬的安全原則堅(jiān)決不要用自己的主賬號(hào)AccessKey跑這種定時(shí)腳本。主賬號(hào)AK等于整個(gè)賬號(hào)的最高權(quán)限一旦腳本所在機(jī)器被入侵或者機(jī)器上的配置文件被讀到等于把你的整個(gè)云上資產(chǎn)都送給對(duì)方了。正確做法是走RAM子賬號(hào)授權(quán)。登錄阿里云控制臺(tái)在訪問控制里創(chuàng)建一個(gè)子用戶只給它開放云解析DNS的操作權(quán)限。然后針對(duì)不同用途權(quán)限還能再細(xì)分。個(gè)人DDNS場(chǎng)景最小權(quán)限只要兩條查詢解析記錄、更新解析記錄。把權(quán)限范圍收縮到這兩條即使AK泄露了能做的事情也就剩下改解析記錄這一件破壞面可控。創(chuàng)建子賬號(hào)的時(shí)候會(huì)生成一組獨(dú)立的AccessKey這組AK專門給alidns用。拿到的AccessKey ID和Secret要妥善保管后面配置和腳本里都要用。2.4 記錄類型與域名前置檢查做IPv4動(dòng)態(tài)解析對(duì)應(yīng)的記錄類型就是A這類記錄把域名指向一個(gè)IPv4地址。如果你的場(chǎng)景以后需要做IPv6動(dòng)態(tài)解析那就是AAAA記錄。alidns對(duì)A和AAAA都支持所以這個(gè)工具往后擴(kuò)展空間也夠。開始之前一定要確認(rèn)幾件事域名已經(jīng)添加到阿里云云解析的域名列表里主域名狀態(tài)正常需要更新的子域名記錄已經(jīng)存在比如我在控制臺(tái)里先手動(dòng)建了一條home.example.com的A記錄初始值隨便填一個(gè)。為什么要先手動(dòng)建一條因?yàn)閡pdate操作是基于已有記錄來更新的如果你要用update就必須保證目標(biāo)記錄已經(jīng)存在。先手動(dòng)建一條腳本調(diào)試階段更新成功與否一眼就能看出來比上來就用add更直觀。3. 實(shí)操過程與核心環(huán)節(jié)實(shí)現(xiàn)3.1 配置文件與認(rèn)證信息組織這一步我們落地一心一用的認(rèn)證文件。我在當(dāng)前用戶目錄下建了一個(gè).alidns目錄然后在里面放了一個(gè)config.json內(nèi)容大概是這樣的{ access-key-id: 你的AccessKey ID, access-key-secret: 你的AccessKey Secret, region-id: cn-hangzhou, record: home.example.com, type: A, ttl: 600 }配置文件寫好之后立刻處理權(quán)限chmod 600 ~/.alidns/config.jsonchmod 600意味著只有文件屬主也就是當(dāng)前用戶能讀和寫這個(gè)文件其他用戶一律不可讀、不可寫、不可執(zhí)行。這是對(duì)密鑰類文件最基本的保護(hù)一定不要跳過。配置里為什么要寫region-id因?yàn)榘⒗镌频腛penAPI調(diào)用需要指定區(qū)域云解析產(chǎn)品目前通用的區(qū)域是cn-hangzhou這個(gè)一般來說不用改保持默認(rèn)就行。ttl設(shè)的是解析記錄的緩存時(shí)間600秒就是10分鐘個(gè)人動(dòng)態(tài)解析場(chǎng)景夠用。3.2 手動(dòng)更新與查詢驗(yàn)證配置好之后先用describe方式確認(rèn)工具能正常讀取配置并查詢記錄alidns --config ~/.alidns/config.json --method describe執(zhí)行完如果正常終端會(huì)輸出當(dāng)前解析記錄的詳情包括記錄ID、記錄類型、記錄值、TTL等信息??吹阶约菏謩?dòng)建的那條A記錄躺在那說明配置和認(rèn)證鏈路都通著。接著做一次手動(dòng)更新先隨便指定一個(gè)新IP值alidns --config ~/.alidns/config.json --method update --value 8.8.4.4看到工具返回更新成功的提示之后再去控制臺(tái)刷新一下域名解析列表確認(rèn)記錄值已經(jīng)變成8.8.4.4。這一步驗(yàn)證的重點(diǎn)是工具確實(shí)有權(quán)限更新該記錄配置文件、記錄名、域名關(guān)系全部正確。驗(yàn)證完再把記錄值手動(dòng)改回真正的公網(wǎng)IP或者等腳本自己處理都可以。3.3 自動(dòng)檢測(cè)公網(wǎng)IP并更新解析工具驗(yàn)證沒問題之后剩下的就是讓整個(gè)流程自動(dòng)化。自動(dòng)化的核心是三步檢測(cè)當(dāng)前出口公網(wǎng)IP、和上次記錄的值做比對(duì)、不一致才觸發(fā)更新。獲取公網(wǎng)IP我試過幾個(gè)渠道比較穩(wěn)的是這類純文本輸出接口比如icanhazip.com、ifconfig.me。實(shí)際用下來單一路由可能有偶發(fā)超時(shí)所以我習(xí)慣寫一個(gè)備選邏輯第一個(gè)接口拿不到就用第二個(gè)。示例腳本大概長這樣#!/bin/bash # 配置區(qū) CONFIG$HOME/.alidns/config.json CACHE_FILE$HOME/.alidns/last_ip.txt LOG_FILE$HOME/.alidns/ddns.log # 函數(shù)獲取當(dāng)前公網(wǎng)IP get_current_ip() { IP$(curl -s -m 10 https://ipv4.icanhazip.com | grep -Eo [0-9]{1,3}(\.[0-9]{1,3}){3} | head -n 1) if [ -z $IP ]; then IP$(curl -s -m 10 https://ifconfig.me | grep -Eo [0-9]{1,3}(\.[0-9]{1,3}){3} | head -n 1) fi echo $IP } # 讀取上次記錄的IP LAST_IP if [ -f $CACHE_FILE ]; then LAST_IP$(cat $CACHE_FILE) fi CURRENT_IP$(get_current_ip) if [ -z $CURRENT_IP ]; then echo $(date %Y-%m-%d %H:%M:%S) 獲取公網(wǎng)IP失敗本次終止 $LOG_FILE exit 1 fi if [ $CURRENT_IP $LAST_IP ]; then echo $(date %Y-%m-%d %H:%M:%S) IP無變化跳過更新 $LOG_FILE exit 0 fi # 執(zhí)行更新 alidns --config $CONFIG --method update --value $CURRENT_IP $LOG_FILE 21 # 更新成功后再記錄新的IP到緩存 if [ $? -eq 0 ]; then echo $CURRENT_IP $CACHE_FILE echo $(date %Y-%m-%d %H:%M:%S) 解析已更新為 $CURRENT_IP $LOG_FILE fi腳本的主要思想就是用緩存文件做狀態(tài)記憶。每次跑完發(fā)現(xiàn)IP變了才去調(diào)API不變就什么都不做。這樣定時(shí)任務(wù)跑得很輕也不會(huì)有多余的API調(diào)用。每行日志都帶時(shí)間戳后面排查問題全靠這個(gè)日志文件。腳本存到本地之后記得賦予執(zhí)行權(quán)限chmod x /usr/local/bin/ddns-update.sh3.4 手動(dòng)執(zhí)行一次完整流程腳本寫完先不急著掛定時(shí)任務(wù)手動(dòng)跑一遍。我習(xí)慣分兩階段驗(yàn)證先看輸出再看日志。執(zhí)行腳本之后檢查終端有沒有報(bào)錯(cuò)信息然后查看日志文件尾部tail -n 20 ~/.alidns/ddns.log如果看到“解析已更新為xxx”馬上去阿里云控制臺(tái)刷新解析列表確認(rèn)記錄值已經(jīng)變成當(dāng)前公網(wǎng)IP。這樣一次全鏈路驗(yàn)證就完成了。驗(yàn)證之后把緩存文件里的IP改成當(dāng)前值再跑一次腳本應(yīng)該能觸發(fā)“IP無變化跳過更新”的日志。這一步說明比對(duì)邏輯是正常的。3.5 掛上cron定時(shí)任務(wù)定時(shí)任務(wù)我用的是系統(tǒng)自帶的crontab。先打開當(dāng)前用戶的定時(shí)任務(wù)編輯界面crontab -e然后在文件末尾加一行*/5 * * * * /usr/local/bin/ddns-update.sh /dev/null 21*/5 * * * *代表每5分鐘執(zhí)行一次腳本。動(dòng)態(tài)IP變化的頻率一般是以小時(shí)甚至天為單位的5分鐘檢查一次已經(jīng)非常充裕。如果想更保守一點(diǎn)改成*/10或者*/15也可以沒必要把間隔壓得太狠。這里有一個(gè)實(shí)際執(zhí)行中容易踩的坑cron環(huán)境變量和當(dāng)前shell環(huán)境不一樣。如果你在終端手動(dòng)執(zhí)行腳本一切正常但掛上cron之后不出日志多半是因?yàn)槟_本執(zhí)行環(huán)境里找不到alidns命令的路徑。解決辦法簡(jiǎn)單粗暴在腳本最前面把PATH環(huán)境變量顯式指到位比如export PATH/usr/local/bin:/usr/bin:/bin:$PATH或者干脆在腳本里用alidns命令的絕對(duì)路徑。我自己的環(huán)境里alidns裝在/usr/local/bin/alidns腳本里直接用絕對(duì)路徑調(diào)用一勞永逸。4. 腳本的容錯(cuò)加固與安全細(xì)節(jié)4.1 多域名批量更新的擴(kuò)展方案如果家里不只一個(gè)域名要指向同一個(gè)IP甚至有好幾個(gè)子域名腳本就得稍微改造一下。最直接的做法是把要更新的記錄名放在一個(gè)數(shù)組里循環(huán)處理RECORDS(home.example.com nas.example.com vpn.example.com) for REC in ${RECORDS[]}; do alidns --config $CONFIG --record $REC --method update --value $CURRENT_IP $LOG_FILE 21 done不要忽略--record參數(shù)的妙用配置文件里如果寫了固定的record命令行里再傳--record就會(huì)覆蓋配置里的記錄名這樣同一個(gè)配置賬戶能管理多個(gè)解析。我實(shí)際就是這么干的一臺(tái)小機(jī)器上同時(shí)維護(hù)好幾個(gè)子域名的映射腳本復(fù)用一個(gè)邏輯。4.2 權(quán)限加固與密鑰保護(hù)實(shí)操安全這個(gè)話題必須單獨(dú)展開。從前面創(chuàng)建RAM子賬號(hào)開始我自己總結(jié)了一套動(dòng)態(tài)DNS場(chǎng)景的密鑰保護(hù)基線第一子賬號(hào)權(quán)限最小化。在RAM授權(quán)時(shí)系統(tǒng)策略里有一串現(xiàn)成的權(quán)限策略比如AliyunDNSFullAccess這種完整訪問權(quán)限雖然方便但權(quán)限過大。我更推薦自定義一個(gè)精簡(jiǎn)策略只放兩條Action{ Version: 1, Statement: [ { Effect: Allow, Action: [ alidns:DescribeDomainRecords, alidns:UpdateDomainRecord ], Resource: * } ] }這個(gè)策略只允許查詢和更新解析記錄無法新增刪除整個(gè)域名也無法做收費(fèi)操作。對(duì)個(gè)人DDNS來說已經(jīng)夠用。第二配置文件絕不進(jìn)倉庫。如果你的腳本和配置是放在代碼倉庫里的一定要用.gitignore把包含密鑰的文件排除掉。.alidns目錄、config.json這類東西堅(jiān)決不能提交一旦提交過再撤回就不干凈了因?yàn)闅v史提交里還留著密鑰文本。第三密鑰輪換要常態(tài)化。即使權(quán)限設(shè)好了也建議每隔半年或者一年重新生成一次AccessKey。RAM控制臺(tái)里的操作不復(fù)雜禁用舊的、新建一對(duì)、替換到配置文件里。輪換周期自己掌握但不要“創(chuàng)建后用到天荒地老”。4.3 記錄類型和TTL調(diào)優(yōu)的邊界很多人會(huì)在解析更新時(shí)糾結(jié)TTL到底設(shè)置多少。從動(dòng)態(tài)場(chǎng)景來看TTL設(shè)置越短DNS服務(wù)器緩存舊值的時(shí)間越短IP變化后生效越快。但TTL也不是越低越好太短的TTL會(huì)導(dǎo)致全球各地的DNS查詢頻繁回到權(quán)威服務(wù)器徒增壓力。對(duì)于家庭應(yīng)用場(chǎng)景我實(shí)測(cè)下來600秒這個(gè)默認(rèn)值已經(jīng)足夠遇到IP變化最長十分鐘左右就能全面生效。如果對(duì)生效速度特別敏感可以調(diào)到120秒代價(jià)是解析查詢量略微上升。日常使用完全沒必要追著60秒跑。再說A和AAAA兩類記錄。本文的項(xiàng)目標(biāo)題只要求IPv4所以全部流程都圍繞A記錄進(jìn)行。如果你的設(shè)備已經(jīng)接入了IPv6環(huán)境也允許使用IPv6地址訪問那可以仿照同樣的邏輯再寫一個(gè)AAAA記錄更新流程alidns工具本身支持--type AAAA參數(shù)改動(dòng)成本很低。5. 常見問題與排查技巧實(shí)錄5.1 高頻報(bào)錯(cuò)與解決方案對(duì)照表實(shí)操過程中可能會(huì)碰到各種報(bào)錯(cuò)我整理了一份對(duì)照表基本都是容易踩到的高頻問題現(xiàn)象大概率原因處理方式提示AccessKey ID不存在配置里的AK信息填寫有誤核對(duì)AccessKey ID和AccessKey Secret是否復(fù)制完整注意別混進(jìn)空格提示權(quán)限不足RAM子賬號(hào)沒有授權(quán)DNS權(quán)限到RAM控制臺(tái)給子賬號(hào)增加自定義或系統(tǒng)DNS權(quán)限策略提示域名記錄不存在目標(biāo)記錄沒有在云解析里創(chuàng)建過先在控制臺(tái)手動(dòng)創(chuàng)建一條對(duì)應(yīng)記錄再執(zhí)行更新命令找不到alidnsPython環(huán)境或PATH未配置正確檢查安裝時(shí)候的Python版本用絕對(duì)路徑調(diào)用alidns腳本能跑但日志為空cron環(huán)境變量差異導(dǎo)致curl或alidns無法執(zhí)行腳本開頭顯式聲明PATH或者全部使用絕對(duì)路徑curl獲取公網(wǎng)IP超時(shí)出口網(wǎng)絡(luò)不穩(wěn)定或接口被臨時(shí)限流在腳本里配置多個(gè)備用IP接口依次嘗試更新成功但訪問還是不通本地或運(yùn)營商DNS緩存了舊值清本地DNS緩存等待TTL時(shí)間過后再測(cè)試5.2 排查思路從現(xiàn)象定位到具體環(huán)節(jié)如果問題不是直接報(bào)錯(cuò)而是“日志顯示更新成功但實(shí)際訪問不了”這就要按鏈路拆開排查了。我習(xí)慣按下面的順序逐一排除先確認(rèn)本機(jī)當(dāng)前出口IP是不是真的已經(jīng)變了。直接瀏覽器訪問icanhazip.com這類頁面看看和腳本獲取到的是否一致。如果不一致說明腳本獲取IP這一段出了偏差可能是curl解析到了IPv6優(yōu)先地址或者走了代理。再確認(rèn)域名解析值是否真的更新成腳本日志里的值。在控制臺(tái)解析列表里直接看記錄值如果控制臺(tái)顯示的就是新IP但本機(jī)訪問不通那就是本地DNS緩存還沒過期。用nslookup或者dig指定公共DNS服務(wù)器查詢能看到權(quán)威解析值已經(jīng)生效。最后才是網(wǎng)絡(luò)路徑問題。如果域名解析到的新IP能ping通但對(duì)應(yīng)端口不通多半是家里路由器沒做端口轉(zhuǎn)發(fā)或者設(shè)備防火墻攔截。這個(gè)已經(jīng)不是DNS的范疇了但也常被誤認(rèn)為是腳本更新失敗值得在排查時(shí)提前區(qū)分開。5.3 個(gè)人堅(jiān)持的幾條運(yùn)維習(xí)慣跑這個(gè)動(dòng)態(tài)解析腳本已經(jīng)幾個(gè)月了有幾條小的運(yùn)維習(xí)慣我特別想分享。日志一定要留。很多人的腳本就是一行alidns --method update跑完就算結(jié)束不出問題還好一旦出現(xiàn)“某個(gè)時(shí)間段解析不對(duì)”沒有日志你根本回憶不起來當(dāng)時(shí)發(fā)生了什么。我在腳本里把每次執(zhí)行的時(shí)間、動(dòng)作、結(jié)果都寫進(jìn)日志成本極低排查時(shí)價(jià)值極高。緩存文件和配置文件的路徑盡量固定。我全放在~/.alidns/下面后面做備份也好、遷移機(jī)器也好打包一個(gè)目錄就全帶走了不用到處找配置。定時(shí)任務(wù)的運(yùn)行狀態(tài)也要自己記一筆。cron本身不給你發(fā)成功日志我隔三差五會(huì)tail一眼腳本的日志文件確保它一直在正常巡檢。這個(gè)動(dòng)作習(xí)慣了之后你會(huì)對(duì)家里網(wǎng)絡(luò)的IP變化周期、穩(wěn)定性都有一個(gè)直覺認(rèn)識(shí)以后再做別的自動(dòng)化項(xiàng)目也非常順手。我自己用這套方案之后最大的感受就是很多東西不用過度工程化路由器插件、獨(dú)立容器這些方案各有各的好處但一個(gè)工具加一個(gè)腳本的輕量組合在“保持簡(jiǎn)單、易于維護(hù)”這個(gè)維度上幾乎無敵。alidns順著官方API的絲滑讓整個(gè)動(dòng)態(tài)解析邏輯收斂成一條命令。以后如果再遇到IP變化的問題腳本自己就把活干完了我只需要偶爾打開日志看看它又“默默”更新了幾次僅此而已。最后分享一個(gè)小技巧如果你臨時(shí)想知道當(dāng)前配置指向的IP和域名解析值是否一致直接用一條命令查出來對(duì)比效率最高echo 當(dāng)前出口IP$(curl -s https://ipv4.icanhazip.com) alidns --config ~/.alidns/config.json --method describe兩行輸出放在一起一眼就知道有沒有追平。這套玩法我已經(jīng)跑穩(wěn)很久了省下來的時(shí)間完全可以拿去做別的更有意思的事情。