1. 程式人生 > >重定向 NSLog 輸出到檔案

重定向 NSLog 輸出到檔案

問題:

在 iOS 的開發過程中總是離不開 Debug,除錯的時候都是依靠 XCode log 輸出來追蹤確定問題。

但如果離開了 XCode 的時候仍然想看到日誌的輸出,比如在除錯 App 與硬體的互動的時候,這時候應該怎麼辦?

解決思路:

方法一:

第一反應是,寫個類似於 NSLog 的輸出函式,把想要的檢視的資訊輸出到 TextView 上就好了。但很快就否決了,原因有2個:

  • 每一個你想要測試的地方都要新增自定列印輸出,程式碼侵入性大,而且 bug 的出現往往在你意想不到的地方
  • 核心程式碼一般都是 C/C++ 寫的,用不了 Cocoa 的框架,想要在 TextView 上打印出日誌,意味著你要把 printf 的 log 一層一層往上傳遞到 Cocoa 層,麻煩!

方法二:

Hook NSLog 和 print 等輸出函式,考慮到 Method Swizzing 方式只能動態替換 OC 方法,對於 C 函式卻無能為力。Google 了一下, 發現 facebook 開源的 fishhook 可以 hook C API 。那麼這樣一來的話就只需要 Hook 常用的幾個輸出就可以了。試了一下確實可以實現,使用fishhook hook NSLog 函式

方法三

深究 NSLog 的呼叫關係

NSlog->_CFLogvEx->0x32262f20

_CFLogvEX 呼叫 
CFStringCreateWithFormatAndArgumentsAux
CFStringGetLength
CFStringGetMaximumSizeForEncoding

進行字串格式化,然後 malloc 一塊記憶體通過 CFStringGetCString 寫入函式 0x32262f20 , 再呼叫 CFAbsoluteTimeGetCurrent 獲得系統時間,CFGetProgname 獲得 mach-o 檔名,getpid 獲得程序 pid

然後,重點來了:

0x32263250 <<redacted>+816>:    movs    r0, #2
0x32263252 <<redacted>+818>:    blx     0x322b541c <dyld_stub_writev>

沒錯,寫入檔案控制代碼 2,也就是 stderr 。(0 是標準輸入,1 是標準輸出,2 是錯誤輸出)

writev 執行完後,可以在 stderr 上看到格式化好的字串。

結論:要獲得 NSLog 輸出的資訊只需要重定向標準輸出 stdout 和錯誤輸出 stderr 即可。其他的輸出函式也是一樣,這樣一來,只需要重定向 stdout 和 stderr 就可以做到把所有的列印日誌輸出到任意地方了,bingo !

解決辦法:

以上 3 中方法中,最有意思的最精簡的為第三種方法,那麼現在就來實現第三種方法。

關於重定向,需要用到 dup2 函式。

int dup2(int oldfd, int newfd);

現在,只需要建立一個檔案,然後將其控制代碼通過函式 dup2 傳入,替換到預設的控制代碼就好了。
int substrateInit()
{
    int fd;
    char pathBuffer[1000];
    char timeBuff[20];
    time_t now = time(NULL);
    strftime(timeBuff, 20, "%Y-%m-%d %H:%M:%S", localtime(&now));
    
    fflush(stdout);
    fflush(stderr);
    snprintf(pathBuffer, sizeof(pathBuffer), "%s/Library/stdout-%s.log", getenv("HOME"), timeBuff);
    setvbuf(stdout,NULL,_IONBF,0);
    fd = open(pathBuffer, (O_RDWR | O_CREAT), 0644);
    if(-1 == fd)
    {
        printf("\n open() failed with error [%s]\n",strerror(errno));
        return -1;
    } else {
        dup2(fd, STDOUT_FILENO);
        dup2(fd, STDERR_FILENO);
        printf("Here is dll init, redirect stdout and stderr to logfile\n");
    }
    
    return 0;
}

開啟 Library/ 目錄下的日誌檔案,日誌全都寫到裡面去了,好好耍去吧~

參考連結:ios NSLog 日誌重定向到檔案中儲存 ,這個只能重定向 NSLog 的,printf 的輸出是捕獲不到的。

相關推薦

定向 NSLog 輸出檔案

問題: 在 iOS 的開發過程中總是離不開 Debug,除錯的時候都是依靠 XCode log 輸出來追蹤確定問題。 但如果離開了 XCode 的時候仍然想看到日誌的輸出,比如在除錯 App 與硬體的互動的時候,這時候應該怎麼辦? 解決思路: 方法一: 第一反應是,寫

Linux shell 輸入/輸出定向—/dev/null檔案

個人分類: Linux/Unix相關 如果希望執行某個命令,但又不希望在螢幕上顯示出輸出的結果,那麼可以將輸出重定向到/dev/null:   $ command > /dev/null /dev/null是一個特殊的檔案,寫入到它的內容都會被丟棄;如果嘗試

Linux命令執行的螢幕輸出內容定向到日誌檔案

摘要: 作者:Syn良子 出處:http://www.cnblogs.com/cssdongl 轉載請註明出處 快速mark一下這個命令細節,免得以後使用又忘記了 大家都知道可以用echo來輸出內容到檔案,比如 echo “hello,word”>> temp.txt 那麼我現在想把hado

Shell中將標準錯誤標準輸出定向到同一個檔案的兩種方式

