[記錄點滴]授人以漁,從Tensorflow找不到dll擴充套件到如何排查問題

羅西的思考發表於2020-09-17

[記錄點滴]授人以漁,從Tensorflow找不到dll擴充套件到如何排查問題

0x00 摘要

本文將通過一個經典的 “tensorflow找不到dll” 問題來入手,給大家一個如何找到缺失dll的辦法,進而再分享一個windows上排查問題的好工具(因為大多開發者在windows上開發&在linux上部署,windows還是繞不過)。

0x01 引言

很多朋友在windows上安裝tensorflow之後,第一次執行會遇到如下錯誤:

ImportError: DLL load failed: 找不到指定的模組。

大家第一反應就是去網上搜尋,比如常見的解決辦法是:

  • 執行環境不全,安裝vc_redist.x64.exe即可,比如在tensorflow官方的release note中有提示。
  • 安裝visual studio2017。
  • 由於tensorflow 2.1.0 版本較高,需要安裝 CUDA、cuDNN神經網路加速庫等,直接降版本。
  • ......

很多朋友解決了這個問題就繼續執行tensorflow了,沒有繼續思考這個問題。

其實,絕大多數問題原因是:tensorflow執行環境缺少庫, msvcp140_1.dll, 或者 VCRUNTIME140_1.dll,而vc_redist.x64.exe就是安裝了這個庫,visual studio2017則剛好有執行tensorflow必須的執行時環境。

但是從而有幾個新問題:

  • 如何知道缺少哪個dll?因為我實驗了兩臺電腦,一臺提示缺少msvcp140_1.dll,一臺沒有任何提示,最後發現是缺少VCRUNTIME140_1.dll。
  • 如果新版本tensorflow又缺少其他的dll怎麼辦?
  • 如果其他軟體缺少dll怎麼辦?
  • 如果在windows上遇到其他古怪的問題怎麼辦?

所以我們的終極目標是:

  • 如果某個軟體也出現缺少dll的情況,我們應該有辦法知道缺少哪個dll
  • 如果在windows上遇到其他古怪問題,我們應該知道有什麼工具來幫我們解決。

下面就讓我們解答這兩個問題。

0x02 如何找到缺失的dll

面對缺失的dll,我們的辦法是:祭出 Process Monitor 大招

Process Monitor是一款 Windows 系統和應用程式監視工具,總體來說,Process Monitor相當於Filemon+Regmon,其中的Filemon專門用來監視系統 中的任何檔案操作過程,而Regmon用來監視登錄檔的讀寫操作過程。

有了Process Monitor,使用者就可以對系統中的任何檔案和 登錄檔操作同時進行監視和記錄,通過登錄檔和檔案讀寫的變化, 對於幫助診斷系統故障或是發現惡意軟體、病毒或木馬來說,非常有用。

Process Monitor 由優秀的 Sysinternals 開發,並且目前已併入微軟旗下,可靠性自不用說。

2.1 Process Monitor可以捕獲哪些事件?

Process Monitor 雖然可以捕獲 Windows 作業系統中的大多數運算元據,但並非抓取每條資訊。它所做的只是獲得特定型別的 I/O(輸入/輸出)操作,其中就包括:檔案系統、網路通訊和登錄檔。當然它還會額外跟蹤其它比較有限幾種事件,例如:

  • 登錄檔:監控登錄檔的建立、讀取、刪除或查詢操作。
  • 檔案系統:監控本地磁碟或網路驅動器中檔案的建立、寫入、刪除等操作。
  • 網路:監控程式的 TCP/UDP 源和目標及流量。
  • 程式:可以被動監控程式和執行緒的活動,包括執行緒的啟動或退出等。不過通常情況下我們都使用 Process Explorer 來監控程式。
  • 效能分析:Process Monitor 還可以捕獲程式的 CPU 時間和記憶體使用,通常情況下這些資訊我們也主要依賴 Process Explorer 來監控分析。

