最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如何使用Swift來實現(xiàn)一個命令行工具的方法

 更新時間:2020年05月15日 14:30:57   作者:超越楊超越  
這篇文章主要介紹了如何使用Swift來實現(xiàn)一個命令行工具,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

本文即簡單介紹了如何在Swift中開發(fā)命令行工具,以及與Shell命令的交互。水文一篇,不喜勿噴。

主要是使用該工具來解析微信的性能監(jiān)控組件Matrix的OOM Log。

基本模塊

這里,僅簡單介紹了常見的基本模塊。

Process

Process類可以用來打開另外一個子進程,并監(jiān)控其運行情況。

  1. launchPath:指定了執(zhí)行路徑。如可以設置為 /usr/bin/env ,這個命令可以用于打印本機上所有的環(huán)境變量;也可以用于執(zhí)行shell命令,如果你接了參數(shù)的話。本文的Demo就用它來執(zhí)行輸入的命令。
  2. arguments:參數(shù),以數(shù)組形式傳遞即可。
  3. launch:調用launch函數(shù)即可啟動process,用于執(zhí)行命令。
  4. waitUntilExit:一般執(zhí)行Shell命令,需要等待命令返回。
  5. terminationStatus:當前process的結束狀態(tài),正常為0.
  6. standardOutput:standardOutput對應于終端的標準輸出。standardError則是錯誤輸出。

Pipe

Pipe這個類就是操作系統(tǒng)的管道,在這里用來接受子進程的輸出。這里,可以用于將process的輸出傳遞至管道指定的地方,如一個output變量,或者文件也可以。

  • fileHandleForReading:pipe從哪里讀取內容?
  • fileHandleForWriting:pipe將內容寫到哪里?

CommandLine

用于獲取腳本參數(shù)而已。

print(CommandLine.argc) // 2
print(CommandLine.arguments) // ["./test.swift", "hello"]

封裝Shell命令

僅執(zhí)行Shell命令

這里提供了兩種調用Shell命令的封裝函數(shù),個人更傾向于第二種,直接將Shell命令及參數(shù)封裝成一個字符串傳入即可。

@discardableResult
func runShell(_ command: String) -> Int32 {
 let task = Process()
 task.launchPath = "/bin/bash"
 task.arguments = ["-c", command]
 task.launch()
 task.waitUntilExit()
 return task.terminationStatus
}

@discardableResult
func runShellWithArgs(_ args: String...) -> Int32 {
 let task = Process()
 task.launchPath = "/usr/bin/env"
 task.arguments = args
 task.launch()
 task.waitUntilExit()
 return task.terminationStatus
}

使用如下:

runShell("pwd")
runShell("ls -l")

runShellWithArgs("pwd")
runShellWithArgs("ls", "-l")

需要Shell命令的輸出內容

這里就需要使用到Pipe了。

@discardableResult
func runShellAndOutput(_ command: String) -> (Int32, String?) {
 let task = Process()
 task.launchPath = "/bin/bash"
 task.arguments = ["-c", command]
 
 let pipe = Pipe()
 task.standardOutput = pipe
 task.standardError = pipe
 
 task.launch()
 
 let data = pipe.fileHandleForReading.readDataToEndOfFile()
 let output = String(data: data, encoding: .utf8)
 
 task.waitUntilExit()
 
 return (task.terminationStatus, output)
}

@discardableResult
func runShellWithArgsAndOutput(_ args: String...) -> (Int32, String?) {
 let task = Process()

 task.launchPath = "/usr/bin/env"
 task.arguments = args
 
 let pipe = Pipe()
 task.standardOutput = pipe
 task.standardError = pipe
 
 task.launch()
 
 let data = pipe.fileHandleForReading.readDataToEndOfFile()
 let output = String(data: data, encoding: .utf8)
 
 task.waitUntilExit()
 
 return (task.terminationStatus, output)
}

使用如下:

