我想用我的Raspberry Pi來記錄一系列傳感器的溫度。爲此,我正在編寫一個使用librrd的C++程序。使用C++在Raspberry上創建RRD文件的行爲很奇怪
對於每個連接的傳感器,我想創建一個12 rra的rrd。下面的調用應創造我想要的RRD:
rrd_create(mNumberOfCreateParams, mCreateParams);
mNumberOfCreateParams是17和mCreateParams的內容如下:
rrdcreate
28-000005fd934f.rrd
--step=300
--no-overwrite
DS:temperature:GAUGE:600:-55:125
RRA:AVERAGE:0.5:1:288
RRA:AVERAGE:0.5:3:672
RRA:AVERAGE:0.5:12:744
RRA:AVERAGE:0.5:72:1464
RRA:MAX:0.5:1:288
RRA:MAX:0.5:3:672
RRA:MAX:0.5:12:744
RRA:MAX:0.5:72:1464
RRA:MIN:0.5:1:288
RRA:MIN:0.5:3:672
RRA:MIN:0.5:12:744
RRA:MIN:0.5:72:1464
第二行對應的傳感器的ID每次都有改變。
現在的問題:有一段時間,對rrd_create的調用按預期工作,但在某些時候它停止工作,只是在進一步調用時創建錯誤。如果我想重新創建一個之前成功創建的rrd,這也是如此。
通過改變mNumberOfCreateParams我可以改變分析參數的數量。如果參數在13到17的範圍內,則rrd_get_error()返回的錯誤是「無法解析參數''」(爲了可讀性,在兩者之間增加了空格)。如果我讓函數解析10到12個參數,它將在第一次「工作」並返回「打開'@':沒有這樣的文件或目錄」第二次因爲第一次創建以下文件:
image of created file in file browser
如果解析參數的數量低於10,則按預期工作。
如果我改變RRA線的順序,沒有任何區別。
如果我打電話給rrdtool,從終端創建[...與上面相同的參數],那麼一切工作正常,無關緊要,多少個參數被解析。
爲了rrd_create再次工作,我重新啓動了Raspberry serveral時間,它甚至在短時間內運行了一次(我的應用程序運行一次)。
有什麼建議我做錯了什麼,或者我如何將rrd_create移動到更穩定的狀態?
編輯: 我正在使用版本1.4.7的RRDtool(shell中的rrdtool版本)。 這裏是我使用的用於創建RRD文件的代碼:
// mCreateParams & mNumberOfCreateParams will be set here
setupRrdCreateParamsDS18B20(lStepSize);
char lCurrentPath[255];
getcwd(lCurrentPath, sizeof(lCurrentPath));
// since I wasn't able to create rrd files outside current working directory I
// change working directory to where I want all files
chdir(DS18B20_PATH.c_str());
// the dump of mCreateParams postet above was created here
int lStatus = rrd_create(mNumberOfCreateParams, mCreateParams);
因爲我只是打電話rrd_create(......)我覺得他們不應該被破壞之前傾倒mCreateParams。
我目前的解決方法使用popen()和mCreateParams用於創建調用rrdtool的shell命令。
stringstream ss;
// create shell command from create params
ss << "rrdtool create ";
for (int i = 1; i < mNumberOfCreateParams - 1; i++) {
ss << mCreateParams[i] << " ";
}
ss << mCreateParams[mNumberOfCreateParams - 1];
// needed for capturing output from executed command
FILE * in;
char buff[512];
if(!(in = popen(ss.str().c_str(), "r"))){
return false;
}
ss.str("");
ss.clear();
// get output
while(fgets(buff, sizeof(buff), in)!=NULL){
ss << buff;
}
lRrdError = ss.str();
ss.str("");
ss.clear();
int lTemp = pclose(in);
// get exit code from rrdtool create
lStatus = WEXITSTATUS(lTemp);
我很感謝每一個建議。
您正在使用哪個版本的RRDtool庫?你能發佈你正在使用的實際代碼(或其中的一部分)嗎?在呼叫之前,您的呼叫參數可能會被破壞掉?也許,出於測試目的,在調用之前打印出通過的argv列表來驗證。另外,請確保在調用此函數時不使用線程或類似函數 - 許多調用都不是線程安全的。 最後,你附加的文件沒有正確完成 - 我只是得到一個二進制文件圖標:) – 2014-08-31 22:29:37
是的,沒錯。它只是創建了一個二進制文件。但據我所見,rrdtool忽略提供的文件名。 – Nazrim 2014-09-01 01:08:13