總的來說,Process Monitor 可以捕獲和監控 Windows 中的 I/O 操作,雖然它不記錄實際對登錄檔、檔案系統或網路傳輸中的資料,但我們可以監控到程式的所有操作事件

2.2 Process Monitor預設列

Process Monitor 的預設列中顯示了微軟認為對使用者最為有用的常用資訊,其中從左到右分別為:

  • Time:此列對應每行,顯示該事件發生的精確時間
  • Process Name:此列顯示的為生成該事件的程式名稱,預設該列只顯示程式所對應的 exe 檔名稱,如果將滑鼠指向某個程式名則會懸浮顯示該 exe 在磁碟中的具體路徑。
  • PID:這個不用多說吧,就是程式 ID
  • Operation:該列記錄的是該事件中所執行的操作名稱,主要匹配對登錄檔、檔案、網路和程式的操作。
  • Path:此列記錄的是此事件操作路徑,非程式的路徑。例如:WriteFile 事件在此路徑中記錄的是操作的檔案或資料夾路徑,如果是登錄檔事件則會記錄所操作的註冊路徑。
  • Result:此列記錄的為該事件操作結果,主要狀態有SUCCESS(成功)或ACCESS DENIED(訪問拒絕)等。
  • Detail:此列記錄一些事件操作的額外細節資訊,通常不對排錯起太大意義。

當然,以上這些列只為 Process Monitor 提供的預設列,如果你覺得不夠的話可以在列名上右鍵 — 選擇 Select Columns 來自定義選擇所需的列。

2.3 排查過程

下文的實驗環境是缺少msvcp140_1.dll,我們假設沒有提示dll檔名字。因為因為我實驗了兩臺電腦都安裝同樣版本tensorflow,一臺提示缺少msvcp140_1.dll,一臺沒有任何提示,最後發現是缺少VCRUNTIME140_1.dll。

2.3.1 實驗程式碼

import tensorflow as tf
print(tf.version)

錯誤如下:

File "C:\Users\xxx\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow\python\platform\self_check.py", line 61, in preload_check
    % " or ".join(missing))
ImportError: Could not find the DLL(s) 'msvcp140_1.dll'. TensorFlow requires that these DLLs be installed in a directory that is named in your %PATH% environment variable. You may install these DLLs by downloading "Microsoft C++ Redistributable for Visual Studio 2015, 2017 and 2019" for your platform from this URL: https://support.microsoft.com/help/2977003/the-latest-supported-visual-c-downloads

2.3.2 初步上手

開啟 Process Monitor,我們可以看到有很多python.exe的事件

2.3.3 篩選Process Monitor資料

我們可以用非常顆粒化的過濾器來篩選 Process Monitor 所捕獲的事件,這非常有利於我們對單個程式所生成的事件進行分析。例如當我們只關心 python.exe 所生成的事件時,只需將其過濾出來即可。

當我們選擇 include ‘python.exe’ 之後,介面中則會只篩選出 python.exe 進行的相關事件。

我們這時候發現,現在事件分為兩種:

  • 對登錄檔的操作。
  • 對檔案系統的操作。

對於我們這個例子來說,登錄檔操作沒啥意義,所以我們只關心對檔案系統的操作。但是這樣事件也太多了,所以我們只篩選出沒有找到檔案的資料,即Result 是 NAME NOT FOUND的事件

2.3.4 Filter

於是我們建立兩個Filter來篩選事件。

一個是指定程式名字是python.exe。

一個是指定Result是NAME NOT FOUND。

建立的filter如下:

結果可以看出來,python.exe 在很多目錄下查詢 msvcp140_1.dll。這就是python在path中所有路徑下查詢這個檔案

2.3.5 檢視單個事件

我們可以雙擊 Process Monitor 中的任意一條事件來檢視其詳細資訊。

雙擊開啟 Event(事件) 標籤,其中將列出該事件的詳細時間、事件型別、事件所執行的操作、操作路徑及事件的執行結果等內容。