let (ret1, output1) = runShellAndOutput("ls -l")
if let output11 = output1 {
 print(output11)
}

let (ret2, output2) = runShellWithArgsAndOutput("ls", "-l")
if let output22 = output2 {
 print(output2)
}

如何解析Matrix的OOM Log

Matrix的OOM Log格式如下,其實就是一個大JSON:

{
 "head": {
  "protocol_ver": 1,
  "phone": "iPhone10,1",
  "os_ver": "13.4",
  "launch_time": 1589361495000,
  "report_time": 1589362109100,
  "app_uuid": ""
 },
 "items": [
  {
   "tag": "iOS_MemStat",
   "info": "",
   "scene": "",
   "name": "Malloc 12.54 MiB",
   "size": 146313216,
   "count": 1,
   "stacks": [
    {
     "caller": "f07199ac8a903127b17f0a906ffb0237@84128",
     "size": 146313216,
     "count": 1,
     "frames": [
      {
       "uuid": "a0a7d67af0f3399a8f006f92716d8e6f",
       "offset": 67308
      },
      {
       "uuid": "a0a7d67af0f3399a8f006f92716d8e6f",
       "offset": 69836
      },
      {
       "uuid": "f07199ac8a903127b17f0a906ffb0237",
       "offset": 84128
      },
      {
       "uuid": "b80198f7beb93e79b25c7a27d68bb489",
       "offset": 14934312
      },
      {
       "uuid": "1a46239df2fc34b695bc9f38869f0c85",
       "offset": 1126304
      },
      {
       "uuid": "1a46239df2fc34b695bc9f38869f0c85",
       "offset": 123584
      },
      {
       "uuid": "1a46239df2fc34b695bc9f38869f0c85",
       "offset": 1135100
      }]
    }
   ]
  }
 ]
}

解析的思路其實非常簡單,將JSON轉為Model,然后根據所需,提取對應的信息即可。

uuid是mach-o的唯一標識,offset則是符號相對于mach-o基地址的偏移量。拿到dSYM文件,使用 atos 命令即可進行符號化。

guard let rawLogModel = MatrixOOMLogParser.parse() else { exit(-1) }
print("______ Start to process Matrix OOM Log ...")

let group = DispatchGroup()

var metaLog = ""

for item in bodyInfo.items {
 guard let stacks = item.stacks else { continue }
 
 group.enter()
 
 DispatchQueue.global().async {
  var log = "______ item ______ name: \(item.name), size: \(item.size), count: \(item.count) \n"
  metaLog += log
  
  for stack in stacks {
   let outputs = stack.frames.map({ (frame: MatrixOOMLogModelFrame) -> String in
    // let uuid = frame.uuid
    let offset = frame.offset
    let instructionAddress = loadAddress + offset
    let (_, output) = runShellAndOutput("xcrun atos -o \(dwarf) -arch arm64 -l 0x1 \(instructionAddress.hexValue)")
    return output ?? ""
   })
   
   log += outputs.joined()
   
   print(log)
  }
  
  group.leave()
 }
}

group.wait()

print("\n\(metaLog)\n")

print("______ Finished processing Matrix OOM Log ...")

MatrixOOMLogParser.parse() 就是將JSON轉為Model,這里用的就是Swift里邊的Codable。

這里有一個需要注意的點,Mac CLI沒有Bundle的概念,只有一個bin文件。所以對于原始的JSON文件,只能通過外部bundle的方式來添加。通過 New->Target 單獨建立一個bundle。需要在 Xcode -> Build Phases -> Copy Files 中添加該bundle名,然后即可通過 Bundle(url: mockDataBundleURL) 來加載該bundle并獲取其中的log文件了。

因為atos的執(zhí)行時間較長,所以大量的符號化操作會非常耗時。一般來說,這段代碼執(zhí)行六七分鐘左右,可以將一個Matrix的OOM Log完全符號化。而符號化之后的記錄如何分析,就是另外一個話題了。