在Shell中,標準錯誤寫法為 2>, 標準輸出為 1> 或者 >。如要要將標準輸出和標準錯誤合二為一,都重定向到同一個檔案,可以使用下面兩種方式: 方式一: > out.txt 2>&1 [[email protected] ~

定向標準輸出檔案有時看不到檔案的內容

作轉碼測試程式時,將輸出儲存到檔案。開始時可以。 將列印的音、視訊的pts刪除後,就看不到檔案的內容了,還以為是程式出問題了。 查了一下,是緩衝地區的問題。 原來有很多的printf,緩衝地區滿了,就會寫到檔案。 可以使用 fflush(stdout)解決。 也可以用se

Python-1、輸出定向到日誌檔案的例子

1.執行環境:Mac自帶Python2.7 2.使用過程:開啟終端未指定python執行檔案路徑下輸入 Last login: Sat Jan  6 11:22:52 on ttys003 applematoiMac:~ apple$python Python 2.7

shell指令碼檔案定向讀取.csv檔案輸出SQL Insert語句

檔案重定向常見於指令碼需要讀入檔案和輸出檔案時。這個樣例指令碼兩件事都做了。它讀取.csv 格式的資料檔案,輸出SQL INSERT語句來將資料插入資料庫。 shell指令碼使用命令列引數指定待讀取的.csv檔案。.csv格式用於從電子表格中匯出資料,所以 你可以把資料庫資料放入電子表格中,把電子表

Qt:定向QDebug輸出檔案,並附上日期

介紹 程式碼比較簡單,就是一個函式,在main中呼叫即可 函式申明 void setDebugOutput(const QString &targetFilePath, const bool &argDateFlag = false

nohup 後臺執行,以及定向標準輸出和標準錯誤 &/dev/null 檔案

具體的命令我就不介紹了, 一般都是在linux下 nohup command_line 或者 nohup command_line & 這之間的差別是帶&的命令列,即使terminal關閉,或者電腦宕機程式依然執行(前提是你把程式遞交到伺服器上); 它把標準輸出(STDOUT)和標準錯誤(S

在python中如何定向標準輸出stdout到檔案程式碼示例

import sys oldStdout = None logfile = None try: logfile = open('d:/1.log','w+') oldStdout = sys.stdout sys.stdout = logfile print 'H

python 檔案輸出定向輸出的內容會在記憶體中暫存,不會立刻輸出檔案

1、使用write寫磁碟檔案 python 中使用write,將資料寫入到檔案中,但是並不是write之後,就立刻寫入到檔案(比如a.txt)中,python的write會先將資料放在記憶體的緩衝區中,等到積累了一定的量,再一起寫入到磁碟檔案中。這樣可以提高效能,減少訪問磁

定向輸入輸出

錯誤 command stdout 重定向 dev 追加 文件 out 情況下 cat 1.txt >2.txt 將讀取1.txt的標準輸出重定向輸出到2.txtcat 1.txt >>2.txt 將讀取1.txt的標準輸出追加輸出到2.txtcat 1.

python 通過 subprocess 執行命令,定向實時輸出

out www. stdout err stderr class 解碼 Coding ces 環境:python 3.6 下面的例子,通過 subprocess 執行命令,重定向並實時輸出,可修改重定向到文件或其他。 (註意:例子只適用於,遇到錯誤就停止執行的命令。

linux系統shell中定向 標準輸出 錯誤輸出 >/dev/null 2>&1

經常shell指令碼中,會看到: 仔細體會下面例子。 >/dev/null  2>&1 這句話的意思簡單理解為:標準輸出和錯誤輸出都不會輸出出來。 [email protected]:/tmp>date>1.txt >/de

[譯]如何將docker日誌定向到單個檔案

原文來源: how-to-redirect-docker-logs-to-a-single-file 問題: 我想把某一個docker的log全部匯出到一個檔案裡進行分析,我該怎麼做? 其實不用那樣操作,Docker預設把所有的日誌存在一個log檔案裡面。你可以通過以下命令檢視docker對應log的地址:

SpringMVC篇:轉發與定向、圖片檔案上傳、Json(jackson)

注意: 專案:war 和 專案:war  exploded 兩者並不同,idea  執行 專案:war  exploded   <dependency> <groupId>org.

檔案定向(採用檔案過濾驅動實現)

Windows的I/O管理器提供了一個方便的方法來重定向一個檔案物件。通常使用檔案過濾驅動(在檔案開啟和檔案建立的操作中)實現該方法。操作方法如下:1、在IRP_MJ_CREATE的分發函式中,獲得FILE_OBJET的FileName屬性。2、用目標檔案的完整路徑替換原有的

使用ifstream ofstream定向輸入輸出 c++

//使用ifstream和ofstream及cin和cout的rdbuf() #include <iostream> #include <fstream> using namespace std; int main() { printf(" 使

Linux定向到文字檔案遇到的詭異問題

想把 service iptables status 的資訊重定向到文字檔案info.txt中, 我嘗試了 1.  service iptables status 2>&1 >&nb

shell中的定向(輸入輸出)

shell中的重定向(輸入輸出) Linux 命令預設從標準輸入裝置(stdin)獲取輸入,將結果輸出到標準輸出裝置(stdout)顯示。一般情況下,標準輸入裝置就是鍵盤,標準輸出裝置就是終端,即顯示器。 輸出重定向 命令的輸出不僅可以是顯示器,還可以很容易的轉移向到檔案,這被稱為輸出重定向。