當我們切換到 Process(程式) 選項卡之後,則可以看到生成該事件的程式的大量相關資訊。

而在 Stack(堆疊) 標籤中,我們可以檢視到該事件程式的堆疊,通過該選項卡我們可以檢查任何不正常的模組。舉個例子,假設某個程式不斷嘗試查詢或訪問不存在的檔案,但我們不知道為什麼會發生這種情況。此時,便可以通過檢視 Stack(堆疊) 標籤來檢視是否有任何不正常的模組。

2.3.6 總結

現在我們知道是python.exe 在很多目錄下查詢 msvcp140_1.dll。我們就可以去網上搜尋這個dll,直接拷貝到系統目錄下即可。

同時我們也初步瞭解瞭如何通過 Process Monitor 來查詢一個缺失的dll。

0x03 Linux下怎麼辦?

3.1 Linux 版本

可能有人會問,在windows下有process monitor可以監控各種事件,那麼在linux下如果有類似需求,我應該如何處理?

微軟貼心的提供了一個Linux版本,而且開源了 https://github.com/Microsoft/Procmon-for-Linux

其簡介是:

Process Monitor (Procmon) is a Linux reimagining of the classic Procmon tool from the Sysinternals suite of tools for Windows. Procmon provides a convenient and efficient way for Linux developers to trace the syscall activity on the system.

但是這個就不是綠色版本了,而是需要自己編譯安裝。

3.2 用法舉例

具體用法舉例如下:

  • 跟蹤系統所有程式和系統呼叫
sudo procmon
  • 跟蹤程式號10和20的程式
sudo procmon -p 10,20
  • 只跟蹤程式號為20的程式的如下系統呼叫: read, write and openat
sudo procmon -p 20 -e read,write,openat
  • 跟蹤程式35,並且把所有事件輸出到procmon.db
sudo procmon -p 35 -c procmon.db

3.3 螢幕示例

具體螢幕示例如下:

目前為止,我們知道了如何排查dll缺失。但是在windows上如果遇到了其他古怪問題,我們應該怎麼處理呢?下面我們繼續瞭解一個排查神器。

0x04 一個給力的排查神器

下面文字幾乎都摘錄 SysInternals系列:什麼是SysInternals工具集 這個系列。

4.1 SysInternals

我們之前提到Process Monitor 屬於SysInternals,那麼我們下面為大家推薦的排查神器就是SysInternals套件

SysInternals 工具集最早由大牛 Mark Russinovich 開發,它是一套完全免費的 Windows 工具套件,其官方網站為 www.SysInternals.com 。由於已經於 2006 年被微軟收購,Mark 也已經出任 Aazure CTO,訪問網址時會直接跳轉到 Technet 的 SysInternals 主頁。

該工具集在平常的維護和排錯工作中經常都會用到,微軟的 Troubleshooting 團隊也會經常使用該工具集中的工具。正是由於其強大的功能和便利性,被微軟收購也不足為奇了。SysInternals 工具集的工具有很多,大概涵蓋了如下的幾個型別:

  • 檔案和磁碟工具
  • 網路工具
  • 程式工具
  • 安全工具
  • 系統資訊工具
  • 其它型別工具

Sysinternals 套件可以免費從微軟 Technet 網站下載,而且都是綠色版無需安裝,大家可以放到 U 盤中隨身攜帶,非常方便。

4.2 功能簡介

因為大家不是專業的windows運維,所以只要快速瀏覽,大概知道此神器有哪些功能,遇到問題時候知道搜尋什麼關鍵字即可。最重要的是知道有這個神器,知道搜尋什麼內容

4.2.1 Process Explorer

Process Explorer 是一個類似於工作管理員和資源監視器的應用,它自 2001 年首次釋出以來歷經了 Windows 9x 至支援 Windows 10 的各種 Windows 版本,目前微軟還在不斷的更新和改進,是我們日常處理故障和排錯的必備利器。