參考資料

How do I run an terminal command in a swift script? (e.g. xcodebuild)

到此這篇關于如何使用Swift來實現(xiàn)一個命令行工具的文章就介紹到這了,更多相關Swift 命令行內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家! 

相關文章

  • RxSwift實現(xiàn)替換delegate的方法示例

    RxSwift實現(xiàn)替換delegate的方法示例

    這篇文章主要給大家介紹了關于RxSwift實現(xiàn)替換delegate的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用RxSwift具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-09-09
  • 使用?Swift?Package?插件生成代碼的示例詳解

    使用?Swift?Package?插件生成代碼的示例詳解

    這篇文章主要介紹了使用?Swift?Package?插件生成代碼,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08
  • 淺談Swift編程中switch與fallthrough語句的使用

    淺談Swift編程中switch與fallthrough語句的使用

    這篇文章主要介紹了Swift編程中switch與fallthrough語句的使用,用于基本的流程控制,需要的朋友可以參考下
    2015-11-11
  • Swift中圖片資源使用流程的優(yōu)化方法詳解

    Swift中圖片資源使用流程的優(yōu)化方法詳解

    這篇文章主要給大家介紹了關于Swift中圖片資源使用流程的優(yōu)化方法的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2018-01-01
  • Swift中 !和 ?的區(qū)別及使用

    Swift中 !和 ?的區(qū)別及使用

    這篇文章主要介紹了Swift中 !和 ?的區(qū)別及使用的相關資料,需要的朋友可以參考下
    2016-12-12
  • Flutter iOS開發(fā)OC混編Swift動態(tài)庫和靜態(tài)庫問題填坑

    Flutter iOS開發(fā)OC混編Swift動態(tài)庫和靜態(tài)庫問題填坑

    這篇文章主要為大家介紹了Flutter iOS OC 混編 Swift動態(tài)庫和靜態(tài)庫問題填坑詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • RxSwift學習教程之基礎篇

    RxSwift學習教程之基礎篇

    RxSwift是Swift函數(shù)響應式編程的一個開源庫,由Github的ReactiveX組織開發(fā),維護。下面這篇文章主要給大家介紹了關于RxSwift學習之基礎篇的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-09-09
  • Swift之UITabBarController 導航控制器的自定義

    Swift之UITabBarController 導航控制器的自定義

    本文給大家介紹swift導航控制器之UITabBarController,本文通過代碼實例給大家講解swift導航控制器,導航控制器類繼承UITabBarController,代碼簡單易懂,需要的朋友可以參考下
    2015-10-10
  • RxSwift學習之Observable的新建、訂閱及取消訂閱

    RxSwift學習之Observable的新建、訂閱及取消訂閱

    這篇文章主要給大家介紹了關于RxSwift學習教程之Observable的相關資料,文中詳細的給大家介紹了關于新建Observable、訂閱Observable和取消訂閱并消除內存泄漏等相關的內容,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-09-09
  • Swift中defer的正確使用方法

    Swift中defer的正確使用方法

    準備把 swift 文檔再掃一遍,發(fā)現(xiàn)了defer這個關鍵字,所以下面這篇文章主要給大家介紹了關于Swift中defer的正確使用方法,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2018-11-11

最新評論

大庆市| 麦盖提县| 江源县| 滦南县| 河西区| 澄江县| 榆林市| 华池县| 大埔区| 博客| 凌海市| 苍山县| 潍坊市| 安图县| 龙泉市| 铁岭县| 晴隆县| 漳州市| 额敏县| 乳源| 徐闻县| 西峡县| 梧州市| 兴国县| 平凉市| 河西区| 珠海市| 名山县| 孝义市| 平阴县| 崇文区| 钦州市| 平利县| 绥化市| 微博| 通化县| 双牌县| 松原市| 衢州市| 杂多县| 昌平区|