下面列舉了 Process Explorer 一些常用功能及特性清單,有許多非常有用的功能都掩藏在其不起眼的介面之下,很多時候一個很小的功能和特性就能夠幫我們在排錯時少走彎路和節約時間,大家一定要用心去發覺。

  • 它預設以程式樹的方式顯示程式及子程式之間的關係(可開關)且以顏色進行區分讓人一目瞭然
  • 非常精確的 CPU 佔用顯示
  • 提供替代工作管理員的選項,在 Windows XP/7/Vista/8/10 中都非常有用
  • 可以工作列托盤圖示的方式監視 CPU、磁碟、GPU 和 網路等的使用情況
  • 檢視程式載入了哪些 DLL
  • 檢視程式開啟或鎖定了哪些檔案或資料夾
  • 檢視任何程式的完整資訊,包括:執行緒、記憶體佔用、控制程式碼、物件和其它幾乎任何你想知道的內容
  • 可以直接 Kill 掉整個程式樹
  • 可以將程式掛起(暫停),凍結其所有執行緒
  • 強大到可以檢視執行緒的CPU使用率
  • 從 v16 版本開始整合了VirusTotal,可以快速驗證是否是病毒

4.2.2 PsTools

PsTools 可以幫助我們在命令列中執行相當多的管理任務,更主要的是可以將其寫成指令碼來執行週期性重複任務或在管理大批量伺服器時提高效率。

作為 Sysinternals 工具包中的一個子集,PsTools 本身就有十來個命令列小工具,下面我們會逐個為大家進行介紹:

  • PsExec – 在遠端計算機執行命令
  • PsFile – 檢視開啟的網路檔案
  • PsGetSid – 獲取 Machine SID
  • PsInfo – 檢視簡要系統資訊
  • PsKill – 按程式名或PID殺掉程式
  • PsList – 列出程式資訊
  • PsLoggedOn – 顯示已登的會話
  • PsLogList – 命令列獲取 event log
  • PsPasswd – 更改使用者密碼
  • PsPing – 簡單的tcp/udp連線測試工具
  • PsService – Windows 服務管理命令
  • PsShutdown – 關機、登出命令
  • PsSuspend – 暫停或恢復某個程式

以上所有命令都可以直接在本地計算機上使用。

4.2.3 TCPView

TCPView 是用於檢視當前 Windows 應用程式和服務連網狀態的絕佳工具,通過它我們可以在圖形介面中檢視到類似使用 netstat 命令輸出的大部分資訊。

4.2.4 ListDlls

與 Process Explorer 的功能類似,ListDlls 主要用於顯示程式載入的 DLL 檔案,當然 Process Explorer 更直觀易用。

4.2.5 RamMap

RamMap 工具主要用於分析實體記憶體的使用情況,它以視覺化的圖形介面進行輸出顯示。在 RamMap 介面中,你可以檢視到非常詳細的記憶體用量,例如:空閒記憶體、頁面緩衝池、非頁面緩衝池、已提交和已快取等條目的詳細情況,比工作管理員中的記憶體顯示強大多了。

4.2.6 Handle

Handle 命令列工具的功能其實在 Process Explorer 中也有,使用它可以快速找出程式所開啟的資源控制程式碼。

4.2.7 Autologon

Autologon 就是可快速實現 Windows 自動登入的第三種工具。

4.2.8 RegJump

RegJump 命令列工具可以很快在登錄檔樹狀條目中進行定位(完全支援簡寫)

4.2.9 ShellRunAs

ShellRunAs 命令列工具其實是一個 Shell 擴充套件應用,它可以讓我們快速以不同使用者身份來執行應用。

4.2.10 AccessEnum

AccessEnum 是在做資料夾許可權排錯時最常用的一個工具,在我們對某個資料夾進行過複雜的許可權配置後,AccessEnum 工具可以非常容易幫助我們理清資料夾或登錄檔的最終訪問控制列表。

4.2.11 Streams:檢視和顯示隱藏的NTFS流

大多數使用者都不瞭解,Windows 其實會隱藏部分儲存在檔案系統中的資料,被稱為「備用資料流」,只有在檔名末尾追加冒號和獨特的金鑰才能與之進行互動。

Streams可以幫助大家檢視指定檔案已有的全部「備用資料流」

4.2.12 SigCheck:分析未經數字簽名的檔案(如惡意軟體)

SigCheck 也是可以幫助我們分析檔案是否擁有數字簽名的一個命令列工具。它還可以從 VirusTotal 進行檢查,以方便我們找出惡意軟體。

4.2.13 SDelete:安全刪除檔案

大家都知道,在 Windows 中刪除檔案都不是直接清除,而是在硬碟中標記為已刪除,SDelete 命令列工具可以幫助我們將硬碟中已經刪除檔案部分填充無意義資料以達到抹除的目的。

4.2.14 Contig:整理一個或多個檔案

如果你想只對 Windows 中的一個或幾個檔案進行磁碟碎片整理,可以使用 Contig 命令列工具

4.2.15 du:檢視磁碟用量

相信大家最常用 Windows 資源管理器來檢視磁碟空間和資料夾大小,而 du 是 Sysinternals 套件中的命令列磁碟和資料夾大小檢視工具。

4.2.16 Junction:建立符號連結

Windows 與 Linux 一樣支援檔案和資料夾的符號連結,Sysinternals 工具包中的 Junction 命令也可用於建立和刪除符號連結。

4.2.17 DiskView:顯示磁碟結構

DiskView 小工具可以讓你以圖形介面的方式檢視詳細的磁碟驅動器結構並可以放大和縮小顯示區塊,甚至可以選擇某個檔案之後檢視其在磁碟中儲存的位置。

4.2.18 MoveFiles:重啟時移動系統檔案

大家有沒想過為什麼在 Windows Update 之後或安裝某些應用程式之後會要求重啟系統?因為在 Windows 執行時,有些檔案(特別是系統檔案)是不能隨便被移來移去功隨意替換掉的。movefile 命令列小工具可以呼叫 Windows 自身的功能幫助我們在 Windows 下次重啟時移動、刪除或重新命名檔案或目錄

4.2.19 FindLinks:查詢硬連結檔案

前面既然提到了 Junction 建立符號連結,就不得不提一個 findlinks 這個 Sysinternals 是用於檢視檔案硬連結的命令列工具。如果有多個硬連結指向同一檔案,在刪除最後一個硬連結時就會將檔案直接刪除,因此大家可用 findlinks 工具進行檢視和關注。

4.2.20 Disk2vhd:物理磁碟轉換VHD虛擬磁碟

Disk2vhd 小工具可將正在執行計算機的磁碟克隆成 VHD 虛擬磁碟檔案,因此它也成為不少虛擬化專案中的 P2V 轉換工具。

0xFF 參考

病毒分析(三)-利用Process Monitor對熊貓燒香病毒進行行為分析

利用Process Monitor軟體解決無法載入DLL檔案的問題

SysInternals系列:什麼是SysInternals工具集

SysInternals系列:使用Sysmon將監控事件寫入系統日誌

SysInternals系列:其它常用工具介紹

SysInternals系列:使用PsTools工具執行本地/遠端PC管理任務

SysInternals系列:分析管理檔案、資料夾和驅動器

SysInternals系列:Windows啟動項管理利器Autoruns

Process Explorer:Windows程式管理及排錯利器(上)

Process Explorer:Windows程式管理利器常用功能(中)

Process Explorer:診斷和排錯例項(下)

Process Monitor:Windows事件監控利器簡介(上)

Process Monitor:Windows事件監控常用功能(中)

Process Monitor:Windows事件監控例項(下)

Process Monitor(簡稱Procmon)釋出Linux版,附使用方法

https://github.com/microsoft/ProcMon-for-Linux

相關文章